Tomcat +jndi.properties - java

i have a problem with JNDI in Tomcat:
without tomcat I have used JNDI as following:
Context context = new InitialContext();
JVoiceXml jvxml = (JVoiceXml) context.lookup("JVoiceXml");
And jndi.properties :
java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
java.naming.provider.url=rmi://localhost:1099
java.naming.rmi.security.manager=true
Now I want to use this code in my Web Application(deployed with Tomcat), I have changed the code to:
Context context = new InitialContext();
Context envCtx = (Context) context.lookup("java:comp/env");
JVoiceXml jvxml = (JVoiceXml) envCtx.lookup("JVoiceXml");
In web.xml:
<resource-env-ref>
<resource-env-ref-name>
JVoiceXml
</resource-env-ref-name>
<resource-env-ref-type>
org.jvoicexml.JVoiceXml
</resource-env-ref-type>
</resource-env-ref>
And in context.xml:
<Resource name="JVoiceXml" auth="Container"
type="org.jvoicexml.JVoiceXml"
factory="com.sun.jndi.rmi.registry.RegistryContextFactory"
url="rmi://localhost:1099"/>
What I have missed, because after lookup() my JVoiceXml is null

Your Tomcat code is not equivalent to what you wrote outside Tomcat. All you've done in the Tomcat case is name an RMI Registry context factory as JVoiceXML. That doesn't seem to make sense: the RMI Registry has nothing to do with XML. I suspect you don't need the java:comp/env stuff at all here. Presumably you have an RMI Registry running somewhere: just look it up with Naming.lookup(). If you want it to act as a Tomcat Resource, you need to define a factory that can create it. That needs to be an instance of javax.naming.spi.ObjectFactory (?). That may in turn do a Naming.lookup(), or a JNDI lookup, outside the java:comp/env namespace.

Related

Working with DataSource, JNDI API in IntelliJ

I'm trying to understand establishing a database-connection with a DataSource Object and the JNDI API.
I'm working with Intellij UE and have a local Tomcat-8- and Postgres-Server running.
I proceed as mentioned in the Oracle Java Documentation:
Creating Instance of DataSource Class and Setting its Properties
org.postgresql.ds.PGSimpleDataSource dataSource = new org.postgresql.ds.PGSimpleDataSource();
dataSource.setServerName("localhost");
dataSource.setDatabaseName("db01");
dataSource.setUser("jwi");
dataSource.setPassword("password");
Registering DataSource Object with Naming Service That Uses JNDI API
Context ctx = null;
try {
ctx = new InitialContext();
ctx.bind("jdbc/localDB", dataSource);
} catch (NamingException e) {
e.printStackTrace();
}
The Oracle Documentation says:
With the properties set, the system administrator can register the BasicDataSource object with a JNDI (Java Naming and Directory Interface) naming service.
So my first Question is: What means to register a DataSource? Is my code obove already the registration of an DataSource Object to JNDI?
Using Deployed DataSource Object
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/localDB");
dbCon = ds.getConnection();
...
In this code cutting IntelliJ always claims, that it can't resolve the method getConnection().
The Oracle Documentation says:
After a basic DataSource implementation is deployed by a system administrator, it is ready for a programmer to use.
So my second Question is: What exactly means deployed in this case? Creating a DataSource Instance and execute the registration with JDNI? Or does deployed mean the Tomcat context.xml and web.xml configuration (Tomcat 8 JNDI How-To)?
I'd really appreciate if anybody has a good step by step instruction for this issue, in fact that the Oracle Documentation isn't really clear about some points imho.
for the second question, deployed means that your datasource is declared in the context.xml in tomcat.
Here is an example of an oracle database (you have to change the driver for postgres) :
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#127.0.0.1:1521:mysid"
username="scott" password="tiger" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/>
After that, you can code the java part, for that you can watch this link http://www.javapractices.com/topic/TopicAction.do?Id=127
For a complete example, there's a good tutorial here http://alvinalexander.com/blog/post/java/how-configure-tomcat-dbcp-connection-pool-pooling-postgres.
Hope this help

Get Datasources programmatically

I have a web-app in Java/Java EE deployed on any application server/web server. I would like to get all the datasources configured on this server in my application.
Does anyone have any ideas to achieve it? I can get those through WLST ant tasks. But I need to get them programatically.
If your datasources are configured with JNDI then you can list the context and can get all the names (more from here) with Context.list() method and from those name you can find all the datasources
the Context.list() returns an enumeration of NameClassPair. Each NameClassPair consists of the object's name and its class name. So just iterate it and check the class name for java.sql.DataSource and then get the object name to retrieve it.
With JBoss you can do the following (assuming JMX is available):
Context ctx = new InitialContext();
MBeanServerConnection mconn = (MBeanServerConnection)ctx.lookup("jmx/invoker/RMIAdaptor");
ObjectName name = new ObjectName("jboss.jca:service=DataSourceBinding,*");
Set s = mconn.queryMBeans(name, null);
Where s is an mbeans collection.

JAX-WS & Tomcat: storing in InitialContext not possible?

Intro I'm writing a web service using JAX-WS, and deploying it in Tomcat. With a lot of difficulties I finally had some code written.
Problem Unfortunately, when trying to run it I get the following error:
Context is read only
Setting I'm writing a web service that queries multiple databases and returns a single result. For that purpose, in the init() method (marked with #PostConstruct), I create a series of DataSources that I add to the context.
This is how I create the pool (based on Tomcat documentation) and after its creation I add it to the context (based on this tutorial):
#PostConstruct
private void init(){
PoolProperties props = new PoolProperties();
props.setUrl("jdbc:postgresql://" + ...);
props.setUsername(...);
props.setPassword(...);
props.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;" +
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
DataSource dataSource = new DataSource();
dataSource.setPoolProperties(propos);
Context ctx = new InitialContext(env);
ctx.bind("java:/comp/env/dbpool", dataSource);
}
And later I use it:
#WebMethod
public Result performQuery(QueryParameters params){
Context ctx = new InitialContext(env);
(DataSource) source = (DataSource) ctx.lookup("java:/comp/env/dbpool");
}
I deploy the web service on a Tomcat 7 server.
Question I understand after Google-ing that I cannot write into the Context on Tomcat. But how else could I solve this? From what I understand about JAX-WS I cannot just have a private variable holding a DataSource, right? I have to pass that DataSource using a Context, right?
The InitialContext is writable from the Tomcat code only, not from your client code. You must add your DataSource to your context.xml and it'll work.

How to set up a <Resource> in Tomcat 7 so that I don't need to use "java:/comp/env" in the code?

I am new to setting up JNDI resources and setting up JNDI resources in Tomcat.
I inherited a servlet application. It runs on a test server via WebLogic. The servlet application accesses its database resource in the following way:
ctx = new InitialContext();
ds = (javax.sql.DataSource)ctx.lookup("myDataBaseName");
conn = ds.getConnection();
When I tried that in a test JSP it doesn't work. I get
javax.naming.NameNotFoundException: Name myDataBaseName is not bound in this Context
However I was able to make the test JSP work if I altered the test JSP code thus:
ctx = new InitialContext();
Context envContext = (Context)ctx.lookup("java:/comp/env");
ds = (DataSource)envContext.lookup("myDataBaseName");
conn = ds.getConnection();
I have this entry in TOMCAT_HOME/conf/context.html ( I'm just using it as a dev environment on my box )
<Resource name="myDataBaseName"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#blahblahblah:1521:database3"
username="joeuser"
password="password"
maxActive="20"
maxIdle="30"
maxWait="-1"/>
</Context>
And I have this in my TOMCAT_HOME/conf/web.xml:
<resource-ref>
<res-ref-name>myDataBaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
I read about 10 stackoverflow pages on related problems, but I am not familiar enough with setting up JNDI resources to abstract those solutions to my problem.
How can I change the way I have Tomcat 7 set up to allow the existing servlet application to access its database as "myDatabaseName"? I don't have the option of altering the code in the servlet application or altering the way WebLogic is set up on the test server.
I need to alter the way my copy of Tomcat 7 is set up on my computer ( for a dev environment ) to allow the servlet application to access its database in the style of the first chunk of quoted code at the top of this post.
I see 2 possibilities here:
Implement a InitialContextFactory and make it available to tomcat (via system property), so that new InitialContext() gives you a context the lookup would work on.
or
Bind the data source to another place in the JNDI, which actually works although it is neither recommended nor documented (tomcat FM states the tree being read-only which only seems to apply to the subtree java:/comp/env):
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/myDataBaseName");
ctx.bind("myDataBaseName", ds);
With the configuration that you provided you should be able to do the following:
ctx = new InitialContext();
ds = (DataSource)ctx.lookup("java:/comp/env/myDataBaseName");
conn = ds.getConnection();

Object reference lookup from JNDI results in ClassCastException

I'm having problems calling EJB3 stateless bean outside the container.
Code for getting the object reference:
Context envCtx = (Context) context.lookup("ejb");
MyObject o = (MyObject) envCtx.lookup(MyObject);
The second row results in exception:
java.lang.ClassCastException: javax.naming.Reference
I use JBoss.org 5.1.0 GA.
Based on some other posts I suspect this might be due to wrong version of client libraries. However, I'm unsure which library jar(s) I should include in the jar? (I get the error using 5.0.4.GA jnpserver.)
For JBoss, your code should look something like that:
Properties properties = new Properties();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","=org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url","localhost:1099");
Context context = new InitialContext(properties);
(EchoBeanRemote) c.lookup("EchoBean/remote");
If you prefer, you can put the JNDI environement settings in a jndi.properties file (that needs to be on the classpath):
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
And use the non-arg InitialContext constructor:
Context context = new InitialContext();
(EchoBeanRemote) c.lookup("EchoBean/remote");
This is obviously more portable.
And in both case, you'll need jbossall-client.jar on the classpath on the client side.
P.S.: You can check the Global JNDI Name your bean is registered at in the JNDI View of the web-based JMX console (if it still exists).

Categories

Resources