package org.jboss.ejb.plugins;
import java.util.Hashtable;
import java.rmi.RemoteException;
import javax.transaction.Transaction;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.RefAddr;
import javax.naming.spi.ObjectFactory;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.AllowedOperationsAssociation;
import org.jboss.invocation.Invocation;
abstract class AbstractTxInterceptorBMT
extends AbstractTxInterceptor
{
private ThreadLocal userTransaction = new ThreadLocal();
protected boolean stateless = true;
public void create()
throws Exception
{
super.create();
RefAddr refAddr = new RefAddr("userTransaction") {
public Object getContent() {
return userTransaction;
}
};
Reference ref = new Reference("javax.transaction.UserTransaction",
refAddr,
new UserTxFactory().getClass().getName(),
null);
((Context)new InitialContext().lookup("java:comp/")).bind("UserTransaction", ref);
}
public void stop()
{
try {
((Context)new InitialContext().lookup("java:comp/")).unbind("UserTransaction");
} catch (Exception e) {
}
}
protected Object invokeNext(Invocation mi)
throws Exception
{
Transaction oldTransaction = mi.getTransaction();
Object oldUserTx = userTransaction.get();
Transaction threadTx = tm.suspend();
try {
EnterpriseContext ctx = ((EnterpriseContext) mi.getEnterpriseContext());
try
{
AllowedOperationsAssociation.pushInMethodFlag(IN_INTERCEPTOR_METHOD);
userTransaction.set(ctx.getEJBContext().getUserTransaction());
}
finally
{
AllowedOperationsAssociation.popInMethodFlag();
}
Transaction beanTx = ctx.getTransaction();
if (beanTx != null)
tm.resume(beanTx);
mi.setTransaction(beanTx);
try {
return super.invokeNext(mi, false);
} finally {
try {
if (stateless)
checkStatelessDone();
} finally {
tm.suspend();
}
}
} finally {
userTransaction.set(oldUserTx);
mi.setTransaction(oldTransaction);
if (threadTx != null)
tm.resume(threadTx);
}
}
private void checkStatelessDone()
throws RemoteException
{
int status = Status.STATUS_NO_TRANSACTION;
try {
status = tm.getStatus();
} catch (SystemException ex) {
log.error("Failed to get status", ex);
}
switch (status) {
case Status.STATUS_ACTIVE:
case Status.STATUS_COMMITTING:
case Status.STATUS_MARKED_ROLLBACK:
case Status.STATUS_PREPARING:
case Status.STATUS_ROLLING_BACK:
try {
tm.rollback();
} catch (Exception ex) {
log.error("Failed to rollback", ex);
}
case Status.STATUS_PREPARED:
String msg = "Application error: BMT stateless bean " +
container.getBeanMetaData().getEjbName() +
" should complete transactions before" +
" returning (ejb1.1 spec, 11.6.1)";
log.error(msg);
throw new RemoteException(msg);
}
}
public static class UserTxFactory
implements ObjectFactory
{
public Object getObjectInstance(Object ref, Name name,
Context nameCtx, Hashtable environment)
throws Exception
{
RefAddr refAddr = ((Reference)ref).get(0);
ThreadLocal threadLocal = (ThreadLocal)refAddr.getContent();
return threadLocal.get();
}
}
}