JNDI is a Java standard that allows applications to get reference to Java Objects by doing a named lookup against a directory. This is the defacto standard on how to get Database and MQ connections.
In this document I we will review the different ways resources can be setup in the Tomcat 6 environment.
Setting up JNDI lookups on Tomcat is typically a 3 step operation.
Step 1: Global Resource Definition
These items are stored in the tag in the server.xml file under the <GlobalNamingResources> tag. These resources affect the whole server. This is actually the prefered approach and close to what IBM Websphere has.
<Resource name="jdbc/recipe" auth="Container" type="javax.sql.DataSource" maxActive="101" maxIdle="30" maxWait="10000" username="tomcat" password="xxxxxx" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://catalinahost.com/recipe?autoReconnect=true"/>
Step 2: Mapping Configuration
Once the resource is defined at the global level you need to map this resource to your application. For this you need to put an element that maps the web applications resource-ref to the globel resource.
The mapping looks like this:
<ResourceLink name="jdbc/recipe" global="jdbc/recipe" type="javax.sql.DataSource"/>
The above code can be put into the context by using any of the 3 methods listed below.
$CATALINA_BASE/conf/context.xml
(prefered) In the $CATALINA_BASE/conf/context.xml file: the Context element information will be loaded by all webapps. This is actually the perfered method since it closely resembles what is done In IBM Websphere Application Server. In Websphere the system administrator got a screen asking him/her to map resource references. The user will select the resource reference that is defined in the web.xml and map it to resources available on the server. The user will click bind and the mapping would be done.
/META-INF/context.xml
In this method the context is defined in the META-INF folder of the WAR file. If the web application is packaged as a WAR then /META-INF/context.xml will be copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to match the application’s context path. Once this file exists, it will not be replaced if a new WAR with a newer /META-INF/context.xml is placed in the host’s appBase. I dont like this approach because it makes the web application responsible for mapping internal resources to server resources. Also if there is ever a change to the context.xml in the war it will not be copied over. The administrator will need to navigate to the /conf/[enginename]/[hostname] folder and delete the context.xml file before a fresh one will be copied from the WAR file.
$CATALINA_BASE/conf/server.xml
This is the least prefered out of all the other approaches. It requires the context to be made available inside a Host element in the main conf/server.xml. The problem with this approach is that the whole tomcat server would need to be restarted for the changes to take effect. In many cases applications can not be brought down for a restart without first sheduling a outage.
The third and last component of defining a resource in a web application is the web.xml file.
Step 3: Web Application Configuration (web.xml)
The web application will have an area where all the resources are specified.
The following is an example of how a resource will be defined in a web.xml file.
<resource-ref> <description>Recipe Database</description> <res-ref-name>jdbc/recipe</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
Finally Using the Resource in Java Code
//You may use the following lines to initialize the context.
// Obtain our environment naming context
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//A data source can be obtained by doing the following.
// Look up our data source
DataSource ds = (DataSource) envCtx.lookup("jdbc/recipe");
// Allocate and use a connection from the pool
Connection conn = ds.getConnection();
//... use this connection to access the database ...
conn.close();
If you are using the popular spring framework you can do the following
<bean id="dataSource">
<property name="jndiName">
<value>jdbc/recipe</value>
</property>
<property name="resourceRef" value="true"></property>
</bean>
Hi,
Thanx for such a nice article. Please continue to write such things which are very much helpful and time saving.
We have an application where we need to initiallize the datasource at server start up. Could you please suggest a way to do that ?
Thanks for providing such a great article.