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.
To create a singleton class, a class must implement the following properties: Create a private constructor of the class to restrict object creation outside of the class. Create a private attribute of the class type that refers to the single object.
The most popular approach is to implement a Singleton by creating a regular class and making sure it has: A private constructor. A static field containing its only instance. A static factory method for obtaining the instance.
This pattern involves a single class which is responsible to create an object while making sure that only single object gets created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With