StatefulContainerInvocation ejb = (StatefulContainerInvocation) invocation;
Object id = ejb.getId();
StatefulContainer container = (StatefulContainer) ejb.getAdvisor();
StatefulBeanContext target = container.getCache().get(id);
boolean block = container.resolveAnnotation(SerializedConcurrentAccess.class) != null;
if (block)
{
target.getLock().lockInterruptibly();
}
else
{
synchronized (target)
{
if (target.isInInvocation()) throw new ConcurrentAccessException("no concurrent calls on stateful bean '" + container.getName() + "' (EJB3 4.3.13)");
target.setInInvocation(true);
}
}
ejb.setTargetObject(target.getInstance());
ejb.setBeanContext(target);
StatefulBeanContext.currentBean.push(target);
try
{
if (target.isDiscarded()) throw new EJBException("SFSB was discarded by another thread");
return ejb.invokeNext();
}
catch (Exception ex)
{
if (isApplicationException(ex.getClass(), container)) throw ex;
if (ex instanceof RuntimeException
|| ex instanceof RemoteException)
{
container.getCache().remove(id);
target.setDiscarded(true);
}
throw ex;
}
finally
{
StatefulBeanContext.currentBean.pop();
synchronized (target)
{
target.setInInvocation(false);
if (!target.isTxSynchronized() && !target.isDiscarded()) container.getCache().finished(target);
if (block) target.getLock().unlock();
}
}