RMI, singletons and multiple classloaders in Weblogic

M

Michael Brown

We have a Weblogic application that has a data cache stored in several
singleton objects. 99% of the access to the data is via servlets or
JSPs that make data requests which are satisfied from the cache (or
the database, if not available from the cache). There is however one
client that accesses data via RMI and this is causing us some major
problems.

If the RMI client runs single-threaded there's no problem.
Additionally, if the RMI client allows one single-threaded remote call
to complete and then starts going hammer and tongs in multiple
threads, that's also OK and there are no problems. However, if the
RMI client immediately steams in with multiple requests on multiple
(client) threads, it causes a most bizzarre situation to occur: the
next time a *servlet/JSP* request comes in, all our cache singletons
become duplicated, presumably loaded by a second classloader.

The result for our application is catastrophic as the fully populated
cache that existed before is now "hidden" to any servlet/JSP requests
and is loaded all over again, doubling the memory usage and crippling
the performance. RMI requests meantime carry on hitting the
"original" cache.

All the server code (including the RMI remote class) is in the same
..war file so I don't understand why a second classloader is being
used. It's even more strange that it should only occur in this very
specific set of circumstances, namely where the first ever RMI call
has not completed before the second one comes in. If we ensure that
the first RMI call completes before any others occur then from that
point on the server is safe from the problem no matter what.
Fortunately, we have control of the client app so we can work around
the problem but it's concerning that we can't control this problem
from the server side.

Having done a bit of reading on the subject I'm aware that using the
singleton pattern in a J2EE environment is not recommended but quite
frankly, I don't see why. Our app doesn't have any EJBs and it's just
a straightforward web application with a cache of data. There must
necessarily only be one copy of the cache (per server) so I don't see
how this could be done *without* using the singleton pattern. I've
seen suggestions that singleton objects should be registered with JNDI
but that seems like an extraordinary overhead for solving a problem
that shouldn't be arising in the first place. Why would two
classloaders be used only in the very speficic circumstances I've
outlined??

Anyone have any ideas what's going on? BTW, we're using Weblogic
7.0sp4 on Solaris.

Michael.
 
J

John C. Bollinger

Michael said:
Having done a bit of reading on the subject I'm aware that using the
singleton pattern in a J2EE environment is not recommended but quite
frankly, I don't see why.

One reason is that objects exchanged over RMI are in many cases copies
of the originals. You therefore have to be very careful if you use
Singletons in an RMI application to ensure that you do not end up with
duplicates.

Moreover, the key J2EE technologies all pretty much require creative use
of ClassLoaders for efficient implementation. ClassLoaders are one of
the banes of Java Singleton implementations.
Our app doesn't have any EJBs and it's just
a straightforward web application with a cache of data. There must
necessarily only be one copy of the cache (per server) so I don't see
how this could be done *without* using the singleton pattern.

Hogwash. The Singleton pattern is by no means the only way to make an
entire application use the same instance of some class, and often it
isn't the best way, either. The key is that there needs to be some sort
of registry in which the instance is stored. With the Singleton
pattern, that registry is within the class itself. Alternatively it
could be in some other class: a factory class, for instance, a class
especially for the purpose, or (as you mention below) some more
general-purpose registry such as JNDI. Do not neglect the possibility
that the registry can even be implicit if (for instance) all the
relevant methods pass around the "singleton" object in method parameters.

I will keep harping on this as long as such questions keep arising:
Singleton is the single most misused design pattern known to
programmerdom. It should be used when the class represents something
that is fundamentally unique and where that uniqueness NEEDS to be tied
to object identity. Those cases are rare. Singleton should NOT be used
simply to enforce development-time predictions of suitable uses, or
(worse) "because it can be".
I've
seen suggestions that singleton objects should be registered with JNDI
but that seems like an extraordinary overhead for solving a problem
that shouldn't be arising in the first place. Why would two
classloaders be used only in the very speficic circumstances I've
outlined??

I couldn't say, but you are setting yourself up for future maintenance
problems if you focus on a solution that simply works around this
particular WL behavior. Look instead for a solution that is not
vulnerable to this kind of problem at all. Example: encapsulate the
data access in a way that can be uniformly accessed by the servlets/JSPs
and the RMI clients. A stateless session bean might be one way to
accomplish that. The main alternative I see is to roll your own custom
equivalent; although that would be lighter-weight, it would probably be
considerably more work to get it right.


John Bollinger
(e-mail address removed)
 
M

Michael Brown

John C. Bollinger said:
Moreover, the key J2EE technologies all pretty much require creative use
of ClassLoaders for efficient implementation. ClassLoaders are one of
the banes of Java Singleton implementations.


Hogwash. The Singleton pattern is by no means the only way to make an
entire application use the same instance of some class, and often it
isn't the best way, either. The key is that there needs to be some sort
of registry in which the instance is stored. With the Singleton
pattern, that registry is within the class itself. Alternatively it
could be in some other class: a factory class, for instance, a class
especially for the purpose, or (as you mention below) some more
general-purpose registry such as JNDI.

OK, but surely if you used another class implementing a registry or a
factory at some point you'd need a static member that stores the
instance which is subject to exactly the same multiple classloader
issues with J2EE as the "classic" singleton implementation.

It would seem that using JNDI is the only surefire way to do this,
without re-inventing the wheel.
I will keep harping on this as long as such questions keep arising:
Singleton is the single most misused design pattern known to
programmerdom. It should be used when the class represents something
that is fundamentally unique and where that uniqueness NEEDS to be tied
to object identity. Those cases are rare. Singleton should NOT be used
simply to enforce development-time predictions of suitable uses, or
(worse) "because it can be".

I think you're being a bit harsh. Sure, Singletons are often misused
but they are also the most useful pattern from the GOF book. I don't
agree that cases where their use is valid are rare.
I couldn't say, but you are setting yourself up for future maintenance
problems if you focus on a solution that simply works around this
particular WL behavior. Look instead for a solution that is not
vulnerable to this kind of problem at all. Example: encapsulate the
data access in a way that can be uniformly accessed by the servlets/JSPs
and the RMI clients. A stateless session bean might be one way to
accomplish that. The main alternative I see is to roll your own custom
equivalent; although that would be lighter-weight, it would probably be
considerably more work to get it right.

Thanks, I'll investigate stateless session beans.

Regards,
Michael.
 
J

John C. Bollinger

[removed weblogic.developer.interest.misc]

Michael said:
OK, but surely if you used another class implementing a registry or a
factory at some point you'd need a static member that stores the
instance which is subject to exactly the same multiple classloader
issues with J2EE as the "classic" singleton implementation.

It depends on your application. In almost all cases it is possible to
do it without involving any static variable in the process. In many
cases, however, that would be more trouble than it's worth.
It would seem that using JNDI is the only surefire way to do this,
without re-inventing the wheel.

JNDI is a very reliable way to do it, and it involves a minimal amount
of coding. You will probably find, by the way, that the back end of the
JNDI implementation you end up using does not use a static variable to
store the instance :) .
I think you're being a bit harsh. Sure, Singletons are often misused
but they are also the most useful pattern from the GOF book. I don't
agree that cases where their use is valid are rare.

I'm afraid I simply don't agree. I don't agree that the pattern is
broadly useful, and I certainly don't agree that it's the most useful
GoF pattern: I'd nominate one of "Decorator", "Template Method", or
"Factory / Factory Method" for that honor. Honorable mention goes to
"Strategy", "Object Adapter", and "Class Adapter". The award for single
most widely used GoF pattern probably goes to "Iterator", at least in
Java. "Observer" might be in one of my lists if I did more GUI
programming or worked on some kinds of dynamic modeling problems.
"Composite", and "Visitor" both have good uses. "Abstract Factory" is
invaluable for certain kinds of problems. "Singleton"? It's down there
somewhere deeper, as far as I'm concerned.

Cheers,

John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top