Hi,

When doing simultaneous calls to the same stateful
session bean I sometimes get a RemoteException:
"Application Error: tried to enter Stateful bean with
different transaction context"
 
This exception is correct; that is exactly what I am
trying to do. In current CVS this is thrown from
StatefulSessionInstanceInterceptor line 169.
However, I would prefer that this exception not be
thrown, and the InstanceInterceptor instead wait
until the current invocation is finished.
 
Looking into the source, I see no easy fix apart
for a busy-wait loop (and a busy-wait loop is IMHO
too expensive here).
Not seeing an easy fix, and knowing that this does
not happen with entity beans, I turn to see how this
is done in EntityInstanceInterceptor. To my horror
this looks like it _is_ using a busy-wait.
IMO Simon has done a fine job on the cache and locking
issues, but maybe there is still a to-do here?
 
One way to fix this could be to add some extra method
to EnterpriseContext that will wait until the
conditions for continuing are present. This would be
natural since these conditions are part of the
EnterpriseContext.
For both stateful session and entity we want to wait
if the call is re-entrant (StatefulSessionInstance-
Interceptor line 189, and EntityInstanceInterceptor
line 162), and we want to wait until the context
transaction is null or the same as the MI transaction
(StatefulSessionInstanceInterceptor line 169, and
EntityInstanceInterceptor line 140).
 
So my proposal is:
A new method is added to the EnterpriseContext with
this signature:
  void waitTxReentry(Transaction tx);
This method is only used with CMT. It will wait
until the context transaction is null or it equals
the tx argument.
Another new method is added to EnterpriseContext with
signature:
  void waitNotLocked();
A call to this method will wait until the context is
not locked.
For both methods it is not guaranteed that the
condition is true on return, so rechecking like is
currently done in EntityInstanceInterceptor is needed.
Their implementation can be done with the good old
wait()-notifyAll() primitives.
In both StatefulSessionInstanceInterceptor and Entity-
InstanceInterceptor a loop like in EntityInstance-
Interceptor is used for retrying. The calls to the
new EnterpriseContext methods are wrapped in a temporary
release of the mutex, like:
  mutex.release();
  try {
    ctx.waitNotLocked();
  } finally {
    mutex.aquire();
  }

This is just a very quick analysis and fix proposal.
Does the mutex really need to be released while waiting?
Could this be done in some better way?


Best Regards,

Ole Husgaard.

Reply via email to