public Object invoke(Invocation mi)
throws Exception
{
// We are going to work with the context a lot
EntityEnterpriseContext ctx = (EntityEnterpriseContext) mi.getEnterpriseContext();
boolean nonReentrant = !(reentrant || isReentrantMethod(mi));
// Not a reentrant method like getPrimaryKey
NonReentrantLock methodLock = ctx.getMethodLock();
Transaction miTx = ctx.getTransaction();
boolean locked = false;
try
{
while (!locked)
{
if (methodLock.attempt(5000, miTx, nonReentrant))
{
locked = true;
}
else
{
if (isTxExpired(miTx))
{
log.error("Saw rolled back tx=" + miTx);
throw new RuntimeException("Transaction marked for rollback, possibly a timeout");
}
}
}
}
catch (NonReentrantLock.ReentranceException re)
{
if (mi.getType() == InvocationType.REMOTE)
{
throw new RemoteException("Reentrant method call detected: "
+ container.getBeanMetaData().getEjbName() + " "
+ ctx.getId().toString());
}
else
{
throw new EJBException("Reentrant method call detected: "
+ container.getBeanMetaData().getEjbName() + " "
+ ctx.getId().toString());
}
}
try
{
ctx.lock();
return getNext().invoke(mi);
}
finally
{
ctx.unlock();
methodLock.release(nonReentrant);
}
}