J2EE Singleton

by David Jones (Virgin Mobile USA)

Welcome to the 52nd edition of The Java(tm) Specialists' Newsletter sent to almost 4000 Java experts in 84 countries.
Any day now we will count over to the 4000 mark! In countries
besides my home country South Africa I would now get a bottle of
champagne ready, but South Africa is one of only 12 countries
where you can actually drink the water from the tap, and we are
ranked #3 in terms of tapwater in the world - so I think I'll
just drink a glass of fresh clear delicious South African water
to celebrate the landmark 4000th subscriber :-)

This week I am very pleased to welcome a new contributor,
David
Jones, onto my newsletter. David is based in San
Francisco, working for Virgin Mobile USA as a J2EE Architecture
consultant. If you have an extremely lucrative job in that area,
for someone with 4 years solid Java experience, you are welcome
to contact David, although I don't know if he is actively looking
for new challenges or not ;-) I might add that David is actually
of British descent, so he knows how to do his maths and
draw with colour.

I know that this is not the first newsletter in the world to
speak about the Singleton pattern and its role in J2EE. I do
hope, however, that it will show a different angle to what others
have done.

J2EE Singleton

What is a Singleton?

The Singleton pattern became widely popular when it was included
in the now famous "Gang of Four" Patterns book [hk: see the
brochure
of my design patterns course for information about several
patterns]. Its general objective is to make sure that only one
instance of a specific object type exists.

Singletons are commonly found in C++ and J2SE applications.
However their use in distributed J2EE environment becomes a lot
more complex and subject to debate.

Synchronization

Lots of common enterprise requirements are implemented to some
degree by the J2EE Container. One of these classic requirements
is the need for multi-threading in enterprise applications. This
is generally implemented by the use of a thread pool. Each
client request coming in is assigned a worker thread to service
the request. Since therefore any J2EE application by its nature
is multithreaded, limiting the synchronization of threads is an
important requirement.

"Synchronized" as shown is used on a Singletons getInstance
method. This is to prevent the "==null" test which is not thread
safe causing the creation of two Singleton objects, one of which
will then end up being thrown away.

There is a way around the "synchronize" issue by using a "startup
class" or a "startup Servlet". Since both these types of objects
are initialized at container start up it is possible to use them
to initialize the Singletons you need. It is then safe to drop
the "synchronized" from the "getInstance" method.

The following StartUpServlet initializes several Singletons in
its init method. This approach relies on the
<load-on-startup> tag being placed in the Web Application's
web.xml deployment descriptor.

Clustering and RMI Singletons

Clustering is when you have J2EE containers that are running on
different VMs talk to each other. Clustering is used to provide
load balancing and fail over for J2EE clients.

The simple/local Singleton as shown is a non-distributed object.
Therefore in a clustered environment you will end up with at
least one Singleton object on each server. This of course may be
ok for the design requirements.

However if the design is to have one Singleton for the cluster
then a common approach is to implement a "pinned service". This
refers to an RMI object that is only located on one container in
the cluster. Its stub is then registered on the clustered JNDI
tree making the object available cluster wide. This raises of
causes one issue, what happens when the server containing the RMI
Singleton crashes?

A Container in the cluster could try to bind a new RMI Singleton
if it notices it is missing out of the JNDI tree. However this
could cause issues if all the containers try to bind new RMI
Singletons at the same time in response to a failure.

Generally at the end of the day RMI Singletons do tend to have
the drawback that they end up as single points of failure.

In the following code example a local Singleton is used to act as
a Wrapper around a RMI object that is bound into the clusters
JNDI tree.

Distributed Singleton Caches

One of the most common usages of Singletons is as caches of data.
This use has issue for non RMI Singletons in a clustered
environment. Problems happen when you attempt to do an update to
the cache. Since a Singleton instance exists on each Container
any update to the cached data by one Singleton will not be
replicated to the other Singletons that exist on the other
Containers.

This issue can be resolved by the use of the Java Messaging API
to send update messages between Containers. In this approach if
an update is made to the cache on one Container a message is
published to a JMS Topic. Each Container has a listener that
subscribes to that topic and updates its Singleton cache based on
the messages it receives. This approach is still difficult as you
have to make sure that the updates received on each container are
handled in a synchronous fashion. JMS messages also take time to
process so the caches may spend some time out of sync.

In the following simplistic implementation of a distributed Cache
a CacheManager Singleton holds a Map of cached items. Items to
be cached are placed in a CachItem object which implements the
ICacheItem interface.

The CacheManager does not make any attempt to remove old items
from the Cache based on any criteria like "Last Accessed Time".

Class Loading

Containers tend to implement their own class loading structures
to support hot deployment for J2EE components and class isolation
WAR files.

Class isolation in WAR files means that all classes found in a
WAR file must be isolated from other deployed WAR files. Each
WAR file therefore is loaded by a separate instance of the Class
loader. The purpose is to allow each WAR file have its own
version of commonly named JSPs like "index.jsp".

If a Singleton class is located in several WAR files it will mean
that a separate Singleton instance will be created for each WAR
file. This may of course be ok for the required design but it is
worth being aware of.

Common Implementations of a Singleton in J2EE

In conclusion I would like to talk about the three most common
implementations of the Singleton pattern in J2EE I have come
across. These are as Service Locators, Object Factories and
Controllers.

Service Locators

A Service Locator allows you to cache objects (like EJB homes)
that are located in the JNDI tree. JNDI look ups are very
expensive so using a Singleton to cache these objects is a good
idea. Since you never update these objects it does not matter
that the cache is not distributed across a cluster.

In the following implementation of a ServiceLocator all lookups
into the JNDI tree are cached into a Map. The ServiceLocators
getService method has a threading issue where it could place the
JNDI Object into the map multiple times. This is due to the fact
that the check to see if the object is already in the cache is
not synchronized. The reason for dropping the synchronization is
that it is more costly to do a "synchronization" than just
ignoring an issue that if it happened would cause no real harm.

Object Factory

An Object Factory class allows you to create an object of a
certain type based on some form of an identifier. A common use
of a factory in J2EE is in the creation of Data Access Objects.
DAOs are commonly used to abstract SQL usage into specific
classes. Clients obtain a factory Singleton and pass in the
specific identifier for the specific DAO they need. The Object
Factory instantiates the object and then returns a common
interface to the client.

To allow possible support of multiple databases, a simple trick
that can be used is to append a specific identifier to the DAOs
class name. The implementer of the DAO class can then provide a
specific implementation of the DAO for each database type if
required. [HK: This is covered in our Design
Patterns Course :-)]

It is possible that the factory could be implemented as a bunch
of static methods. A reason not to take the static approach is
the fact that maybe at some point the caching of DAOs will be
required. If caching is required than the factories
implementation can be changed to support caching without changing
the factories' interface.

Controller

A Controller takes a request and based on some criteria directs
that request to an object to be serviced. Since the container is
running multiple threads and garbage collection is expensive it
would be nice to have just one instance of the controller. A
Singleton therefore is a good protocol independent Controller.

In the following implementation of an EJB Controller, the
processRequest method takes a Request object that specifies the
following; the Stateless EJBs Home interface class name, the Home
interfaces JNDI name, the method name within the Stateless EJB to
call and finally the list of parameters to pass in. The Response
object contains the return object from the method call.

The Singletons presented here as common implementations of the
pattern in J2EE can be thought of as either stateless or ones
that at most control resources/objects that do not need to be
cluster aware.

That was an excellent piece of writing, very clear, concise, to
the point - Thank you very much, David.

Oracle and Java are registered trademarks of Oracle and/or its
affiliates. Other names may be trademarks of their respective
owners. JavaSpecialists.eu is not connected to Oracle, Inc.
and is not sponsored by Oracle, Inc.