User: azakkerman
Date: 01/05/22 15:12:57
Modified: src/main/org/jboss/ejb/plugins TxInterceptorBMT.java
TxInterceptorCMT.java
Log:
Initial commit of Tyrex distributed transaction manager support in JBoss. Support
added for using JBoss with any TM that supports javax.transaction.TransactionManager
interface.
Revision Changes Path
1.16 +125 -102 jboss/src/main/org/jboss/ejb/plugins/TxInterceptorBMT.java
Index: TxInterceptorBMT.java
===================================================================
RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptorBMT.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- TxInterceptorBMT.java 2001/05/16 20:44:16 1.15
+++ TxInterceptorBMT.java 2001/05/22 22:12:57 1.16
@@ -51,63 +51,64 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
* @author Peter Antman ([EMAIL PROTECTED])
-* @version $Revision: 1.15 $
+* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
+* @version $Revision: 1.16 $
*/
public class TxInterceptorBMT
extends AbstractInterceptor
{
-
+
// Attributes ----------------------------------------------------
// Protected to be able to inherit, pra
protected TxManager tm;
-
+
// lookup on java:comp/UserTransaction should be redirected to
// sessionContext.getUserTransaction()
- // The ThreadLocal associates the thread to the UserTransaction
- ThreadLocal userTransaction = new ThreadLocal();
-
+ // The ThreadLocal associates the thread to the UserTransaction
+ ThreadLocal userTransaction = new ThreadLocal();
+
protected Container container;
// Static --------------------------------------------------------
-
+
// Constructors --------------------------------------------------
-
+
// Public --------------------------------------------------------
public void setContainer(Container container)
{
this.container = container;
}
-
+
public Container getContainer()
{
return container;
}
-
+
// Interceptor implementation --------------------------------------
public void init()
throws Exception
{
// Store TM reference locally
tm = (TxManager) getContainer().getTransactionManager();
-
+
// bind java:comp/UserTransaction
RefAddr refAddr = new RefAddr("userTransaction") {
public Object getContent() {
return userTransaction;
}
};
-
- Reference ref = new Reference("javax.transaction.UserTransaction",
- refAddr,
- new UserTxFactory().getClass().getName(),
+
+ 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
+ try
{
((Context)new
InitialContext().lookup("java:comp/")).unbind("UserTransaction");
}
@@ -123,31 +124,34 @@
// set the threadlocal to the userTransaction of the instance
// (mi has the sessioncontext from the previous interceptor)
if (((SessionMetaData)container.getBeanMetaData()).isStateful()) {
-
+
// Save old userTx
Object oldUserTx = userTransaction.get();
-
+
// retrieve the real userTransaction
userTransaction.set(((StatefulSessionEnterpriseContext)mi.getEnterpriseContext()).getSessionContext().getUserTransaction());
-
+
// t1 refers to the client transaction (spec ejb1.1, 11.6.1, p174)
// this is necessary for optimized (inVM) calls: threads come
associated with the client transaction
- Transaction t1 = tm.disassociateThread();
-
- // t2 refers to the instance transaction (spec ejb1.1, 11.6.1, p174)
+ Transaction t1 = tm.getTransaction();
+
+ // t2 refers to the instance transaction (spec ejb1.1, 11.6.1, p174)
Transaction t2 = mi.getEnterpriseContext().getTransaction();
-
+
try {
-
- if (t2 != null) {
-
- // associate the transaction to the thread
- tm.associateThread(t2);
-
+
+ if (t2 == null) {
+ tm.suspend();
}
-
+ else if (! t2.equals(t1) ){
+ tm.suspend();
+ // associate the transaction to the thread
+ tm.resume(t2);
+
+ } // else we are in the proper tx context
+
return getNext().invokeHome(mi);
-
+
} catch (RuntimeException e)
{
// EJB 2.0 17.3, table 16
@@ -157,12 +161,12 @@
} catch (IllegalStateException ex) {
}
}
-
+
if (e instanceof EJBException) {
throw new ServerException("Transaction rolled back",
- ((EJBException)
e).getCausedByException());
+ ((EJBException)
e).getCausedByException());
} else {
- throw new ServerException("Transaction rolled back", e);
+ throw new ServerException("Transaction rolled back", e);
}
} catch (RemoteException e)
{
@@ -173,8 +177,8 @@
} catch (IllegalStateException ex) {
}
}
-
- throw new ServerException("Transaction rolled back", e);
+
+ throw new ServerException("Transaction rolled back", e);
} catch (Error e)
{
// EJB 2.0 17.3, table 16
@@ -184,30 +188,34 @@
} catch (IllegalStateException ex) {
}
}
-
- throw new ServerException("Transaction rolled
back:"+e.getMessage());
+
+ throw new ServerException("Transaction rolled
back:"+e.getMessage());
} finally {
-
+
// Reset user Tx
userTransaction.set(oldUserTx);
-
- if (t1 != null) {
-
- // reassociate the previous transaction before returning
- tm.associateThread(t1);
-
+
+ Transaction currentTx = tm.getTransaction();
+ if (t1 == null) {
+ tm.suspend();
}
+ else if (! t1.equals(currentTx)) {
+
+ tm.suspend();
+ // reassociate the previous transaction before returning
+ tm.resume(t1);
+ } // else we are in the right tx context, do nothing
}
} else {
-
+
// stateless: no context, no transaction, no call to the instance
-
+
return getNext().invokeHome(mi);
}
-
-
+
+
}
-
+
/**
* This method does invocation interpositioning of tx management
*
@@ -221,46 +229,52 @@
// Store old UserTX
Object oldUserTx = userTransaction.get();
-
+
// set the threadlocal to the userTransaction of the instance
// (mi has the sessioncontext from the previous interceptor)
if (((SessionMetaData)container.getBeanMetaData()).isStateful()) {
-
+
// retrieve the real userTransaction
userTransaction.set(((StatefulSessionEnterpriseContext)mi.getEnterpriseContext()).getSessionContext().getUserTransaction());
-
+
} else {
-
+
// retrieve the real userTransaction
userTransaction.set(((StatelessSessionEnterpriseContext)mi.getEnterpriseContext()).getSessionContext().getUserTransaction());
}
-
-
+
+
// t1 refers to the client transaction (spec ejb1.1, 11.6.1, p174)
// this is necessary for optimized (inVM) calls: threads come associated
with the client transaction
- Transaction t1 = tm.disassociateThread();
-
+ Transaction t1 = tm.getTransaction();
+
//DEBUG Logger.debug("TxInterceptorBMT disassociate" + ((t1==null) ? "null":
Integer.toString(t1.hashCode())));
-
- // t2 refers to the instance transaction (spec ejb1.1, 11.6.1, p174)
+
+ // t2 refers to the instance transaction (spec ejb1.1, 11.6.1, p174)
Transaction t2 = mi.getEnterpriseContext().getTransaction();
-
+
// This is BMT so the transaction is dictated by the Bean, the
MethodInvocation follows
mi.setTransaction(t2);
-
+
//DEBUG Logger.debug("TxInterceptorBMT t2 in context" + ((t2==null) ? "null":
Integer.toString(t2.hashCode())));
-
+
try {
-
- if (t2 != null) {
-
+
+ if (t2 == null) {
+
+ tm.suspend();
+ }
+ else if ( ! t2.equals(t1) ) {
+
+ tm.suspend();
// associate the transaction to the thread
- tm.associateThread(t2);
-
+ tm.resume(t2);
+
}
-
+ // else we are in the right tx context
+
return getNext().invoke(mi);
-
+
} catch (RuntimeException e)
{
// EJB 2.0 17.3, table 16
@@ -270,7 +284,7 @@
} catch (IllegalStateException ex) {
}
}
-
+
if (e instanceof EJBException) {
throw new ServerException("Transaction rolled back",
((EJBException)
e).getCausedByException());
@@ -286,8 +300,8 @@
} catch (IllegalStateException ex) {
}
}
-
- throw new ServerException("Transaction rolled back", e);
+
+ throw new ServerException("Transaction rolled back", e);
} catch (Error e)
{
// EJB 2.0 17.3, table 16
@@ -297,70 +311,79 @@
} catch (IllegalStateException ex) {
}
}
-
- throw new ServerError("Transaction rolled back", e);
+
+ throw new ServerError("Transaction rolled back", e);
} finally {
-
+
// Reset user Tx
userTransaction.set(oldUserTx);
-
+
//DEBUG Logger.debug("TxInterceptorBMT reassociating client tx " +
//DEBUG (t1==null?"null":String.valueOf(t1.hashCode())));
-
- // reassociate the previous transaction before returning,
- // even if it was null
- tm.associateThread(t1);
-
+
+
+ Transaction currentTx = tm.getTransaction();
+ if (t1 == null) {
+
+ tm.suspend();
+ }
+ else if (! t1.equals(currentTx)) {
+
+ tm.suspend();
+ // reassociate the previous transaction before returning
+ tm.resume(t1);
+ } // else we are in the right tx context, do nothing
+
if (((SessionMetaData)container.getBeanMetaData()).isStateless()) {
// t3 is the transaction associated with the context at the end of
the call
Transaction t3 = mi.getEnterpriseContext().getTransaction();
-
+
//DEBUG Logger.debug("in TxIntBMT " + t3);
-
+
// for a stateless sessionbean the transaction should be completed
at the end of the call
if (t3 != null) switch (t3.getStatus()) {
- case Status.STATUS_ACTIVE:
- case Status.STATUS_COMMITTING:
- case Status.STATUS_MARKED_ROLLBACK:
- case Status.STATUS_PREPARING:
+ case Status.STATUS_ACTIVE:
+ case Status.STATUS_COMMITTING:
+ case Status.STATUS_MARKED_ROLLBACK:
+ case Status.STATUS_PREPARING:
case Status.STATUS_ROLLING_BACK:
-
+
t3.rollback();
-
- case Status.STATUS_PREPARED:
-
+
+ case Status.STATUS_PREPARED:
+
// cf ejb1.1 11.6.1
Logger.error("Application error: BMT stateless bean " +
container.getBeanMetaData().getEjbName() + " should complete transactions before
returning (ejb1.1 spec, 11.6.1)");
-
+
// the instance interceptor will discard the instance
throw new RemoteException("Application error: BMT stateless
bean " + container.getBeanMetaData().getEjbName() + " should complete transactions
before returning (ejb1.1 spec, 11.6.1)");
}
}
}
}
-
+
// Protected ----------------------------------------------------
-
+
// Inner classes -------------------------------------------------
-
+
public static class UserTxFactory implements ObjectFactory {
public Object getObjectInstance(Object ref,
Name name,
Context nameCtx,
Hashtable environment)
- throws Exception
+ throws Exception
{
-
+
// the ref is a list with only one refAddr whose content is the
threadlocal
ThreadLocal threadLocal =
(ThreadLocal)((Reference)ref).get(0).getContent();
-
+
// the threadlocal holds the UserTransaction
// we can now return the userTx, calls on it will indirect on the right
context
return threadLocal.get();
-
+
}
}
-
+
}
1.10 +274 -155 jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java
Index: TxInterceptorCMT.java
===================================================================
RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- TxInterceptorCMT.java 2000/12/07 15:44:25 1.9
+++ TxInterceptorCMT.java 2001/05/22 22:12:57 1.10
@@ -26,7 +26,6 @@
import org.jboss.ejb.Container;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.MethodInvocation;
-import org.jboss.tm.TxManager;
import org.jboss.logging.Logger;
import org.jboss.metadata.MetaData;
@@ -40,52 +39,53 @@
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
-* @version $Revision: 1.9 $
+* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
+* @version $Revision: 1.10 $
*/
public class TxInterceptorCMT
extends AbstractInterceptor
{
-
+
// Attributes ----------------------------------------------------
- private TxManager tm;
+ private TransactionManager tm;
private HashMap methodTx = new HashMap();
-
+
protected Container container;
// Static --------------------------------------------------------
-
+
// Constructors --------------------------------------------------
-
+
// Public --------------------------------------------------------
public void setContainer(Container container)
{
this.container = container;
}
-
+
public Container getContainer()
{
return container;
}
-
+
// Interceptor implementation --------------------------------------
public void init()
throws Exception
{
// Store TM reference locally
- tm = (TxManager) getContainer().getTransactionManager();
-
+ tm = (TransactionManager) getContainer().getTransactionManager();
+
// Find out method->tx-type mappings from meta-info
// EnterpriseBean eb = getContainer.getMetaData();
// eb.getBeanContext()
}
-
+
public Object invokeHome(MethodInvocation mi)
throws Exception
{
return runWithTransactions(false, mi);
}
-
+
/**
* This method does invocation interpositioning of tx management
*
@@ -98,7 +98,7 @@
public Object invoke(MethodInvocation mi) throws Exception {
return runWithTransactions(true, mi);
}
-
+
private void printMethod(Method m, byte type) {
String name;
switch(type) {
@@ -125,7 +125,7 @@
}
//DEBUG Logger.debug(name+" for "+m.getName());
}
-
+
private Object invokeNext(boolean remoteInvocation, MethodInvocation mi) throws
Exception {
try
{
@@ -185,131 +185,168 @@
// This exception will be transformed into a
RemoteException by the LogInterceptor
throw e;
}
- }
+ }
}
-
+
/*
* runWithTransactions
*
* This is where the meat is. We define what to do with the Tx based on the
declaration.
- * The MethodInvocation is always the final authority on what the Tx looks like
leaving this
+ * The MethodInvocation is always the final authority on what the Tx looks like
leaving this
* interceptor. In other words, interceptors down the chain should not rely on
the thread
* association with Tx but on the Tx present in the MethodInvocation
*/
-
+
private Object runWithTransactions(boolean remoteInvocation, MethodInvocation
mi) throws Exception {
-
+
+ // Thread transaction is the transaction that the
+ // current thread came in with
+ Transaction threadTransaction = tm.getTransaction();
// Old transaction is the transaction that comes with the MI
Transaction oldTransaction = mi.getTransaction();
// New transaction is the new transaction this might start
Transaction newTransaction = null;
-
- //DEBUG Logger.debug("Current transaction in MI is
"+mi.getTransaction());
- //DEBUG Logger.debug("Current method "+mi.getMethod());
+
+ // Indicates if the call was made already
+ // in the context of the right transaction
+ boolean optimized = ( (threadTransaction != null) &&
+ (oldTransaction != null) &&
+ (threadTransaction.equals(oldTransaction)) );
+
+ //DEBUG Logger.debug("Current transaction in MI is
"+mi.getTransaction());
+ //DEBUG Logger.debug("Current thread transaction is
"+threadTransaction);
+ //DEBUG Logger.debug("Current method "+mi.getMethod());
byte transType = getTransactionMethod(mi.getMethod(), remoteInvocation);
-
+
printMethod(mi.getMethod(), transType);
-
+
switch (transType) {
-
- case MetaData.TX_NOT_SUPPORTED:
+
+ case MetaData.TX_NOT_SUPPORTED:
{
-
-
+ //DEBUG Logger.debug("TX_NOT_SUPPORTED
begin");
// Thread arriving must be clean (jboss doesn't set the thread
previously)
// However optimized calls come with associated thread for
example
- Transaction threadTx = tm.disassociateThread();
-
+ if (threadTransaction != null) {
+ //DEBUG Logger.debug("Suspending
current thread transaction");
+ tm.suspend();
+ }
+
try {
-
+
// Do not set a transaction on the thread even if in MI,
just run
return invokeNext(remoteInvocation,mi );
}
finally {
-
+
// IN case we had a Tx associated with the thread
reassociate
- if (threadTx != null) {
-
- tm.associateThread(threadTx);
+ if (threadTransaction != null) {
+ //DEBUG
Logger.debug("Resuming original thread transaction");
+ tm.resume(threadTransaction);
}
+ //DEBUG
Logger.debug("TX_NOT_SUPPORTED end");
}
}
-
-
- case MetaData.TX_REQUIRED:
+
+
+ case MetaData.TX_REQUIRED:
{
-
+ //DEBUG Logger.debug("TX_REQUIRED begin");
+
if (oldTransaction == null) { // No tx running
-
- // Create tx
+
+ if (threadTransaction != null) {
+ //DEBUG
Logger.debug("Suspending current thread transaction");
+ tm.suspend();
+ }
+
+ //DEBUG Logger.debug("Starting new
transaction");
+ // Create tx
tm.begin();
-
+
// get the tx
newTransaction = tm.getTransaction();
-
+
// Let the method invocation know
- mi.setTransaction(newTransaction);
+ mi.setTransaction(newTransaction);
}
-
+
else { // We have a tx propagated
-
- // Associate it with the thread
- tm.associateThread(oldTransaction);
+
+ // are we in optimized tx context?
+ if ( ! optimized ) {
+ // the incoming thread is not optimized, so
+ // suspend its transaction
+ // DEBUG
Logger.debug("Suspending current thread transaction");
+ tm.suspend();
+ // Associate the propagated tx with the thread
+ // DEBUG
Logger.debug("Resuming propagated transaction");
+ tm.resume(oldTransaction);
+ }
+ /*
+ else {
+ //DEBUG
+ Logger.debug("Optimized call -- current transaction
same as propagated");
+ }
+ */
}
-
+
// Continue invocation
try {
-
+ //DEBUG Logger.debug("Current
transaction is "+tm.getTransaction());
+
return invokeNext(remoteInvocation,mi );
- }
+ }
catch (RemoteException e) {
-
+
if (newTransaction != null) {
-
- //We started it, it will be rolled back in the finally
+
+ //We started it, it will be rolled back in the finally
newTransaction.setRollbackOnly();
}
-
+
throw e;
- }
+ }
catch (RuntimeException e) {
-
+
if (newTransaction != null) {
-
+
// We started it, it will be rolled back in the finally
newTransaction.setRollbackOnly();
}
-
+
throw new ServerException("Exception occurred", e);
- }
+ }
catch (Error e) {
-
+
if (newTransaction != null) {
-
+
// we started it, it will be rolled back in the finally
newTransaction.setRollbackOnly();
}
throw new ServerException("Exception
occurred:"+e.getMessage());
- }
-
+ }
+
finally {
-
- //DEBUG Logger.debug("TxInterceptorCMT: in finally");
-//DEBUG Logger.debug("TxInterceptorCMT: In finally");
-
- // Only do something if we started the transaction
+
+ //DEBUG
Logger.debug("TxInterceptorCMT: in finally");
+
+ // Do something wuth the transaction we've started
if (newTransaction != null) {
-
+
+ //DEBUG
Logger.debug("TxInterceptorCMT: newTransaction is not null");
+
// Marked rollback
if (newTransaction.getStatus() ==
Status.STATUS_MARKED_ROLLBACK) {
-
- // actually roll it back
+
+ // actually roll it back
newTransaction.rollback();
+ //DEBUG
Logger.debug("TxInterceptorCMT: rolling back newTransaction");
}
-
+
//Still running
else if(newTransaction.getStatus() ==
Status.STATUS_ACTIVE) {
-
+
// Commit tx
// This will happen if
// a) everything goes well
@@ -317,172 +354,254 @@
//DEBUG Logger.debug("TxInterceptorCMT:before
commit");
newTransaction.commit();
//DEBUG Logger.debug("TxInterceptorCMT:after
commit");
-
+
}
-
+
// reassociate the oldTransaction with the
methodInvocation (even null)
mi.setTransaction(oldTransaction);
}
+
+ // Either the newTransaction was committed/rolled back
+ // or it was null. Just disassociate ourselves from
+ // whatever the current transaction is (the only
optimization
+ // here could be to check if the current transaction is the
+ // same as the threadTransaction but this, AFAIK, is not
+ // very likely)
+ // In any case, if the original invocation was without a
+ // transactional context, we need to make sure we come out
+ // without one, especially not in the context of already
+ // committed transaction, for this may cause big trouble
later on
+
+ Transaction currentTx = tm.getTransaction();
+
+ if (threadTransaction == null) {
+
+ if (currentTx != null)
+ tm.suspend();
+ }
+ else if (! threadTransaction.equals(currentTx)) {
+
+ tm.suspend();
+ //DEBUG
Logger.debug("TxInterceptorCMT: resuming threadTransaction");
+ tm.resume(threadTransaction);
+ }
+ /* else we are still in the right context, don't do
anything */
+
}
}
-
- case MetaData.TX_SUPPORTS:
+
+ case MetaData.TX_SUPPORTS:
{
-
+
+ // DEBUG Logger.debug("TX_SUPPORTS begin");
+
if (oldTransaction != null) { // We have a tx propagated
-
- // Associate it with the thread
- tm.associateThread(oldTransaction);
+ // are we in the optimized tx context?
+ if ( ! optimized ) {
+ // the incoming thread is not optimized, so
+ // suspend its transaction
+ // DEBUG
Logger.debug("Suspending current thread transaction");
+ tm.suspend();
+ // Associate the propagated tx with the thread
+ // DEBUG
Logger.debug("Resuming propagated transaction");
+ tm.resume(oldTransaction);
+ }
+ /*
+ else {
+ //DEBUG
+ Logger.debug("Optimized call -- current transaction
same as propagated");
+ }
+ */
}
-
+
// If we don't have a tx propagated we don't do anything
-
+
// Continue invocation
try {
-
+
return invokeNext(remoteInvocation,mi );
- }
+ }
catch (RuntimeException e) {
-
+
throw new ServerException("Exception occurred", e);
- }
+ }
catch (Error e) {
-
+
throw new ServerException("Exception
occurred:"+e.getMessage());
- }
-
- // Even on error we don't do anything with the tx, we didn't
start it
-
+ }
+ finally {
+
+ Transaction currentTx = tm.getTransaction();
+
+ if (threadTransaction == null) {
+
+ if (currentTx != null)
+ tm.suspend();
+ }
+ else if ( ! threadTransaction.equals(currentTx) ){
+ tm.suspend();
+ // resume the original transaction
+ //DEBUG Logger.debug("Resuming
original thread transaction");
+ tm.resume(threadTransaction);
+ }
+
+ //DEBUG Logger.debug("TX_SUPPORTS
end");
+ }
}
-
- case MetaData.TX_REQUIRES_NEW:
+
+ case MetaData.TX_REQUIRES_NEW:
{
-
+
// Thread arriving must be clean (jboss doesn't set the thread
previously)
// However optimized calls come with associated thread for
example
- Transaction threadTx = tm.disassociateThread();
-
-
- // Always begin a transaction
+ tm.suspend();
+
+
+ // Always begin a transaction
tm.begin();
-
+
// get it
newTransaction = tm.getTransaction();
-
+
// Set it on the method invocation
mi.setTransaction(newTransaction);
-
+
// Continue invocation
try {
-
+
return invokeNext(remoteInvocation,mi );
- }
+ }
catch (RemoteException e) {
-
+
// We started it for sure
// will be rolled back in the finally
newTransaction.setRollbackOnly();
-
+
throw e;
- }
+ }
catch (RuntimeException e) {
-
+
// We started it for sure
// will be rolled back in the finally
newTransaction.setRollbackOnly();
-
+
throw new ServerException("Exception occurred", e);
- }
+ }
catch (Error e) {
-
+
// We started it for sure
// will be rolled back in the finally
newTransaction.setRollbackOnly();
-
+
throw new ServerException("Exception
occurred:"+e.getMessage());
- }
+ }
finally {
-
+
// We started the transaction for sure so we commit or roll
back
-
+
if (newTransaction.getStatus() ==
Status.STATUS_MARKED_ROLLBACK) {
-
+
newTransaction.rollback();
}
else {
-
+
// Commit tx
// This will happen if
// a) everything goes well
// b) app. exception was thrown
newTransaction.commit();
}
-
+
// set the old transaction back on the method invocation
mi.setTransaction(oldTransaction);
-
- // IN case we had a Tx associated with the thread
reassociate
- if (threadTx != null) {
-
- tm.associateThread(threadTx);
+
+ // make sure if we came w/o a transactional
+ // context into this call, we leave w/o one
+ tm.suspend();
+
+ // or in case we had a Tx associated
+ // with this thread reassociate
+ if (threadTransaction != null) {
+ tm.resume(threadTransaction);
}
- }
+ }
}
-
- case MetaData.TX_MANDATORY:
+
+ case MetaData.TX_MANDATORY:
{
-
- if (oldTransaction == null) { // no transaction = bad!
-
+
+ if (oldTransaction == null) { // no transaction = bad!
+
throw new TransactionRequiredException("Transaction
Required, read the spec!");
- }
+ }
else {
-
- // Associate it with the thread
- tm.associateThread(oldTransaction);
-
- // That's it
- return invokeNext(remoteInvocation,mi );
+ // are we in the optimized tx context?
+ if ( ! optimized ) {
+ // clean up this thread
+ tm.suspend();
+
+ // Associate it with the thread
+ tm.resume(oldTransaction);
+ }
+
+ try {
+ return invokeNext(remoteInvocation,mi );
+ }
+ finally {
+
+ Transaction currentTx = tm.getTransaction();
+
+ if (threadTransaction == null) {
+
+ if (currentTx != null)
+ tm.suspend();
+ }
+ else if ( ! threadTransaction.equals(currentTx) ) {
+ tm.suspend();
+ tm.resume(threadTransaction);
+ }
+ // else we are still in the right context
+ }
}
}
-
- case MetaData.TX_NEVER:
+
+ case MetaData.TX_NEVER:
{
-
+
if (oldTransaction != null) { // Transaction = bad!
-
+
throw new RemoteException("Transaction not allowed");
- }
+ }
else {
-
+
return invokeNext(remoteInvocation,mi );
}
}
}
-
+
return null;
}
-
+
// Protected ----------------------------------------------------
-
+
// This should be cached, since this method is called very often
protected byte getTransactionMethod(Method m, boolean remoteInvocation) {
Byte b = (Byte)methodTx.get(m);
if(b != null) return b.byteValue();
-
+
BeanMetaData bmd = container.getBeanMetaData();
-
+
//DEBUG Logger.debug("Found metadata for bean '"+bmd.getEjbName()+"'"+"
method is "+m.getName());
-
+
byte result = bmd.getMethodTransactionType(m.getName(),
m.getParameterTypes(), remoteInvocation);
-
- // provide default if method is not found in descriptor
+
+ // provide default if method is not found in descriptor
if (result == MetaData.TX_UNKNOWN) result = MetaData.TX_REQUIRED;
-
+
methodTx.put(m, new Byte(result));
return result;
}
-
+
// Inner classes -------------------------------------------------
-
+
}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development