URL as JNDI resource using WAS and Tomcat

2010/12/18

The last couple of days I’ve been looking into ways of configuring a JEE application. A common problem is how to configure your application for different environments (local dev machine, test machine, integration tests, production). This can be done in different ways including:

  • Fetching configuration from the database.
  • Running different post compile scripts for the various environments.
  • Shipping different properties files along the main package (WAR or EAR)

The database url/datasource is often retrieved from the web server or app server using JNDI.

A nice approach is to store not only datasources, but also other properties on the app server. On Websphere Application Server (WAS) version 6 and 7 (at least) there are different types of resources that can be configured: jdbc datasources, jms, urls and a few more.

I had the need to configure a remote webservice endpoint as a resource and the URL type on WAS felt natural but it also had to work nicely on Tomcat during development. Setting up a URL resource on WAS is straight forward: give it a name, a JNDI name and the actual URL.  Accessing this JNDI resource can be done in different ways, but I’ll show the way which also works on Tomcat:

1. Edit your web.xml and add something like:

<resource-ref>
 <res-ref-name>
   url/SomeService
 </res-ref-name>
 <res-type>
   java.net.URL
 </res-type>
 <res-auth>
   Container
 </res-auth>
</resource-ref>

2. Instruct Tomcat to setup an object accessible over JNDI. Edit your app’s META-INF/context.xml or $CATALINA_HOME/conf/server.xml if you want to setup a system wide resource:

<Resource name="url/SomeService" auth="Container"
 type="java.net.URL"
 factory="com.mycompany.common.URLFactory"
 url="http://www.someservice.com/service" />

3. Implement a URLFactory used by Tomcat to create URL objects on demand:

import java.net.URL;
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.spi.ObjectFactory;

public class URLFactory implements ObjectFactory {
 public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
 Reference ref = (Reference) obj;
 String urlString =  (String) ref.get("url").getContent();
 return new URL(urlString);
 }
}

4. Write some application code to fetch your Resource:

InitialContext context = new InitialContext();
URL url = (URL) context.lookup("java:comp/env/url/SomeService");

Using this approach it’s possible to build one WAR or EAR and install it wherever you want. The different environments hold their own configuration within the app server. Since Tomcat is only used for local development, the resources could be stored as application specific resources in META-INF/context.xml, but it’s also possible to keep resources as a per-environment basis using Tomcat’s conf/server.xml

It’s also possible to write your own class as a resource (instead of using DataSource, URL and so on). This is quite easy on Tomcat, see Apache Tomcat 6.0 – JNDI Resources HOW-TO, but takes some pain to setup on WAS. Here’s an old article on how to get it done on WAS 5, but it works similarly on newer releases:

Resources:
Apache Tomcat 6.0 – JNDI Resources HOW-TO:

2 Responses to “URL as JNDI resource using WAS and Tomcat”

  1. David Schott said

    This is an excellent post! I’ve been searching everywhere for a simple and clear explanation on how to set up resources in Tomcat and this gets right to the point. A+

  2. Mangesh M. Kulkarni said

    I am tried to implement this – but it didn’t worked. I am using tomcat 6. Can you please provide sample deploy able code ?

Leave a comment