User: sparre  
  Date: 01/06/25 12:45:50

  Modified:    src/main/org/jboss/ejb/plugins TxInterceptorBMT.java
                        TxInterceptorCMT.java
  Added:       src/main/org/jboss/ejb/plugins AbstractTxInterceptor.java
                        AbstractTxInterceptorBMT.java
  Log:
  Transaction interceptors cleanup and reorganization.
  
  Revision  Changes    Path
  1.18      +49 -369   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.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- TxInterceptorBMT.java     2001/06/18 20:01:23     1.17
  +++ TxInterceptorBMT.java     2001/06/25 19:45:49     1.18
  @@ -6,384 +6,64 @@
   */
   package org.jboss.ejb.plugins;
   
  -import java.lang.reflect.Method;
  -import java.rmi.RemoteException;
  -import java.rmi.ServerError;
  -import java.rmi.ServerException;
  -import java.util.*;
  -
  -import javax.swing.tree.*;
  -
  -import javax.transaction.Status;
  -import javax.transaction.Transaction;
  -import javax.transaction.TransactionManager;
  -import javax.transaction.RollbackException;
  -import javax.transaction.TransactionRequiredException;
  -import javax.transaction.SystemException;
  -import javax.transaction.UserTransaction;
  -
  -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 javax.ejb.EJBException;
  -
  -import org.jboss.ejb.Container;
  -import org.jboss.ejb.EnterpriseContext;
  -import org.jboss.ejb.StatefulSessionEnterpriseContext;
  -import org.jboss.ejb.StatelessSessionEnterpriseContext;
  +
   import org.jboss.ejb.MethodInvocation;
  -import org.jboss.tm.TxManager;
  -import org.jboss.logging.Logger;
   
  -import org.jboss.metadata.MetaData;
  -import org.jboss.metadata.BeanMetaData;
   import org.jboss.metadata.SessionMetaData;
  -import org.jboss.metadata.MethodMetaData;
   
   /**
  -*   <description>
  -*
  -*   @see <related>
  -*   @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
  -*   @author <a href="mailto:[EMAIL PROTECTED]";>Sebastien Alborini</a>
  -*   @author <a href="mailto:[EMAIL PROTECTED]";>Peter Antman</a>.
  -*   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
  -*   @version $Revision: 1.17 $
  -*/
  + *   This interceptor handles transactions for session BMT beans.
  + *
  + *   @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
  + *   @author <a href="mailto:[EMAIL PROTECTED]";>Sebastien Alborini</a>
  + *   @author <a href="mailto:[EMAIL PROTECTED]";>Peter Antman</a>.
  + *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
  + *   @author <a href="mailto:[EMAIL PROTECTED]";>Ole Husgaard</a>
  + *   @version $Revision: 1.18 $
  + */
   public class TxInterceptorBMT
  -extends AbstractInterceptor
  +   extends AbstractTxInterceptorBMT
   {
  +
  +   // Attributes ----------------------------------------------------
  +
  +   // Static --------------------------------------------------------
  +
  +   // Constructors --------------------------------------------------
  +
  +   // Public --------------------------------------------------------
  +
  +   // Interceptor implementation --------------------------------------
  +
  +   public void init()
  +      throws Exception
  +   {
  +      // Do initialization in superclass.
  +      super.init();
  + 
  +      // Set the atateless attribute
  +      stateless = ((SessionMetaData)container.getBeanMetaData()).isStateless();
  +   }
  +
  +   public Object invokeHome(MethodInvocation mi)
  +      throws Exception
  +   {
  +      if (stateless)
  +         // stateless: no context, no transaction, no call to the instance
  +         return getNext().invokeHome(mi);
  +      else
  +         return invokeNext(false, mi);
  +   }
  +
  +   public Object invoke(MethodInvocation mi)
  +      throws Exception
  +   {
  +      return invokeNext(true, mi);
  +   }
   
  -    // 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();
  -
  -    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(),
  -                                      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)
  -       {
  -          //ignore
  -       }
  -    }
  -
  -    public Object invokeHome(MethodInvocation mi)
  -    throws Exception
  -    {
  -        // 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.getTransaction();
  -
  -            // t2 refers to the instance transaction (spec ejb1.1, 11.6.1, p174)
  -            Transaction t2 = mi.getEnterpriseContext().getTransaction();
  -
  -            try {
  -
  -                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
  -                if (mi.getEnterpriseContext().getTransaction() != null) {
  -                    try {
  -                        
mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                    } catch (IllegalStateException ex) {
  -                    }
  -                }
  -
  -                if (e instanceof EJBException) {
  -                    throw new ServerException("Transaction rolled back",
  -                                              ((EJBException) 
e).getCausedByException());
  -                } else {
  -                    throw new ServerException("Transaction rolled back", e);
  -                }
  -            } catch (RemoteException e)
  -            {
  -                // EJB 2.0 17.3, table 16
  -                if (mi.getEnterpriseContext().getTransaction() != null) {
  -                    try {
  -                        
mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                    } catch (IllegalStateException ex) {
  -                    }
  -                }
  -
  -                throw new ServerException("Transaction rolled back", e);
  -            } catch (Error e)
  -            {
  -                // EJB 2.0 17.3, table 16
  -                if (mi.getEnterpriseContext().getTransaction() != null) {
  -                    try {
  -                        
mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                    } catch (IllegalStateException ex) {
  -                    }
  -                }
  -
  -                throw new ServerException("Transaction rolled 
back:"+e.getMessage());
  -            } finally {
  -
  -                // Reset user Tx
  -                userTransaction.set(oldUserTx);
  -
  -                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
  -    *
  -    * @param   id
  -    * @param   m
  -    * @param   args
  -    * @return
  -    * @exception   Exception
  -    */
  -    public Object invoke(MethodInvocation mi) throws Exception {
  -
  -        // 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.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)
  -        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) {
  -
  -                tm.suspend();
  -            }
  -            else if ( ! t2.equals(t1) ) {
  -
  -                tm.suspend();
  -                // associate the transaction to the thread
  -                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
  -            if (mi.getEnterpriseContext().getTransaction() != null) {
  -                try {
  -                    mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                } catch (IllegalStateException ex) {
  -                }
  -            }
  -
  -            if (e instanceof EJBException) {
  -                throw new ServerException("Transaction rolled back",
  -                                          ((EJBException) 
e).getCausedByException());
  -            } else {
  -                throw new ServerException("Transaction rolled back", e);
  -            }
  -        } catch (RemoteException e)
  -        {
  -            // EJB 2.0 17.3, table 16
  -            if (mi.getEnterpriseContext().getTransaction() != null) {
  -                try {
  -                    mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                } catch (IllegalStateException ex) {
  -                }
  -            }
  -
  -            throw new ServerException("Transaction rolled back", e);
  -        } catch (Error e)
  -        {
  -            // EJB 2.0 17.3, table 16
  -            if (mi.getEnterpriseContext().getTransaction() != null) {
  -                try {
  -                    mi.getEnterpriseContext().getTransaction().setRollbackOnly();
  -                } catch (IllegalStateException ex) {
  -                }
  -            }
  -
  -            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())));
  -
  -
  -            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_ROLLING_BACK:
  -
  -                        t3.rollback();
  -
  -                    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
  -        {
  -
  -            // 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();
  +   // Protected  ----------------------------------------------------
   
  -        }
  -    }
  +   // Inner classes -------------------------------------------------
   
   }
   
  
  
  
  1.13      +5 -132    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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- TxInterceptorCMT.java     2001/06/20 05:56:11     1.12
  +++ TxInterceptorCMT.java     2001/06/25 19:45:49     1.13
  @@ -8,29 +8,17 @@
   
   import java.lang.reflect.Method;
   import java.rmi.RemoteException;
  -import java.rmi.ServerException;
  -import java.rmi.NoSuchObjectException;
   import java.util.HashMap;
   
   import javax.transaction.Status;
   import javax.transaction.Transaction;
  -import javax.transaction.TransactionManager;
  -import javax.transaction.RollbackException;
   import javax.transaction.TransactionRequiredException;
  -import javax.transaction.TransactionRolledbackException;
  -import javax.transaction.SystemException;
   
  -import javax.ejb.EJBException;
  -import javax.ejb.NoSuchEntityException;
  -
  -import org.jboss.ejb.Container;
  -import org.jboss.ejb.EnterpriseContext;
   import org.jboss.ejb.MethodInvocation;
   import org.jboss.logging.Logger;
   
   import org.jboss.metadata.MetaData;
   import org.jboss.metadata.BeanMetaData;
  -import org.jboss.metadata.MethodMetaData;
   
   /**
    *  This interceptor handles transactions for CMT beans.
  @@ -40,58 +28,25 @@
    *  @author <a href="mailto:[EMAIL PROTECTED]";>Sebastien Alborini</a>
    *  @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
    *  @author <a href="mailto:[EMAIL PROTECTED]";>Ole Husgaard</a>
  - *  @version $Revision: 1.12 $
  + *  @version $Revision: 1.13 $
    */
   public class TxInterceptorCMT
  -extends AbstractInterceptor
  +    extends AbstractTxInterceptor
   {
   
       // Attributes ----------------------------------------------------
   
  -    /** Local reference to the container's TransactionManager. */
  -    private TransactionManager tm;
  - 
       /** A cache mapping methods to transaction attributes. */
       private HashMap methodTx = new HashMap();
   
  -    /** The container that we manage transactions for. */
  -    protected Container container;
  -
       // Static --------------------------------------------------------
   
       // Constructors --------------------------------------------------
   
       // Public --------------------------------------------------------
   
  -    /**
  -     *  Set the container that we manage transactions for.
  -     */
  -    public void setContainer(Container container)
  -    {
  -        this.container = container;
  -    }
  -
  -    /**
  -     *  Set the container that we manage transactions for.
  -     */
  -    public Container getContainer()
  -    {
  -        return container;
  -    }
  -
       // Interceptor implementation --------------------------------------
  -    public void init()
  -        throws Exception
  -    {
  -        // Store TM reference locally
  -        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
       {
  @@ -107,6 +62,8 @@
           return runWithTransactions(true, mi);
       }
   
  +    // Private  ------------------------------------------------------
  +
       private void printMethod(Method m, byte type) {
           String name;
           switch(type) {
  @@ -135,90 +92,6 @@
       }
   
       /*
  -     *  This method calls the next interceptor in the chain.
  -     *
  -     *  Throwables <code>Error</code>, <code>RemoteException</code> and
  -     *  <code>RuntimeException</code> are caught and result in the transaction
  -     *  being marked for rollback only. If such a non-application exception
  -     *  happens with a transaction that was not started locally, it is wrapped
  -     *  in a <code>TransactionRolledbackException</code>.
  -     *
  -     *  @param remoteInvocation If <code>true</code> this is an invocation
  -     *                          of a method in the remote interface, otherwise
  -     *                          it is an invocation of a method in the home
  -     *                          interface.
  -     *  @param mi The <code>MethodInvocation</code> of this call.
  -     *  @param newTx If <code>true</code> the transaction has just been
  -     *               started in this interceptor.
  -     */
  -    private Object invokeNext(boolean remoteInvocation, MethodInvocation mi, 
boolean newTx)
  -        throws Exception
  -    {
  -        try {
  -            if (remoteInvocation)
  -                return getNext().invoke(mi);
  -            else
  -                return getNext().invokeHome(mi);
  -        } catch (RuntimeException e) {
  -            try {
  -                mi.getTransaction().setRollbackOnly();
  -            } catch (SystemException ex) {
  -                Logger.exception(ex);
  -            } catch (IllegalStateException ex) {
  -                Logger.exception(ex);
  -            }
  -            RemoteException ex;
  -            if (newTx) {
  -                if (e instanceof NoSuchEntityException) {
  -                    // Convert NoSuchEntityException to a NoSuchObjectException
  -                    // with the same detail.
  -                    ex = new NoSuchObjectException(e.getMessage());
  -                    ex.detail = ((NoSuchEntityException)e).getCausedByException();
  -                    throw ex;
  -                }
  -                // OSH: Should this be wrapped?
  -                ex = new ServerException(e.getMessage());
  -            } else
  -                // We inherited tx: Tell caller that we marked for rollback only.
  -                ex = new TransactionRolledbackException(e.getMessage());
  -            ex.detail = e;
  -            throw ex;
  -        } catch (RemoteException e) {
  -            try {
  -                mi.getTransaction().setRollbackOnly();
  -            } catch (SystemException ex) {
  -                Logger.exception(ex);
  -            } catch (IllegalStateException ex) {
  -                Logger.exception(ex);
  -            }
  -            RemoteException ex;
  -            if (newTx) {
  -                if (e instanceof NoSuchObjectException)
  -                    throw e; // Do not wrap this.
  -                // OSH: Should this be wrapped?
  -                ex = new ServerException(e.getMessage());
  -            } else
  -                ex = new TransactionRolledbackException(e.getMessage());
  -            ex.detail = e;
  -            throw ex;
  -        } catch (Error e) {
  -            if (mi.getTransaction() != null) {
  -                try {
  -                    mi.getTransaction().setRollbackOnly();
  -                } catch (IllegalStateException ex) {
  -                }
  -                RemoteException tre = new 
TransactionRolledbackException(e.getMessage());
  -                tre.detail = e;
  -                throw tre;
  -            } else {
  -                // This exception will be transformed into a RemoteException
  -                // by the LogInterceptor
  -                throw e;
  -            }
  -        }
  -    }
  -
  -    /*
        *  This method does invocation interpositioning of tx management.
        *
        *  This is where the meat is.  We define what to do with the Tx based
  @@ -246,7 +119,7 @@
           //DEBUG       Logger.debug("Current transaction in MI is 
"+mi.getTransaction());
           //DEBUG Logger.debug("Current method "+mi.getMethod());
           byte transType = getTransactionMethod(mi.getMethod(), remoteInvocation); 
  -        printMethod(mi.getMethod(), transType);
  +        // printMethod(mi.getMethod(), transType);
    
           // Thread arriving must be clean (jboss doesn't set the thread
           // previously). However optimized calls come with associated
  
  
  
  1.1                  jboss/src/main/org/jboss/ejb/plugins/AbstractTxInterceptor.java
  
  Index: AbstractTxInterceptor.java
  ===================================================================
  /*
  * JBoss, the OpenSource EJB server
  *
  * Distributable under LGPL license.
  * See terms of license at gnu.org.
  */
  package org.jboss.ejb.plugins;
  
  import java.rmi.RemoteException;
  import java.rmi.ServerException;
  import java.rmi.NoSuchObjectException;
  
  import javax.transaction.Transaction;
  import javax.transaction.TransactionManager;
  import javax.transaction.TransactionRolledbackException;
  import javax.transaction.SystemException;
  
  import javax.ejb.NoSuchEntityException;
  
  import org.jboss.ejb.Container;
  import org.jboss.ejb.MethodInvocation;
  import org.jboss.logging.Logger;
  
  /**
   *  A common superclass for the transaction interceptors.
   *
   *  @author <a href="mailto:[EMAIL PROTECTED]";>Ole Husgaard</a>
   *  @version $Revision: 1.1 $
   */
  abstract class AbstractTxInterceptor
     extends AbstractInterceptor
  {
  
      // Attributes ----------------------------------------------------
  
      /** Local reference to the container's TransactionManager. */
      protected TransactionManager tm;
   
      /** The container that we manage transactions for. */
      protected Container container;
  
      // Static --------------------------------------------------------
  
      // Constructors --------------------------------------------------
  
      // Public --------------------------------------------------------
  
      /**
       *  Set the container that we manage transactions for.
       */
      public void setContainer(Container container)
      {
          this.container = container;
      }
  
      /**
       *  Get the container that we manage transactions for.
       */
      public Container getContainer()
      {
          return container;
      }
  
      // Interceptor implementation --------------------------------------
  
      public void init()
          throws Exception
      {
          tm = (TransactionManager) getContainer().getTransactionManager();
      }
  
      // Protected  ----------------------------------------------------
  
      /**
       *  This method calls the next interceptor in the chain.
       *
       *  Throwables <code>Error</code>, <code>RemoteException</code> and
       *  <code>RuntimeException</code> are caught and result in the transaction
       *  being marked for rollback only. If such a non-application exception
       *  happens with a transaction that was not started locally, it is wrapped
       *  in a <code>TransactionRolledbackException</code>.
       *
       *  @param remoteInvocation If <code>true</code> this is an invocation
       *                          of a method in the remote interface, otherwise
       *                          it is an invocation of a method in the home
       *                          interface.
       *  @param mi The <code>MethodInvocation</code> of this call.
       *  @param newTx If <code>true</code> the transaction has just been
       *               started in this interceptor.
       */
      protected Object invokeNext(boolean remoteInvocation, MethodInvocation mi,
                                  boolean newTx)
          throws Exception
      {
          try {
              if (remoteInvocation)
                  return getNext().invoke(mi);
              else
                  return getNext().invokeHome(mi);
          } catch (RuntimeException e) {
              try {
                  mi.getTransaction().setRollbackOnly();
              } catch (SystemException ex) {
                  Logger.exception(ex);
              } catch (IllegalStateException ex) {
                  Logger.exception(ex);
              }
              RemoteException ex;
              if (newTx) {
                  if (e instanceof NoSuchEntityException) {
                      // Convert NoSuchEntityException to a NoSuchObjectException
                      // with the same detail.
                      ex = new NoSuchObjectException(e.getMessage());
                      ex.detail = ((NoSuchEntityException)e).getCausedByException();
                      throw ex;
                  }
                  // OSH: Should this be wrapped?
                  ex = new ServerException(e.getMessage());
              } else
                  // We inherited tx: Tell caller we marked for rollback only.
                  ex = new TransactionRolledbackException(e.getMessage());
              ex.detail = e;
              throw ex;
          } catch (RemoteException e) {
              try {
                  mi.getTransaction().setRollbackOnly();
              } catch (SystemException ex) {
                  Logger.exception(ex);
              } catch (IllegalStateException ex) {
                  Logger.exception(ex);
              }
              RemoteException ex;
              if (newTx) {
                  if (e instanceof NoSuchObjectException)
                      throw e; // Do not wrap this.
                  // OSH: Should this be wrapped?
                  ex = new ServerException(e.getMessage());
              } else
                  ex = new TransactionRolledbackException(e.getMessage());
              ex.detail = e;
              throw ex;
          } catch (Error e) {
              if (mi.getTransaction() != null) {
                  try {
                      mi.getTransaction().setRollbackOnly();
                  } catch (IllegalStateException ex) {
                  }
                  RemoteException tre = new 
TransactionRolledbackException(e.getMessage());
                  tre.detail = e;
                  throw tre;
              } else {
                  // This exception will be transformed into a RemoteException
                  // by the LogInterceptor
                  throw e;
              }
          }
      }
  
      // Inner classes -------------------------------------------------
  
  }
  
  
  
  1.1                  
jboss/src/main/org/jboss/ejb/plugins/AbstractTxInterceptorBMT.java
  
  Index: AbstractTxInterceptorBMT.java
  ===================================================================
  /*
  * JBoss, the OpenSource EJB server
  *
  * Distributable under LGPL license.
  * See terms of license at gnu.org.
  */
  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.MethodInvocation;
  import org.jboss.logging.Logger;
  
  
  /**
   *  A common superclass for the BMT transaction interceptors.
   *
   *  @author <a href="mailto:[EMAIL PROTECTED]";>Ole Husgaard</a>
   *  @version $Revision: 1.1 $
   */
  abstract class AbstractTxInterceptorBMT
     extends AbstractTxInterceptor
  {
  
     // Attributes ----------------------------------------------------
  
     /**
      *  This associates the thread to the UserTransaction.
      *
      *  It is used to redirect lookups on java:comp/UserTransaction to
      *  the <code>getUserTransaction()</code> method of the context.
      */
     private ThreadLocal userTransaction = new ThreadLocal();
  
     /**
      *  If <code>false</code>, transactions may live across bean instance
      *  invocations, otherwise the bean instance should terminate any
      *  transaction before returning from the invocation.
      *  This attribute defaults to <code>true</code>.
      */
     protected boolean stateless = true;
  
     // Static --------------------------------------------------------
  
     // Constructors --------------------------------------------------
  
     // Public --------------------------------------------------------
  
     // Interceptor implementation --------------------------------------
  
     public void init()
        throws Exception
     {
        // Do initialization in superclass.
        super.init();
  
        // 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(),
                                      null);
        ((Context)new InitialContext().lookup("java:comp/")).bind("UserTransaction", 
ref);
     }
  
     public void stop()
     {
        // bind java:comp/UserTransaction
        try {
           ((Context)new 
InitialContext().lookup("java:comp/")).unbind("UserTransaction");
        } catch (Exception e) {
           //ignore
        }
     }
  
     // Protected  ----------------------------------------------------
  
     /*
      *  This method calls the next interceptor in the chain.
      *
      *  It handles the suspension of any client transaction, and the
      *  association of the calling thread with the instance transaction.
      *  And it takes care that any lookup of
      *  <code>java:comp/UserTransaction</code> will return the right
      *  UserTransaction for the bean instance.
      *
      *  @param remoteInvocation If <code>true</code> this is an invocation
      *                          of a method in the remote interface, otherwise
      *                          it is an invocation of a method in the home
      *                          interface.
      *  @param mi The <code>MethodInvocation</code> of this call.
      */
     protected Object invokeNext(boolean remoteInvocation, MethodInvocation mi)
        throws Exception
     {
        // Save the transaction that comes with the MI
        Transaction oldTransaction = mi.getTransaction();
  
        // Get old threadlocal: It may be non-null if one BMT bean does a local
        // call to another.
        Object oldUserTx = userTransaction.get();
  
        // Suspend any transaction associated with the thread: It may be
        // non-null on optimized local calls.
        Transaction threadTx = tm.suspend();
  
        try {
           EnterpriseContext ctx = mi.getEnterpriseContext();
  
           // Set the threadlocal to the userTransaction of the instance
           userTransaction.set(ctx.getEJBContext().getUserTransaction());
  
           // Get the bean instance transaction
           Transaction beanTx = ctx.getTransaction();
  
           // Resume the bean instance transaction
           tm.resume(beanTx);
  
           // Let the MI know about our new transaction
           mi.setTransaction(beanTx);
  
           try {
              // Let the superclass call next interceptor and do the exception
              // handling
              return super.invokeNext(remoteInvocation, mi, true);
           } finally {
              try {
                 if (stateless)
                    checkStatelessDone();
              } finally {
                 tm.suspend();
              }
           }
        } finally {
           // Reset threadlocal to its old value
           userTransaction.set(oldUserTx);
  
           // Restore old MI transaction
           // OSH: Why ???
           mi.setTransaction(oldTransaction);
  
           // If we had a Tx associated with the thread reassociate
           if (threadTx != null)
               tm.resume(threadTx);
        }
     }
  
  
     private void checkStatelessDone()
        throws RemoteException
     {
        int status = Status.STATUS_NO_TRANSACTION;
  
        try {
           status = tm.getStatus();
        } catch (SystemException ex) {
           Logger.exception(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) {
                 Logger.exception(ex);
              }
              // fall through...
           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)";
              Logger.error(msg);
  
              // the instance interceptor will discard the instance
              throw new RemoteException(msg);
        }
     }
  
     // Inner classes -------------------------------------------------
  
     public static class UserTxFactory
        implements ObjectFactory
     {
        public Object getObjectInstance(Object ref, Name name,
                                        Context nameCtx, Hashtable environment)
           throws Exception
        {
           // The ref is a list with only one RefAddr ...
           RefAddr refAddr = ((Reference)ref).get(0);
           // ... whose content is the threadlocal
           ThreadLocal threadLocal = (ThreadLocal)refAddr.getContent();
  
           // The threadlocal holds the right UserTransaction
           return threadLocal.get();
        }
     }
  
  }
  
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to