Skip to content

Commit

Permalink
Refactor the tx interceptors to move away from TransactionalInvocatio…
Browse files Browse the repository at this point in the history
…nContext
  • Loading branch information
jaikiran committed Feb 16, 2011
1 parent 1c3dcc0 commit 86611bd
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 120 deletions.
26 changes: 16 additions & 10 deletions tx/impl/src/main/java/org/jboss/ejb3/tx2/impl/BMTInterceptor.java
Expand Up @@ -21,16 +21,17 @@
*/
package org.jboss.ejb3.tx2.impl;

import org.jboss.ejb3.tx2.spi.TransactionalInvocationContext;
import org.jboss.ejb3.tx2.spi.TransactionalComponent;
import org.jboss.logging.Logger;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

/**
* Suspend an incoming tx.
*
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author <a href="mailto:osh@sparre.dk">Ole Husgaard</a>
* @author <a href="cdewolf@redhat.com">Carlo de Wolf</a>
Expand All @@ -39,26 +40,31 @@ public abstract class BMTInterceptor
{
private static final Logger log = Logger.getLogger(BMTInterceptor.class);

protected final TransactionManager tm;

protected BMTInterceptor(TransactionManager tm)
{
this.tm = tm;
}
protected abstract TransactionalComponent getTransactionalComponent();

protected abstract Object handleInvocation(TransactionalInvocationContext invocation) throws Exception;
protected abstract Object handleInvocation(InvocationContext invocation) throws Exception;

@AroundInvoke
public Object invoke(TransactionalInvocationContext invocation) throws Exception
public Object invoke(InvocationContext invocation) throws Exception
{
TransactionManager tm = this.getTransactionManager();
Transaction oldTx = tm.suspend();
try
{
return handleInvocation(invocation);
}
finally
{
if (oldTx != null) tm.resume(oldTx);
if (oldTx != null)
{
tm.resume(oldTx);
}
}
}

protected TransactionManager getTransactionManager()
{
return this.getTransactionalComponent().getTransactionManager();
}
}
123 changes: 72 additions & 51 deletions tx/impl/src/main/java/org/jboss/ejb3/tx2/impl/CMTTxInterceptor.java
Expand Up @@ -21,54 +21,55 @@
*/
package org.jboss.ejb3.tx2.impl;

import org.jboss.ejb3.tx2.spi.TransactionalInvocationContext;
import org.jboss.ejb3.tx2.spi.TransactionalComponent;
import org.jboss.logging.Logger;
import org.jboss.tm.TransactionTimeoutConfiguration;
import org.jboss.util.deadlock.ApplicationDeadlockException;

import javax.annotation.Resource;
import javax.ejb.ApplicationException;
import javax.ejb.EJBException;
import javax.ejb.EJBTransactionRequiredException;
import javax.ejb.EJBTransactionRolledbackException;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.Random;

/**
* Ensure the correct exceptions are thrown based on both caller
* transactional context and supported Transaction Attribute Type
*
* <p/>
* EJB3 13.6.2.6
* EJB3 Core Specification 14.3.1 Table 14
*
* @author <a href="mailto:andrew.rubinger@redhat.com">ALR</a>
* @author <a href="mailto:cdewolf@redhat.com">Carlo de Wolf</a>
*/
public class CMTTxInterceptor
public abstract class CMTTxInterceptor
{
private static final Logger log = Logger.getLogger(CMTTxInterceptor.class);

private static final int MAX_RETRIES = 5;
private static final Random RANDOM = new Random();

private TransactionManager tm;
protected abstract TransactionalComponent getTransactionalComponent();

/**
* The <code>endTransaction</code> method ends a transaction and
* translates any exceptions into
* TransactionRolledBack[Local]Exception or SystemException.
*
* @param tm a <code>TransactionManager</code> value
* @param tx a <code>Transaction</code> value
* @param tm a <code>TransactionManager</code> value
* @param tx a <code>Transaction</code> value
*/
protected void endTransaction(TransactionManager tm, Transaction tx)
{
Expand Down Expand Up @@ -112,7 +113,8 @@ protected void endTransaction(TransactionManager tm, Transaction tx)

protected int getCurrentTransactionTimeout() throws SystemException
{
if(tm instanceof TransactionTimeoutConfiguration)
TransactionManager tm = this.getTransactionManager();
if (tm instanceof TransactionTimeoutConfiguration)
{
return ((TransactionTimeoutConfiguration) tm).getTransactionTimeout();
}
Expand All @@ -121,26 +123,30 @@ protected int getCurrentTransactionTimeout() throws SystemException

protected void handleEndTransactionException(Exception e)
{
if(e instanceof RollbackException)
if (e instanceof RollbackException)
{
throw new EJBTransactionRolledbackException("Transaction rolled back", e);
}
throw new EJBException(e);
}

protected void handleInCallerTx(TransactionalInvocationContext invocation, Throwable t, Transaction tx) throws Exception
protected void handleInCallerTx(InvocationContext invocation, Throwable t, Transaction tx) throws Exception
{
ApplicationException ae = invocation.getApplicationException(t.getClass());

ApplicationException ae = this.getApplicationException(t.getClass());
if (ae != null)
{
if (ae.rollback()) setRollbackOnly(tx);
if (ae.rollback())
{
setRollbackOnly(tx);
}
// an app exception can never be an Error
throw (Exception) t;
}

// if it's not EJBTransactionRolledbackException
if(!(t instanceof EJBTransactionRolledbackException))
if (!(t instanceof EJBTransactionRolledbackException))
{
if(t instanceof Error)
if (t instanceof Error)
{
//t = new EJBTransactionRolledbackException(formatException("Unexpected Error", t));
Throwable cause = t;
Expand All @@ -153,7 +159,7 @@ else if (t instanceof EJBException || t instanceof RemoteException)
// Leave Exception as-is (this is in place to handle specifically, and not
// as a generic RuntimeException
}
else if(t instanceof RuntimeException)
else if (t instanceof RuntimeException)
{
t = new EJBTransactionRolledbackException(t.getMessage(), (Exception) t);
}
Expand All @@ -168,20 +174,23 @@ else if(t instanceof RuntimeException)
throw (Exception) t;
}

public void handleExceptionInOurTx(TransactionalInvocationContext invocation, Throwable t, Transaction tx) throws Exception
public void handleExceptionInOurTx(InvocationContext invocation, Throwable t, Transaction tx) throws Exception
{
ApplicationException ae = invocation.getApplicationException(t.getClass());
ApplicationException ae = this.getApplicationException(t.getClass());
if (ae != null)
{
if (ae.rollback()) setRollbackOnly(tx);
if (ae.rollback())
{
setRollbackOnly(tx);
}
throw (Exception) t;
}

// if it's neither EJBException nor RemoteException
if(!(t instanceof EJBException || t instanceof RemoteException))
if (!(t instanceof EJBException || t instanceof RemoteException))
{
// errors and unchecked are wrapped into EJBException
if(t instanceof Error)
if (t instanceof Error)
{
//t = new EJBException(formatException("Unexpected Error", t));
Throwable cause = t;
Expand All @@ -190,7 +199,7 @@ public void handleExceptionInOurTx(TransactionalInvocationContext invocation, Th
}
else if (t instanceof RuntimeException)
{
t = new EJBException((Exception)t);
t = new EJBException((Exception) t);
}
else
{
Expand All @@ -204,10 +213,11 @@ else if (t instanceof RuntimeException)
}

@AroundInvoke
public Object invoke(TransactionalInvocationContext invocation) throws Exception
public Object invoke(InvocationContext invocation) throws Exception
{
TransactionAttributeType attr = invocation.getTransactionAttribute();
switch(attr)
Method invokedMethod = invocation.getMethod();
TransactionAttributeType txAttr = this.getTransactionalComponent().getTransactionAttributeType(invokedMethod);
switch (txAttr)
{
case MANDATORY:
return mandatory(invocation);
Expand All @@ -222,11 +232,11 @@ public Object invoke(TransactionalInvocationContext invocation) throws Exception
case SUPPORTS:
return supports(invocation);
default:
throw new IllegalStateException("Unexpected tx attribute " + attr + " on " + invocation);
throw new IllegalStateException("Unexpected tx attribute " + txAttr + " on " + invocation);
}
}

protected Object invokeInCallerTx(TransactionalInvocationContext invocation, Transaction tx) throws Exception
protected Object invokeInCallerTx(InvocationContext invocation, Transaction tx) throws Exception
{
try
{
Expand All @@ -239,12 +249,12 @@ protected Object invokeInCallerTx(TransactionalInvocationContext invocation, Tra
throw new RuntimeException("UNREACHABLE");
}

protected Object invokeInNoTx(TransactionalInvocationContext invocation) throws Exception
protected Object invokeInNoTx(InvocationContext invocation) throws Exception
{
return invocation.proceed();
}

protected Object invokeInOurTx(TransactionalInvocationContext invocation, TransactionManager tm) throws Exception
protected Object invokeInOurTx(InvocationContext invocation, TransactionManager tm) throws Exception
{
for (int i = 0; i < MAX_RETRIES; i++)
{
Expand Down Expand Up @@ -287,8 +297,9 @@ protected Object invokeInOurTx(TransactionalInvocationContext invocation, Transa
throw new RuntimeException("UNREACHABLE");
}

protected Object mandatory(TransactionalInvocationContext invocation) throws Exception
protected Object mandatory(InvocationContext invocation) throws Exception
{
TransactionManager tm = this.getTransactionManager();
Transaction tx = tm.getTransaction();
if (tx == null)
{
Expand All @@ -297,17 +308,19 @@ protected Object mandatory(TransactionalInvocationContext invocation) throws Exc
return invokeInCallerTx(invocation, tx);
}

protected Object never(TransactionalInvocationContext invocation) throws Exception
protected Object never(InvocationContext invocation) throws Exception
{
TransactionManager tm = this.getTransactionManager();
if (tm.getTransaction() != null)
{
throw new EJBException("Transaction present on server in Never call (EJB3 13.6.2.6)");
}
return invokeInNoTx(invocation);
}

protected Object notSupported(TransactionalInvocationContext invocation) throws Exception
protected Object notSupported(InvocationContext invocation) throws Exception
{
TransactionManager tm = this.getTransactionManager();
Transaction tx = tm.getTransaction();
if (tx != null)
{
Expand All @@ -319,7 +332,7 @@ protected Object notSupported(TransactionalInvocationContext invocation) throws
catch (Exception e)
{
// If application exception was thrown, rethrow
if(invocation.getApplicationException(e.getClass()) != null)
if (this.getApplicationException(e.getClass()) != null)
{
throw e;
}
Expand All @@ -337,14 +350,15 @@ protected Object notSupported(TransactionalInvocationContext invocation) throws
else
{
return invokeInNoTx(invocation);
}
}
}

protected Object required(TransactionalInvocationContext invocation) throws Exception
protected Object required(InvocationContext invocation) throws Exception
{
int oldTimeout = getCurrentTransactionTimeout();
int timeout = invocation.getTransactionTimeout();

Method invokedMethod = invocation.getMethod();
int timeout = this.getTransactionalComponent().getTransactionTimeout(invokedMethod);
TransactionManager tm = this.getTransactionManager();
try
{
if (timeout != -1 && tm != null)
Expand All @@ -369,14 +383,15 @@ protected Object required(TransactionalInvocationContext invocation) throws Exce
{
tm.setTransactionTimeout(oldTimeout);
}
}
}
}

protected Object requiresNew(TransactionalInvocationContext invocation) throws Exception
protected Object requiresNew(InvocationContext invocation) throws Exception
{
int oldTimeout = getCurrentTransactionTimeout();
int timeout = invocation.getTransactionTimeout();

Method invokedMethod = invocation.getMethod();
int timeout = this.getTransactionalComponent().getTransactionTimeout(invokedMethod);
TransactionManager tm = this.getTransactionManager();
try
{
if (timeout != -1 && tm != null)
Expand Down Expand Up @@ -408,7 +423,7 @@ protected Object requiresNew(TransactionalInvocationContext invocation) throws E
{
tm.setTransactionTimeout(oldTimeout);
}
}
}
}

/**
Expand All @@ -434,15 +449,10 @@ protected void setRollbackOnly(Transaction tx)
}
}

@Resource
public void setTransactionManager(TransactionManager tm)
{
this.tm = tm;
}

protected Object supports(TransactionalInvocationContext invocation) throws Exception

protected Object supports(InvocationContext invocation) throws Exception
{
Transaction tx = tm.getTransaction();
Transaction tx = this.getTransactionManager().getTransaction();
if (tx == null)
{
return invokeInNoTx(invocation);
Expand All @@ -452,4 +462,15 @@ protected Object supports(TransactionalInvocationContext invocation) throws Exce
return invokeInCallerTx(invocation, tx);
}
}

private TransactionManager getTransactionManager()
{
return this.getTransactionalComponent().getTransactionManager();
}

private ApplicationException getApplicationException(Class<?> exceptionClass)
{
TransactionalComponent txComponent = this.getTransactionalComponent();
return txComponent.getApplicationException(exceptionClass);
}
}

0 comments on commit 86611bd

Please sign in to comment.