views:

947

answers:

4

I am facing a problem with my singleton when used across multiple class loaders. E.g Singleton accessed by multiple EJBs. Is there any way to create a singleton which has only one instance across all class loader?

I am looking for pure java solution either using custom class loader or some other way.

+2  A: 

The only way would be to make your singleton class be loaded by a single classloader - put that jar file in the bootclasspath, for example.

A static variable is inherently tied to the classloader which loaded the class containing that variable. It's just the way it works. If you need absolutely one instance, you need that class to only be loaded by one classloader.

Jon Skeet
We use Glassfish App server and OpenESB as Enterrprise service bus. This singleton (a wrapper to JCS Cache to store Ldap Search results) is part of the common library which is shared among multiple binding components and EJB's.
rjoshi
@rjoshi: And is the singleton being loaded in multiple classloaders, and can you avoid that? If the class is always going to be in multiple classloaders, I can't see how you can avoid it not being a "proper" singleton.
Jon Skeet
And also assure that you are careful with serialization/deserialization. Best practice is probably to avoid allowing your singleton to be serializable.
CPerkins
@Pascal: it was a mistake to accept the answer. so I have deleted it.
rjoshi
+4  A: 

JavaEE app servers generally solve this problem by setting up the singleton as a "service", the exact definition and configuration of which depends on the appserver in question.

For example, in JBoss you could use a xyz-service.xml descriptor to set up a singleton object that hangs off the JNDI or JMX tree, and your application components (e.g. your EJBs) would fetch the singleton from the tree. That protects you to some extent from the underlying classloader semantics.

skaffman
We use Glassfish App server and OpenESB as Enterrprise service bus. This singleton is part of the common library which is shared among multiple binding components and EJB's.
rjoshi
OK, so find out how to create a JMX service in Glassfish, and connect to that service from your components.
skaffman
I googled but couldn't find anything except support of EJB3.1 with singleton feature in Glassfish V3. but we use EJB3 with Glassfish 2.1GA.
rjoshi
+3  A: 

J2EE is designed with clustering in mind, so any designs that it supports are going to have to work with multiple JVM's. I take it from your question that you aren't concerned about a clustered environment, so a simple insertion into JNDI on your app server should do it. In Glassfish, that is called a lifecycle listener. After the startup even, insert your singleton into JNDI, and then have everything else do a JNDI lookup to find it.

Note that GlassFish could still mess you up here, in that it could serialize the class to JNDI causing you to get different instances. I doubt it actually does this within one JVM, but you won't know until you try it.

The real bottom line answer is that J2EE is hostile to a global true singleton, and the J2EE way around the problem is to rethink the solution. Something like a database to hold values or some other external service that can ensure that only one instance of the data (even if multiple instances of objects representing the data) exists is the J2EE way.

Yishai
I am using this singleton to store the ldap cache. I am wondering how other developers are solving this issues?
rjoshi
rjoshi, I would ask that as a seperate question with some more technical details, but it seems to me that you don't need it to be truely global. Put it in JNDI, and if a given lookup happens twice, so be it.
Yishai
@Yishai: thx. for you suggestion. I will try it out and let you know. I was trying to avoid the JNDI/EJB wrapper and resolve using classloader hack but I guess that's the only way..
rjoshi
A: 

http://surguy.net/articles/communication-across-classloaders.xml Refer to this link

madhav