Search code examples
javaooptomcatservletsjndi

Using JNDI to share servlet session objects and data in Tomcat


Over the last few weeks i have been looking at solutions to share an object between two contexts/war files. There are a number of ways this can be done and one of them is JNDI.

I am not very familiar with JNDI used in Tomcat so would like a few questions clarified:

Basically i have an instance of an object that would provide the following services to more than one context/application

  • Check that the user is logged on
  • Check that the user's session is valid
  • Logon user - Includes logging the logon details
  • Logout user - Remove session

Each application will call this object to validate the user before it processes any requests. What i dont understand is how the object would work if it is stored on JNDI. I have seen a few examples of how JNDI is used in Tomcat but 99% of the examples show how to configure a JDBC datasource.

  • How exactly is the object initialised in JNDI. For example, the following configuration from the Tomcat docs shown the configuration for JDBC
<Resource name="jdbc/db1"
   auth="Container"
   type="oracle.jdbc.pool.OracleDataSource"
   driverClassName="oracle.jdbc.driver.OracleDriver"
   factory="oracle.jdbc.pool.OracleDataSourceFactory"
   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db1"
   user="scott"
   password="tiger"
   maxActive="20"
   maxIdle="10"
   maxWait="-1">

How would i do a similar thing in my case and most importantly, how would i initialise the object before it is put on the JNDI tree. Once it is on the JNDI tree, how is it updated?

I guess what i am looking for is a simple example of the use of JNDI in Tomcat but not for database connections but for service provider type objects.

I have been reading this tutorial http://docs.oracle.com/javase/tutorial/jndi/ops/bind.html but it is focused more on LDAP naming directories which doesnt really help.

Edit

Ok i did find an example in the tutorial i listed above that shows how to "bind" an object the the JNDI tree.

class SerObj {
    public static void main(String[] args) {

    // Set up environment for creating initial context
        Hashtable<String, Object> env = new Hashtable<String, Object>(11);
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
        "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

    try {
        // Create the initial context
        Context ctx = new InitialContext(env);

        // Create object to be bound
        Button b = new Button("Push me");

        // Perform bind
        ctx.bind("cn=Button", b);

        // Check that it is bound
        Button b2 = (Button)ctx.lookup("cn=Button");
        System.out.println(b2);

        // Close the context when we're done
        ctx.close();
    } catch (NamingException e) {
        System.out.println("Operation failed: " + e);
    }
    }
}
  • How would i modify it to use the Tomcat environment instead of the LDAP environment as shown above?
  • Does the bind store a copy of the object or a reference to the object? What i am not sure of is for example, if 3 webapps access the object, will they all be accesssing the same instance of the object or different instances? I would like there to be only one instance of the object i put in the JNDI tree.

Edit

I must be missing something very simple. Here is another example i found which shows how to configure a JNDI object in Tomcat - http://flylib.com/books/en/4.255.1.275/1/

  • How is the com.jspservletcookbook.StockPriceBean initialised?
  • If one webapp uses the com.jspservletcookbook.StockPriceBean object and changes its state, is this change reflected across all other webapps that access this object?
  • And most importantly, how many instances of the com.jspservletcookbook.StockPriceBean will be created - I need it to be the same instance for all webapps that would access the object.

Edit

@Ben Brunk - At the moment the session data is stored in a Map which is managed by one of the applications(context). All i need is for the other applications to call this application to check if the session is valid. My problem is that for these applications to get the services of the application that manages the session data, i need to use JNDI for them to get a reference to the relevant object.

The data will not be stored in JNDI. I just want to use JNDI as a means for the applications to find and use the Session Manager object. The problem though is that everything i read about JNDI leads me to believe that it is used to create new objects every time an object is searched or 'looked up' in the directory.

Here is diagram i think shows exactly what i want to achieve:

Obtaining a reference

Edit

@EJP - Just to clarify, the functions i listed above are just examples of what the shared object might do. These were provided just as an example. All the functions it would do are related to the user and the logged on session. For example things like account information(username, last login etc), password information (expiry date etc), user privileges (i.e. which areas of the application the user is allowed access to).

Given that the question is really related to multi-context communication via JNDI (Or any other means) and not about the requirements of the object it doesn't really make sense to list everything that the object is supposed to do so i just listed examples of what it could do.

Apologies if the way i put the question confused anyone.


Solution

  • If you don't care to use LDAP, just use the database itself by creating tables in there to manage session information. You should be able to find plenty of examples of how to do that because it is a common need in enterprise applications. In fact, I had not seen an example of doing it using the LDAP directory before. It seems like LDAP would be a bad fit for managing sessions across domains because it really isn't designed to be updated a lot.

    Just to be clear: JNDI is not a storage mechanism. It is a mechanism for naming resources in an enterprise environment and then having the container manage connections to those resources. You need to store your session data in a database or you could use the filesystem or a NoSQL map type solution.