Setting up a JNDI datasource in Tomcat

Setting up a JNDI datasource in an application server will allow a reference to the datasource to be obtained from anywhere in an application by a simple call to the Java Naming and Directory Interface. Although Apache Tomcat is not an application server, this will work in Tomcat, too.

The Datasource

Let's start by setting up the datasource. This is done in ${your_app_home}/**/WEB-INF/context.xml. This file will be used to create ${TOMCAT_HOME}/conf/Catalina/localhost/${your_app_name}.xml, at least in Tomcat 6.x. If this is to be publicly deployed and your application will be packaged as ROOT.war, this file will be called ${TOMCAT_HOME}/conf/Catalina/localhost/ROOT.xml. As it will be created by Tomcat you don't have to worry about it, except to check that it is there in case things don't work. This is the way the context.xml file should look:

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" docBase="/home/you/projects/java/your_app/build/web" path="/your_war_name">
    <Resource name="jdbc/jndi_name"
              auth="Container"
              type="javax.sql.DataSource"
              username="your_database_username"
              password="your_database_password"
              driverClassName="org.postgresql.Driver"
              url="jdbc:postgresql://localhost:5432/your_database_name"
              validationQuery="select 1"
              maxActive="5"
              maxIdle="2"/>
</Context>

In the example above your application is not deployed to $/webapps, but to the directory indicated in the docBase attribute of the Context element. If you are going to deploy your application to $/webapps you simply replace the full path descriptor with your_war_name.war. In case the war name is going to be ROOT.war you can do away with the docBase attribute completely.

The path attribute of the Context element indicates the context root of your application you will type into your browser, like http://localhost:8080/your_war_name. In case the context root is going to be the root element, the value of path can be empty or /.

The name attribute of the Resource element nested inside the Context element is the JNDI name you are going to use to get hold of your datasource. The jdbc/ prefix is required.

The JNDI part of the equation

This is specified in web.xml in the resource-ref element. Below is an extract from web-app_2_3.dtd to show where resource-ref fits in.

<!ELEMENT web-app (icon?, display-name?, description?, distributable?,
context-param*, filter*, filter-mapping*, listener*, servlet*,
servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*,
login-config?, security-role*, env-entry*, ejb-ref*,  ejb-local-ref*)>

Below is an example of a resource-ref element. Just by chance, it was the last element in the web.xml file, below the welcome-file-list element.

<resource-ref>
    <description>The dbapps database</description>
    <res-ref-name>jdbc/jndi_name</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

Obviously, the value in the res-ref-name element nested inside the resource-ref element is an exact match to the value in the name attribute of the Resource element nested inside the Context element of the context.xml file discussed in the first section of this how-to. Again, the jdbc/ prefix is required.

Your JNDI specification can be done elsewhere, from where it will be written to web.xml, if you are using anything but a plain JDBC set-up. For example, if you are using Grails, use grails-app/conf/DataSource.groovy and, for the production environment, do it as follows:

production {
    dataSource {
        pooled = true
        dbCreate = "update"
        jndiName = "jdbc/jndi_name"
    }
}

When you use Grails and you do it as indicated above you will have to add some code to scripts/_Event.groovy so that the resource-ref element is written correctly to web.xml. But that's another story...

And finally...

This works in Tomcat 6 and 7. Let us know if you have anything to add or any remarks. The form for sending mail is below.

Use and empty line to separate paragraphs in the "Comment" text area.

Links and html markup are not allowed.

Submit a Comment




PvxqGbsxMLhqKmP

DCnUjrcIkoUc

Stands back from the kyeobard in amazement! Thanks!

Valid XHTML 1.0 Strict