Link to home
Start Free TrialLog in
Avatar of howesd
howesd

asked on

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
ASKER CERTIFIED SOLUTION
Avatar of girionis
girionis
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
Avatar of kylar
kylar

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
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.
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.
Avatar of howesd

ASKER

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
 Take a look here for a detailed analysis:

http://www.javageeks.com/Papers/JavaStatics/index.html
>>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'.
Avatar of howesd

ASKER

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
Avatar of howesd

ASKER

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
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.
Avatar of howesd

ASKER

CEHJ - That's very kind of you. I'll read it and let you know what I make of it

Dave
 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.

> 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.

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