I read an EJB pattern at The Server Side entitled: "EJBean Class
Initialization Hooks "
http://www.theserverside.com/patterns/thread.jsp?thread_id=7270
There is a code snippet here:
public abstract class AbstractEJBean
{
private boolean isInstanceInitialized = false;
private static Set initializedBeanClasses = new HashSet();
protected void onSetEJBContext()
{
if (!isInstanceInitialized)
{
//This block of code needs to be synchronized because the
sequence of execution is critical,
//and HotSpot 2.0 mangles the order if synchronized block is
removed!
synchronized(this.getClass())
{
if(!initializedBeanClasses .contains(this.getClass()))
{
initializeOncePerBeanClass();
initializedBeanClasses.add(this.getClass());
}
initializeOncePerInstance();
isInstanceInitialized = true;
}
}
initializeEveryContextSwap();
}
}
FYI onSetEJBContext will be called from setEntityContext which is guaranteed
to be called exactly once per instance by the EJB container before other
methods are called on the bean. The author, Gene Chuang, also seemed to
indicate in /his/ first reply to the discussion thread, that
initializeEveryContextSwap is unnecessary because (a)?was he trying to say
that there is an error and that it should be invoked by ejbActivate instead?
or (b) that it is redundant since it is guaranteed to be called, in his
implementation above, right after initializeOncePerInstance is called.
In the comments the author, Gene Chuang, says "HotSpot 2.0 mangles the order
if synchronized block is removed". Later on he goes on to say:
"The reason why I synchronize this block of code is because I expect
initializeOncePerBeanClass() to always be called before
initializeOncePerInstance() for I have services in the former method that
will be used by the latter. And without this synchronization block, in a
multi-threaded SMP environment, I've seen some heinously mangled call
orders! "
I could discuss his findings on the discussion thread there at
theserverside.com, but here is a much better forum for such matters :-) We
should post the conclusion of our findings on that list for the benefit of
theserverside.com viewers.
My comments on Gene Chuang's code and finings follow:
First of all, isInstanceInitialized is not needed since this method is
guaranteed to be called exactly once. The method initializeEveryContextSwap
is not needed too. As far as synchronization... it seems to me that he
needed to synchronize not for the reason he said (HotSpot 2.0 weirdness),
but because he is accessing a shared datastructure (the static
initializedBeanClasses HashSet) in a multithreaded manner. I beleive his
code to still be in error because if there are more than one subclasses of
AbstractEJBean, then multiple threads might access that shared datastructure
because each thread would aquire a different lock (being the class of the
instance of the subclass extending AbstractEJBean).
What I would do is this:
public abstract class AbstractEJBean
{
// Collections.synchronizedSet is sufficient
private static Set initializedBeanClasses =
Collections.synchronizedSet(new HashSet());
// added a final
final protected void onSetEJBContext()
{
boolean added= initializedBeanClasses.add(this.getClass());
if (added)
initializeOncePerBeanClass();
initializeOncePerInstance();
}
Can someone on this list please comment on my findings?
-- David Smiley
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:32 EDT