Share WURFL across Multiple Java Web Applications with JNDI

Share WURFL across Multiple Java Web Applications with JNDI

by Fulvio Crivellaro, ScientiaMobile, Java Team

A lot of work has gone into optimizing WURFL, both in terms of performance and memory consumption for version 1.4 of the Java API.

With this tutorial, we show you how you can save even more memory by sharing the running WURFL instance among different web applications, thanks to the Java Naming Directory Interface (JNDI) API.

This article (and the examples that come with it) have been tested on Tomcat, but readers shouldn’t encounter too much trouble porting them to other Application Servers.

As usual, provide Tomcat with the WURFL JAR and its dependencies, by placing them in the path $CATALINA_BASE/lib folder. This will be needed for the purpose of initializing WURFL.

To enable Tomcat to instantiate WURFL, you need a factory class that implements the javax.naming.spi.ObjectFactory interface (see the javadoc in the references at the end of the article), and, of course, you need to configure the server to use it.

The configuration has to be done in the $CATALINA_BASE/conf/server.xml file, by adding the following entry inside the <GlobalNamingResources> tag:

<Resourceauth="Container"
                 description="WURFL holder provider for web applications"
                 factory="com.scientiamobile.wurflprovider.WURFLHolderFactory"
                 name="wurfl/wurflholder"
                 path="C:/wurfl.zip"
                 type="net.sourceforge.wurfl.core.WURFLHolder" />

Next, the WURFLHolderFactory has to be implemented; you can find the whole example here. Here are the key steps:

  • acquire configuration parameters from the xml tag (‘obj’ is one of the argument in the method signature):
// Customize the bean properties from our attributes
Reference ref = (Reference) obj;
// get wurfl.zip path
String wurflPath = ref.get("path").getContent().toString();
  • instantiate the GeneralWURFLEngine, and return it:
return new GeneralWURFLEngine(wurflPath);

Such class has to be compiled and made visible to the application server; the simplest way is to package it into a JAR, and then place it in the $CATALINA_BASE/lib folder.

Finally, we need to make the applications aware of the shared WURFL resource. 

There are two ways we can do it, depending on specific requirements: globally or locally.

By acting globally, every application deployed will be able to access the resource, while a local approach will allow to specify application-level permissions.

The xml entry to expose the resource is the same for both the approaches:

<ResourceLinkglobal="wurfl/wurflholder"
            name="wurfl/wurflholder"
            type="net.sourceforge.wurfl.core.WURFLHolder"/>

To share the resource globally, you must add the entry to the file $CATALINA_BASE/conf/context.xml as a child of the root element.

To enable specific applications, you most modify the file context.xml (contained in the META-INF folder in the WAR archive) accordingly.

Applications configured in this way can access the WURFL services. The following code will get you a WURFLHolder instance:

 [...]
 try {
    Context initCtx = new InitialContext();
    Context envCtx = (Context) initCtx.lookup("java:comp/env");
    WURFLHolder holder = (WURFLHolder) envCtx.lookup("wurfl/wurflholder");
    [...]
 } catch (NamingException e) {
    // manage the exception
    [...]
 }

 

REFERENCES:

Complete WAR file

http://scientiamobile.com/download/jnditut/WURFLHolderFactory.java

http://java.sun.com/products/jndi/1.2/javadoc/javax/naming/spi/ObjectFactory.html

http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html

http://tomcat.apache.org/tomcat-5.5-doc/config/context.html