Monday, April 7, 2008

JNDI Lookup for JDBC resources

Recently I came across an issue where the code to perform a JNDI lookup for a JDBC resource that worked fine in a tomcat container did not work when migrated to an OC$J container. Looking at the details of the code and the resource definitions explained why it did not work and the fix needed.

The following is code snippet that is used to get the datasource object by the application.

String dsName = "myDataSource";
initCtx = new InitialContext();
envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup(dsName);

In Tomcat the server.xml file contains the definition for the datasource "myDataSource". The resource ref mapping is done by an entry in the Catalina/hostname/warname.xml file. This setup works fine in a Tomcat container.

When ported to oc4j container, the datasource "myDataSource" is defined in the application's context (in this case it was the default application). However the code is when running within oc4j container, it failed to find the resource. Taking a closer look at the issue helped identify the solution.

The application is looking for the resource name "myDataSource" within its environment. In Tomcat this resource name was made available to it by the context definition within the Catalina/hostname/appname.xml file by having the following entry

In OC4J the datasources.xml file can provide this mapping. However, providing that mapping itself is not sufficient. The web.xml file needs to have a resource-ref definition that the name referenced within its environment is the globalname defined else where. Tomcat container was forgiving for some reason and it lookedup the resource withoout having the resource-ref definition. In order to fix the issue we had tow choice:

1) Change the code to lookup the resource using the global jndi name. ie

String dsName = "myDataSource";
initCtx = new InitialContext();
DataSource ds = (DataSource) initCtx.lookup(dsName);

2) Add the resource-ref to the web.xml file so the local name is mapped to the jndi global name.

<res-type >javax.sql.DataSource
<res-auth >Container
<res-sharing-scope >Shareable< /res-sharing-scope>

I personally prefer the later as it gives the option to change DataSource reference/names etc without having to change the code.

No comments: