[Webinar] Streamline your web hosting managementRegister Today

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 319
  • Last Modified:

Return instance of load-on-startup servlet

The overall goal is to create a DataSource in a startup servlet rather than doing it in every servlet.  The problem I'm having is that I can't figure out how to call the method that returns the datasource.  I've tried making the method and the DataSource variable static but I get a variety of "static reference to non-static variable, etc." message depending on how I try and implement it.  I was following a guide on performance optimization and unfortunately the person who wrote it gave no indication of how one makes a call to the getDataSource() method of the startup servlet.  I've tried modifying a dynamic configuration startup servlet example I found elsewhere to use JNDI to reference the startup servlet and all I get are naming context errors.  Here's my latest (lame) attempt so please don't just critique the code since I know there are probably a lot of things I could do better but I've been trying a bunch of different things to get it to work so it's mutated into the ugliness below.  I just want to learn how to do this.  The precise question I have is at the bottom and may make all this code pointless so you may want to start there.  I'm probably going about this all wrong.  Anyway, here goes:

******* StartupServlet.java ********
public class StartupServlet extends HttpServlet {

    private static DataSource ds = null;
    public final static String ENV_CONTEXT = "java:comp/env";
    public final static String JNDI_NAME = "startup/StartupServlet";
    public static StartupServlet getInstance() throws NamingException {
        Context initialContext = new InitialContext();
        Context envContext = (Context) initialContext.lookup(ENV_CONTEXT);
        StartupServlet r = (StartupServlet) envContext.lookup(JNDI_NAME);
        if (r == null) {
            throw new NamingException("Naming exception: No JNDI object named `" +
                    JNDI_NAME + "' in context '" + ENV_CONTEXT + "'");            
      return r;
    public void init(ServletConfig config) throws ServletException {
        System.out.println("******** StartupServlet init() called. ********");

//this code works...was tested outside of startup servlet
        try {            
              Context myContext = new InitialContext();
              Context envContext = (Context)myContext.lookup("java:comp/env");
              ds = (DataSource)envContext.lookup("jdbc/db2");
          } catch (NameNotFoundException ne) {
              System.err.println("Error getting context: " + ne.toString());
          } catch (Exception e){
              System.err.print("Error getting datasource: " + e.toString());
    public DataSource getDS() {
        System.out.println("******** StartupServlet getDS() called. ********");
        return ds;
    public void destroy() {
        System.out.println("******** StartupServlet destroy() called. ********");

******** web.xml *********
This is not complete only the relevant sections.  This is what was in the tutorial (with the names changed, of course)

I get an error that <resource> is not a valid tag, so in keeping with other resource references (I'm using WebSphere Application Server Express and WebSphere Development Studio Client, BTW) I did this:

<resource-ref id="ResourceRef_1153257505430"><---- this was automatically created by WSDC

Also, the "startup/" part of the name was "config/" everywhere...I changed in because the error was always on "config" and I wanted to see if the error would be on startup, which it is.  I'm a neophyte with JNDI so I don't fully understand how it works yet.  Here's the error I keep getting, not that I think it matters because I'm probably doing this all wrong anyway, but for the sake of completeness...

[7/18/06 14:31:54:712 PDT] 00000024 SystemErr     R com.ibm.websphere.naming.CannotInstantiateObjectException: Exception occurred while the JNDI NamingManager was processing a javax.naming.Reference object.  Root exception is javax.naming.NameNotFoundException: Context: PC-ISIT-8801Node01Cell/nodes/PC-ISIT-8801Node01/servers/server1, name: startup/StartupServlet: First component in name startup/StartupServlet not found.  Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0
      at com.ibm.ws.naming.ipcos.WsnOptimizedNamingImpl.handleNameNotFound(WsnOptimizedNamingImpl.java:2252)
      at com.ibm.ws.naming.ipcos.WsnOptimizedNamingImpl.getNextWsnOptimizedNamingContext(WsnOptimizedNamingImpl.java:1448)
      at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase.getTargetContext(WsnOptimizedNamingImplBase.java:4396)
      at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase$LeafOperationData.<init>(WsnOptimizedNamingImplBase.java:5012)
      at com.ibm.ws.naming.cosbase.WsnOptimizedNamingImplBase.resolve_complete_info(WsnOptimizedNamingImplBase.java:2205)
      at com.ibm.WsnOptimizedNaming._NamingContextStub.resolve_complete_info(Unknown Source)
      at com.ibm.ws.naming.jndicos.CNContextImpl.cosResolve(CNContextImpl.java:4043)
      at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1746)
      at com.ibm.ws.naming.jndicos.CNContextImpl.doLookup(CNContextImpl.java:1707)
      at com.ibm.ws.naming.jndicos.CNContextImpl.lookupExt(CNContextImpl.java:1412)
      at com.ibm.ws.naming.util.IndirectJndiLookupObjectFactory$1.run(IndirectJndiLookupObjectFactory.java:372)
      at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java(Compiled Code))
      at com.ibm.ws.naming.util.IndirectJndiLookupObjectFactory.getObjectInstanceExt(IndirectJndiLookupObjectFactory.java:221)
      at com.ibm.ws.naming.util.IndirectJndiLookupObjectFactory.getObjectInstance(IndirectJndiLookupObjectFactory.java:149)
      at com.ibm.ws.util.ResRefJndiLookupObjectFactory.getObjectInstance(ResRefJndiLookupObjectFactory.java:138)
      at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:314)
      at com.ibm.ws.naming.util.Helpers.processSerializedObjectForLookupExt(Helpers.java:894)
      at com.ibm.ws.naming.urlbase.UrlContextHelper.processBoundObjectForLookup(UrlContextHelper.java:191)
      at com.ibm.ws.naming.urlbase.UrlContextImpl.processBoundObjectForLookup(UrlContextImpl.java:1775)
      at com.ibm.ws.naming.urlbase.UrlContextImpl.lookup(UrlContextImpl.java:1280)
      at com.ibm.ws.naming.urlbase.UrlContextImpl.lookup(UrlContextImpl.java:1307)
      at com.signet.lcdm.StartupServlet.getInstance(StartupServlet.java:42)
      at com.signet.lcdm.GetRepDataAction.execute(GetRepDataAction.java:83)
      at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
      at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
      at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
      at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:507)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
      at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1282)
      at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:673)
      at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:2965)
      at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:221)
      at com.ibm.ws.webcontainer.VirtualHost.handleRequest(VirtualHost.java:210)
      at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:1931)
      at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:84)
      at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:472)
      at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:411)
      at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:288)
      at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminaters(NewConnectionInitialReadCallback.java:207)
      at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:109)
      at com.ibm.ws.tcp.channel.impl.WorkQueueManager.requestComplete(WorkQueueManager.java:566)
      at com.ibm.ws.tcp.channel.impl.WorkQueueManager.attemptIO(WorkQueueManager.java:619)
      at com.ibm.ws.tcp.channel.impl.WorkQueueManager.workerRun(WorkQueueManager.java:952)
      at com.ibm.ws.tcp.channel.impl.WorkQueueManager$Worker.run(WorkQueueManager.java:1039)
      at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java(Compiled Code))
More stack errors but probably not needed at this point.

The pointed question is how do I return a reference to the StartupServlet class that the container started so I can call the getDataSource() method?

Thanks.  Sorry for the length but I've been criticized before for not posting enough.  Probably went overboard this time.
  • 5
  • 5
1 Solution
Hi SimmerDown

why do you want to create a datasource in the startup servlet? The application server should be able to create the named datasource once and you should be able to accss uit from any servlet/jsp/ejb etc. There is no reason to do it in a Servlet and then get this datasource via a reference to this start up servlet (tbh I am not even sure if you can get a reference to a servlet like you do with a normal java class).

SimmerDownAuthor Commented:
Hi Girionis,

The purpose is to only do the JNDI lookup once instead of in several places.  This is based on information I got out of a performance improvement article for servlets with reference to datasources.  I found other articles similarly recommending the same thing but with no example code.  My application is already working retrieving the JNDI datasource object in each servlet but I thought this tip sounding like it would be worth checking out.  As I said above, the information was probably intended for someone beyond intermediate in skill because a lot was left to work out on your own, like calling the non-static class.  I also made an assumption based on the example classes name (ControllerServlet) that it was a load-on-startup servlet.  However, even if that assumption is incorrect it's still pretty clear that only one instance of that class would exist and in order to use it's methods one would have to retrieve the instance of the class rather than creating a new instance.

In any case I have found out that the other example I was trying to meld with this one was specifically for resin which explains why I'm getting the naming context error since WebSphere isn't set up to use a config container.  Most of the singleton examples I've referred to which are able to return an instance of themselves also create their own instance to pass back to the calling method.  The question I was asking was how one would have an already instantiated class return itself.

It may not be possible but since I can't contact the author of the original article I thought I'd test the waters here at E-E.  Thanks for the feedback.  I think I'll leave this up for awhile to see if anyone has other ideas.  If I figure something out in the meantime I'll post it here for posterity and close the question.


> The question I was asking was how one would have an already instantiated class return itself.

This can only be done if other objects register themselves with the class in question, so the class notifies them when it is loaded.

What I suggest is to write a standard java class that starts up when the application server starts up. In this class you do the jndi look up you need and obtain the datasource. Then have a static method that returns this instance to the callers something like

public class MyJNDIReturner
   private static Datasource ds = null;
   private static MyJNDIReturner myObject = null;

   private MyJNDIReturner()
      // Do the lookup and assign the datasource

   public static MyJNDIReturner getInstance() {
        if (myObject == null)
            myObject = new MyJNDIReturner();

       return myObject;

    public Datasource getDatasource()
      return ds;

and from your servlets you can do

MyJNDIReturner r = MyJNDIReturner.getInstance();
Datasource ds = r.getDatasource();

Of course the doce might need some modifications and/or optimizations. It is only here to give you an idea of how you should go on. For more info you might want to sdo a google search for "Service locator pattern"
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

> doce

I mean

code :)
SimmerDownAuthor Commented:
I just wanted to say I haven't abandoned this question.  I've had a another project take priority so I haven't been able to try the proposed solution.
SimmerDownAuthor Commented:

Sorry...I can post here every couple of days until I have a chance to test the solution.  I haven't had a chance to test the solution and before I award 350 points it seems I should have the opportunity to do so.

How fequently do I need to update this question to prevent it being closed?  This is not an abandoned issue...it's a reprioritized project and unfortunately I simply haven't had a chance to work on this project let alone try the proposed solution.  I want to award the points fairly and if the solution hasn't been tested I don't feel it's fair to arbitrarily assign just because someone has offered an unproven solution.  Since you aren't losing anything by leaving the question open, providing I keep updating it, I don't see how this is a problem.

I will update as frequently as necessary to keep the question from being closed, just let me know how frequently that needs to be.  I don't think I've ever abandoned a question here other than ones that never received any expert's response and I've been a member for awhile.  Check my history.

Also, since the only person to have proposed any solution is yourself there would appear to be a bit of a conflict of interest if you decided to close the question and award the points to yourself. :o)

Thank you.
Ok, no problem. Normally you should post at least one comment every 21 days, after that the question is considered abandoned. But I am the only one that is doing clean up in the Java area at the moment, so I can just ignore your question when I see it again even if there is no comment within a three weeks period :)
SimmerDownAuthor Commented:
Thank you very much for being understanding.  I appreciate it.  I expect to be put back on this project within the next two weeks.
Hello SimmerDown, do you still need help on this because I am gonna do some cleanup and I am going to post recommendation for this question.
SimmerDownAuthor Commented:

Sorry again.  I've been so busy on other development projects I still haven't revisited this specific issue but I have had some more experience with singleton classes and based on what I've learned I understand your suggestion better and I'm confident it will work.

Thanks again for being so patient.


Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now