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

Reply via email to