Help me understand static!

I've the following code which I am using to implement a pool of database connection pools ( our development environment needs each of our developers to have their own db pool - it's a long story.... )

Anyway, what I thought would happen is that as the applications make calls to DatabasePoolFactory.getInstance(...) I would create one and only one hashtable and put and get poolmanager objects from it. Here's the code:

package BslDatabasePool;

import java.util.*;
import SPAR.BslException.*;

public class BslDatabasePoolFactory
{

    static private Hashtable dbList = null;

/**
 * Retrieves an instance of the named PoolManager. This should be used when you
 * want to connect to a pool which you know ( or hope! )to be available, and you don't want to
 * go to the trouble of having to define the db context. If the Pool is actually
 * NOT running, then an UnknownPoolException is thrown.
 */
    static public synchronized PoolManager getInstance(String PoolName) throws Exception
    {
       return getInstance(PoolName,(SparDatabaseContext)null);
    }
   
/**
 * Retrieves an instance of the named PoolManager, creating a new one with
 * the supplied name and database context if one does not already exist. If
 * a pool manager exists with the specified name, YOU WILL BE RETURNED A
 * REFERENCE TO IT REGARDLESS OF WHETHER OR NOT ITS CONTEXT MATCHES THAT
 * WHICH YOU PASSED IN. This means that there is a possibility that you
 * may end up connecting to a database that you don't want to. Making sure
 * that this doesn't happen is dependent upon sensible naming standards.
 */
    static public synchronized PoolManager getInstance(String PoolName,
                                                       SparDatabaseContext SdbC)
                                                       throws Exception,
                                                              UnknownPool
    {

        if (dbList == null)
        {
            System.out.println("Creating New Database Factory");
            dbList = new Hashtable();
        }

        PoolManager tmp = (PoolManager)dbList.get(PoolName);

        if (tmp == null)
        {
            System.out.println("PoolManager Not Found - Creating New One called " + PoolName);
            if (SdbC == null)
            {
                throw(new UnknownPool(PoolName));
            }
            tmp = new PoolManager(SdbC);
            tmp.setName(PoolName);
            dbList.put(PoolName,tmp);
        }
         else {System.out.println("Pool Already Available");};

        return tmp;

    }

}

My understanding of static ( which I'm sure is wrong! ) is such that, as the first call on the static getInstance method is received, a dbList hashtable will be created and the message "Creating New Database Factory" will be produced. After that, any subsequent calls to getInstance will go to the hashtable and retrieve the specified poolmanager object. This appears to happen as long as only one tomcat servlet is running. When a second servlet calls getInstance, I would expect it to see that the static hashtable dbList is already in existence and just put any new pool manager instances in to the same hashtable. What _actually_ happens is that I see another "Creating New Database Factory" message, which I guess means that a new hash table is being created and populated.

My understanding was that a static class would exist once in the JVM. This doesn't appear to be happening. Where is my understanding letting me down?

Dave
LVL 1
howesdAsked:
Who is Participating?
 
girionisConnect With a Mentor Commented:
 AFAIK it is likely to be a class loader issue. Where do you have BslDatabasePoolFactory class? Try to put it in your current working web application and see what happens.

  In general try to move it up and down the class loader hierarchy.

  Hope it helps.
0
 
CEHJCommented:
It seems to me your understanding of 'static' in this situation is quite correct. It seems a little mysterious to me too. But I could suggest the following, some of which might bring about a change:

1. If you're going to use some kind of pool manager, you could arrange for it to be preloaded by the context.

2. If you're going to do that, you may as well create dbList as soon as the class is loaded:

static private Hashtable dbList = new Hashtable();

3. Since this reference will never change, why not:

private static final Hashtable dbList = new Hashtable();

4. On an unrelated note, I would rename UnknownPool to UnknownPoolException.
0
 
kylarCommented:
I agree in that it seems like your assumptions are correct and that there should only be a single Hashtable. Is it possible that multiple VM's are running somehow inside the servlet container? (I don't do much servlet work so forgive my ignorance :)

Listening Curiously...
-K
0
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.

 
cehjohnsonCommented:
On the other hand, if you want to construct a BslDatabasePool explicitly at a certain point, you could make this class a singleton as an extra safeguard, if Tomcat will allow it. This means that you would have only *one* possible BslDatabasePool to get only *one* possible PoolManager from.
I say if Tomcat will allow it as Tom might not allow private constructors.
0
 
objectsCommented:
An instance of each static variable exists for every *class loader*. Tomcat uses a seperate class loader for each servlet which is resulting in what you are experiencing.
0
 
howesdAuthor Commented:
cehjohnson - After I posted the message I realised that making it a singleton class would be a good idea ( that was what I was actually trying to achieve but I'd made a hash of it! )

objects - given what you're saying about the separate class loader for each servlet, am I wasting my time in trying to produce a poolfactory which will serve up poolmanagers across a complete tomcat installation?

Dave
0
 
girionisCommented:
 Take a look here for a detailed analysis:

http://www.javageeks.com/Papers/JavaStatics/index.html
0
 
CEHJCommented:
>>you could make this class a singleton as an extra safeguard, if Tomcat will allow it

Even that won't work as the paper girionis mentions explains, so my suggestion won't cure the problem. The problem can be treated by applying the principles the paper's author describes beginning 'Consequences'.
0
 
howesdAuthor Commented:
Unfortunately, I can't read the paper - I think the firewall I'm behind might be getting in the way. I'll try to read it when I can get access from another machine.

Thanks
0
 
howesdAuthor Commented:
I still can't get hold of the paper .... but, if I understand objects comment about each servlet having its own classloader correctly, does this mean that I need to instantiate the DatabasePoolFactory in one servlet ( probably one that loads on startup ) and then push it into the servlet context using getServletContext().setAttribute(...) and then get any other JSP's or servlets which want to use the pool to use getServletContext().getAttribute(...) ( or what ever it's called - I don't have my documentation with me at the moment )?

Dave
0
 
CEHJCommented:
Probably easier if we somehow get you the paper! I wonder if you can't it because of the mime type of the url? You could try this if that's the case - the pdf file is converted into html:

http://access.adobe.com/perl/convertPDF.pl?url=http://www.javageeks.com/Papers/JavaStatics/JavaStatics.pdf

If that doesn't work, let me know and I'll mail you the file.

In the meantime you can save yourself some time by implementing the singleton anyway, as we were discussing, although as you'll see when you read the document, this will not be sufficient in itself to cure the problem.
0
 
howesdAuthor Commented:
CEHJ - That's very kind of you. I'll read it and let you know what I make of it

Dave
0
 
girionisCommented:
 Or you can send me an e-mail to p_konstantinidis@hotmail.com and I will mail the file to you. I rarely ever use his address anymore.  It's mainly full of junk mail so I do not mind getting some more. I have just deleted all my mails cause my mail box was full, so there is space for your e-mail (if you decide to send me one).

  Hope it helps.

0
 
objectsCommented:
> am I wasting my time in trying to produce a poolfactory
> which will serve up poolmanagers across a complete
> tomcat installation?

No, what you need to do is ensure your singleton pool factory is loaded by the system class loader. You can do this by ensuring the classes are found in the ext directory or the classpath.

0
 
girionisCommented:
No comment has been added lately, so it's time to clean up this TA.

I will leave a recommendation in the Cleanup topic area that this question is:

- points to girionis

Please leave any comments here within the
next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !

girionis
Cleanup Volunteer
0
All Courses

From novice to tech pro — start learning today.