User: fleury  
  Date: 00/09/26 11:58:33

  Modified:    src/main/org/jboss/ejb/plugins
                        StatefulSessionFilePersistenceManager.java
                        StatefulSessionInstanceInterceptor.java
                        StatelessSessionInstanceInterceptor.java
  Added:       src/main/org/jboss/ejb/plugins TxInterceptorCMT.java
  Log:
  new adds for the proper management of Tx and cache
  
  Revision  Changes    Path
  1.7       +240 -240  
jboss/src/main/org/jboss/ejb/plugins/StatefulSessionFilePersistenceManager.java
  
  Index: StatefulSessionFilePersistenceManager.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/StatefulSessionFilePersistenceManager.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- StatefulSessionFilePersistenceManager.java        2000/08/18 03:20:57     1.6
  +++ StatefulSessionFilePersistenceManager.java        2000/09/26 18:58:32     1.7
  @@ -1,240 +1,240 @@
  -/*
  - * jBoss, the OpenSource EJB server
  - *
  - * Distributable under GPL license.
  - * See terms of license at gnu.org.
  - */
  -package org.jboss.ejb.plugins;
  -
  -import java.beans.Beans;
  -import java.beans.beancontext.BeanContextServicesSupport;
  -import java.io.File;
  -import java.io.InputStream;
  -import java.io.OutputStream;
  -import java.io.ObjectInputStream;
  -import java.io.ObjectOutputStream;
  -import java.io.FileOutputStream;
  -import java.io.FileInputStream;
  -import java.io.IOException;
  -import java.lang.reflect.Method;
  -import java.lang.reflect.Field;
  -import java.lang.reflect.Modifier;
  -import java.lang.reflect.InvocationTargetException;
  -import java.rmi.RemoteException;
  -import java.rmi.NoSuchObjectException;
  -import java.rmi.ServerException;
  -import java.util.Collection;
  -import java.util.ArrayList;
  -import java.util.Iterator;
  -import java.sql.SQLException;
  -import java.sql.ResultSet;
  -import java.sql.ResultSetMetaData;
  -import java.sql.DriverManager;
  -import java.sql.Statement;
  -import java.sql.PreparedStatement;
  -import java.sql.Connection;
  -
  -import javax.ejb.EJBObject;
  -import javax.ejb.Handle;
  -import javax.ejb.SessionBean;
  -import javax.ejb.CreateException;
  -import javax.ejb.DuplicateKeyException;
  -import javax.ejb.FinderException;
  -import javax.ejb.RemoveException;
  -import javax.naming.Context;
  -import javax.naming.InitialContext;
  -
  -import org.jboss.ejb.Container;
  -import org.jboss.ejb.StatefulSessionContainer;
  -import org.jboss.ejb.StatefulSessionPersistenceManager;
  -import org.jboss.ejb.StatefulSessionEnterpriseContext;
  -import org.jboss.logging.Logger;
  -
  -
  -/**
  - *   StatefulSessionFilePersistenceManager
  - *
  - *  This class is one of the passivating plugins for jBoss.  
  - *  It is fairly simple and can work from the file system from wich jBoss is 
operating
  - *      
  - *   @see <related>
  - *   @author Rickard �berg ([EMAIL PROTECTED])
  - *  @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
  - *   @version $Revision: 1.6 $
  - */
  -public class StatefulSessionFilePersistenceManager
  -   implements StatefulSessionPersistenceManager
  -{
  -   // Constants -----------------------------------------------------
  -    
  -   // Attributes ----------------------------------------------------
  -   StatefulSessionContainer con;
  -   
  -   Method ejbActivate;
  -   Method ejbPassivate;
  -   Method ejbRemove;
  -   
  -   File dir;
  -   
  -   // Static --------------------------------------------------------
  -   private static long id = System.currentTimeMillis();
  -   
  -   // Constructors --------------------------------------------------
  -   
  -   // Public --------------------------------------------------------
  -   public void setContainer(Container c)
  -   {
  -      con = (StatefulSessionContainer)c;
  -   }
  -   
  -    public void init()
  -        throws Exception {
  -         
  -        // Find methods
  -        ejbActivate = SessionBean.class.getMethod("ejbActivate", new Class[0]);
  -        
  -       ejbPassivate = SessionBean.class.getMethod("ejbPassivate", new Class[0]);
  -        
  -       ejbRemove = SessionBean.class.getMethod("ejbRemove", new Class[0]);
  -      
  -        // Initialize the dataStore
  -       String ejbName = con.getBeanMetaData().getEjbName();
  -      
  -       File database = new File("database");
  -      
  -       dir = new File(database, ejbName);
  -         
  -       dir.mkdirs();
  -       
  -       Logger.log("Storing sessions for "+ejbName+" in:"+dir);
  -      
  -       // Clear dir of old files
  -       File[] sessions = dir.listFiles();
  -       for (int i = 0; i < sessions.length; i++)
  -       {
  -         sessions[i].delete();
  -       }
  -       Logger.log(sessions.length + " old sessions removed");
  -   }
  -   
  -   public void start()
  -      throws Exception
  -   {
  -   }
  -
  -   public void stop()
  -   {
  -   }
  -   
  -   public void destroy()
  -   {
  -   }
  -   
  -   public void createSession(Method m, Object[] args, 
StatefulSessionEnterpriseContext ctx)
  -      throws RemoteException, CreateException
  -   {
  -      // Get methods
  -      try
  -      {
  -         Method createMethod = con.getBeanClass().getMethod("ejbCreate", 
m.getParameterTypes());
  -      
  -         // Call ejbCreate
  -         createMethod.invoke(ctx.getInstance(), args);
  -         
  -         // Set id
  -         ctx.setId(nextId());
  -         
  -         // Lock instance in cache
  -         ((StatefulSessionContainer)con).getInstanceCache().insert(ctx);
  -         
  -         // Create EJBObject
  -         
ctx.setEJBObject(con.getContainerInvoker().getStatefulSessionEJBObject(ctx.getId()));
  -
  -      } catch (InvocationTargetException e)
  -      {
  -         throw new CreateException("Create failed:"+e);
  -      } catch (NoSuchMethodException e)
  -      {
  -         throw new CreateException("Create methods not found:"+e);
  -      } catch (IllegalAccessException e)
  -      {
  -         throw new CreateException("Could not create entity:"+e);
  -      } 
  -   }
  -
  -   public void activateSession(StatefulSessionEnterpriseContext ctx)
  -      throws RemoteException
  -   {
  -       try
  -       {
  -         
  -            ObjectInputStream in;
  -            
  -            
  -            // Load state
  -            in = new SessionObjectInputStream(ctx, new FileInputStream(new 
File(dir, ctx.getId()+".ser")));
  -         Field[] fields = ctx.getInstance().getClass().getFields();
  -         
  -         for (int i = 0; i < fields.length; i++)
  -          if (!Modifier.isTransient(fields[i].getModifiers()))
  -              fields[i].set(ctx.getInstance(), in.readObject());
  -         
  -          // Call bean
  -         ejbActivate.invoke(ctx.getInstance(), new Object[0]);
  -      } catch (Exception e)
  -      {
  -         throw new ServerException("Activation failed", e);
  -      }
  -   }
  -   
  -   public void passivateSession(StatefulSessionEnterpriseContext ctx)
  -      throws RemoteException
  -   {
  -      try
  -      {
  -          // Call bean
  -         ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
  -       
  -          // Store state
  -          ObjectOutputStream out = new SessionObjectOutputStream(new 
FileOutputStream(new File(dir, ctx.getId()+".ser")));
  -         
  -         Field[] fields = ctx.getInstance().getClass().getFields();
  -         
  -         for (int i = 0; i < fields.length; i++)
  -          if (!Modifier.isTransient(fields[i].getModifiers()))
  -              out.writeObject(fields[i].get(ctx.getInstance()));
  -         
  -         out.close();        
  -       } catch (Exception e)
  -       {
  -          throw new ServerException("Passivation failed", e);
  -       }
  -   }
  -      
  -   public void removeSession(StatefulSessionEnterpriseContext ctx)
  -      throws RemoteException, RemoveException
  -   {
  -      // Call bean
  -      try
  -      {
  -         ejbRemove.invoke(ctx.getInstance(), new Object[0]);
  -      } catch (Exception e)
  -      {
  -         throw new ServerException("Remove failed", e);
  -      }
  -   }
  -   
  -   // Z implementation ----------------------------------------------
  -    
  -   // Package protected ---------------------------------------------
  -    
  -   // Protected -----------------------------------------------------
  -   protected Long nextId()
  -   {
  -      return new Long(id++);
  -   }
  -   
  -   // Private -------------------------------------------------------
  -   
  -   // Inner classes -------------------------------------------------
  -}
  +/*
  + * jBoss, the OpenSource EJB server
  + *
  + * Distributable under GPL license.
  + * See terms of license at gnu.org.
  + */
  +package org.jboss.ejb.plugins;
  +
  +import java.beans.Beans;
  +import java.beans.beancontext.BeanContextServicesSupport;
  +import java.io.File;
  +import java.io.InputStream;
  +import java.io.OutputStream;
  +import java.io.ObjectInputStream;
  +import java.io.ObjectOutputStream;
  +import java.io.FileOutputStream;
  +import java.io.FileInputStream;
  +import java.io.IOException;
  +import java.lang.reflect.Method;
  +import java.lang.reflect.Field;
  +import java.lang.reflect.Modifier;
  +import java.lang.reflect.InvocationTargetException;
  +import java.rmi.RemoteException;
  +import java.rmi.NoSuchObjectException;
  +import java.rmi.ServerException;
  +import java.util.Collection;
  +import java.util.ArrayList;
  +import java.util.Iterator;
  +import java.sql.SQLException;
  +import java.sql.ResultSet;
  +import java.sql.ResultSetMetaData;
  +import java.sql.DriverManager;
  +import java.sql.Statement;
  +import java.sql.PreparedStatement;
  +import java.sql.Connection;
  +
  +import javax.ejb.EJBObject;
  +import javax.ejb.Handle;
  +import javax.ejb.SessionBean;
  +import javax.ejb.CreateException;
  +import javax.ejb.DuplicateKeyException;
  +import javax.ejb.FinderException;
  +import javax.ejb.RemoveException;
  +import javax.naming.Context;
  +import javax.naming.InitialContext;
  +
  +import org.jboss.ejb.Container;
  +import org.jboss.ejb.StatefulSessionContainer;
  +import org.jboss.ejb.StatefulSessionPersistenceManager;
  +import org.jboss.ejb.StatefulSessionEnterpriseContext;
  +import org.jboss.logging.Logger;
  +
  +
  +/**
  + *   StatefulSessionFilePersistenceManager
  + *
  + *  This class is one of the passivating plugins for jBoss.  
  + *  It is fairly simple and can work from the file system from wich jBoss is 
operating
  + *      
  + *   @see <related>
  + *   @author Rickard �berg ([EMAIL PROTECTED])
  + *  @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
  + *   @version $Revision: 1.7 $
  + */
  +public class StatefulSessionFilePersistenceManager
  +   implements StatefulSessionPersistenceManager
  +{
  +   // Constants -----------------------------------------------------
  +    
  +   // Attributes ----------------------------------------------------
  +   StatefulSessionContainer con;
  +   
  +   Method ejbActivate;
  +   Method ejbPassivate;
  +   Method ejbRemove;
  +   
  +   File dir;
  +   
  +   // Static --------------------------------------------------------
  +   private static long id = System.currentTimeMillis();
  +   
  +   // Constructors --------------------------------------------------
  +   
  +   // Public --------------------------------------------------------
  +   public void setContainer(Container c)
  +   {
  +      con = (StatefulSessionContainer)c;
  +   }
  +   
  +    public void init()
  +        throws Exception {
  +         
  +        // Find methods
  +        ejbActivate = SessionBean.class.getMethod("ejbActivate", new Class[0]);
  +        
  +       ejbPassivate = SessionBean.class.getMethod("ejbPassivate", new Class[0]);
  +        
  +       ejbRemove = SessionBean.class.getMethod("ejbRemove", new Class[0]);
  +      
  +        // Initialize the dataStore
  +       String ejbName = con.getBeanMetaData().getEjbName();
  +      
  +       File database = new File("database");
  +      
  +       dir = new File(database, ejbName);
  +         
  +       dir.mkdirs();
  +       
  +       Logger.log("Storing sessions for "+ejbName+" in:"+dir);
  +      
  +       // Clear dir of old files
  +       File[] sessions = dir.listFiles();
  +       for (int i = 0; i < sessions.length; i++)
  +       {
  +         sessions[i].delete();
  +       }
  +       Logger.log(sessions.length + " old sessions removed");
  +   }
  +   
  +   public void start()
  +      throws Exception
  +   {
  +   }
  +
  +   public void stop()
  +   {
  +   }
  +   
  +   public void destroy()
  +   {
  +   }
  +   
  +   public void createSession(Method m, Object[] args, 
StatefulSessionEnterpriseContext ctx)
  +      throws RemoteException, CreateException
  +   {
  +      // Get methods
  +      try
  +      {
  +         Method createMethod = con.getBeanClass().getMethod("ejbCreate", 
m.getParameterTypes());
  +      
  +         // Call ejbCreate
  +         createMethod.invoke(ctx.getInstance(), args);
  +         
  +         // Set id
  +         ctx.setId(nextId());
  +       
  +         // Insert in cache
  +         ((StatefulSessionContainer)con).getInstanceCache().insert(ctx);
  +        
  +         // Create EJBObject
  +         
ctx.setEJBObject(con.getContainerInvoker().getStatefulSessionEJBObject(ctx.getId()));
  +
  +      } catch (InvocationTargetException e)
  +      {
  +         throw new CreateException("Create failed:"+e);
  +      } catch (NoSuchMethodException e)
  +      {
  +         throw new CreateException("Create methods not found:"+e);
  +      } catch (IllegalAccessException e)
  +      {
  +         throw new CreateException("Could not create entity:"+e);
  +      } 
  +   }
  +
  +   public void activateSession(StatefulSessionEnterpriseContext ctx)
  +      throws RemoteException
  +   {
  +       try
  +       {
  +         
  +            ObjectInputStream in;
  +            
  +            
  +            // Load state
  +            in = new SessionObjectInputStream(ctx, new FileInputStream(new 
File(dir, ctx.getId()+".ser")));
  +         Field[] fields = ctx.getInstance().getClass().getFields();
  +         
  +         for (int i = 0; i < fields.length; i++)
  +          if (!Modifier.isTransient(fields[i].getModifiers()))
  +              fields[i].set(ctx.getInstance(), in.readObject());
  +         
  +          // Call bean
  +         ejbActivate.invoke(ctx.getInstance(), new Object[0]);
  +      } catch (Exception e)
  +      {
  +         throw new ServerException("Activation failed", e);
  +      }
  +   }
  +   
  +   public void passivateSession(StatefulSessionEnterpriseContext ctx)
  +      throws RemoteException
  +   {
  +      try
  +      {
  +          // Call bean
  +         ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
  +       
  +          // Store state
  +          ObjectOutputStream out = new SessionObjectOutputStream(new 
FileOutputStream(new File(dir, ctx.getId()+".ser")));
  +         
  +         Field[] fields = ctx.getInstance().getClass().getFields();
  +         
  +         for (int i = 0; i < fields.length; i++)
  +          if (!Modifier.isTransient(fields[i].getModifiers()))
  +              out.writeObject(fields[i].get(ctx.getInstance()));
  +         
  +         out.close();        
  +       } catch (Exception e)
  +       {
  +          throw new ServerException("Passivation failed", e);
  +       }
  +   }
  +      
  +   public void removeSession(StatefulSessionEnterpriseContext ctx)
  +      throws RemoteException, RemoveException
  +   {
  +      // Call bean
  +      try
  +      {
  +         ejbRemove.invoke(ctx.getInstance(), new Object[0]);
  +      } catch (Exception e)
  +      {
  +         throw new ServerException("Remove failed", e);
  +      }
  +   }
  +   
  +   // Z implementation ----------------------------------------------
  +    
  +   // Package protected ---------------------------------------------
  +    
  +   // Protected -----------------------------------------------------
  +   protected Long nextId()
  +   {
  +      return new Long(id++);
  +   }
  +   
  +   // Private -------------------------------------------------------
  +   
  +   // Inner classes -------------------------------------------------
  +}
  
  
  
  1.4       +313 -131  
jboss/src/main/org/jboss/ejb/plugins/StatefulSessionInstanceInterceptor.java
  
  Index: StatefulSessionInstanceInterceptor.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/StatefulSessionInstanceInterceptor.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StatefulSessionInstanceInterceptor.java   2000/06/16 13:10:23     1.3
  +++ StatefulSessionInstanceInterceptor.java   2000/09/26 18:58:32     1.4
  @@ -1,131 +1,313 @@
  -/*
  -* jBoss, the OpenSource EJB server
  -*
  -* Distributable under GPL license.
  -* See terms of license at gnu.org.
  -*/
  -package org.jboss.ejb.plugins;
  -
  -import java.lang.reflect.Method;
  -import java.rmi.RemoteException;
  -
  -import org.jboss.ejb.Container;
  -import org.jboss.ejb.InstanceCache;
  -import org.jboss.ejb.InstancePool;
  -import org.jboss.ejb.StatefulSessionContainer;
  -import org.jboss.ejb.EnterpriseContext;
  -import org.jboss.ejb.MethodInvocation;
  -
  -
  -/**
  -*   This container acquires the given instance. 
  -*
  -*   @see <related>
  -*   @author Rickard �berg ([EMAIL PROTECTED])
  -*   @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
  -*   @version $Revision: 1.3 $
  -*/
  -public class StatefulSessionInstanceInterceptor
  -     extends AbstractInterceptor
  -{
  -     // Constants ----------------------------------------------------
  -     
  -     // Attributes ---------------------------------------------------
  -     protected StatefulSessionContainer container;
  -     
  -     // Static -------------------------------------------------------
  -     
  -     // Constructors -------------------------------------------------
  -     
  -     // Public -------------------------------------------------------
  -     public void setContainer(Container container) 
  -     { 
  -             this.container = (StatefulSessionContainer)container; 
  -     }
  -     
  -     public  Container getContainer()
  -     {
  -             return container;
  -     }
  -     // Interceptor implementation -----------------------------------
  -     public Object invokeHome(MethodInvocation mi)
  -             throws Exception
  -     {
  -             // Get context
  -             mi.setEnterpriseContext(container.getInstancePool().get());
  -             
  -             try
  -             {
  -                     // Invoke through interceptors
  -                     return getNext().invokeHome(mi);
  -             } finally
  -             {
  -                     // Still free? Not free if create() was called successfully
  -                     if (mi.getEnterpriseContext().getId() == null)
  -                     {
  -                             // Create did not associate an ID with the ctx
  -                             // There is nothing to do just let the garbage 
collector do its work
  -                     
  -                     } else
  -                     {
  -                             // Create was called succesfully we go to the cache
  -                             
container.getInstanceCache().release(mi.getEnterpriseContext());
  -                     }
  -             }
  -     }
  -     
  -     public Object invoke(MethodInvocation mi)
  -             throws Exception
  -     {
  -             // Get context
  -             EnterpriseContext ctx = container.getInstanceCache().get(mi.getId());
  -             mi.setEnterpriseContext(ctx);
  -             
  -             try
  -             {
  -                     // Invoke through interceptors
  -                     return getNext().invoke(mi);
  -             } catch (RemoteException e)
  -             {
  -                     // Discard instance
  -                     container.getInstanceCache().remove(mi.getId());
  -                     ctx = null;
  -                     
  -                     throw e;
  -             } catch (RuntimeException e)
  -             {
  -                     // Discard instance
  -                     container.getInstanceCache().remove(mi.getId());
  -                     ctx = null;
  -                     
  -                     throw e;
  -             } catch (Error e)
  -             {
  -                     // Discard instance
  -                     container.getInstanceCache().remove(mi.getId());
  -                     ctx = null;
  -                     
  -                     throw e;
  -             } finally 
  -             {
  -                     if (ctx != null)
  -                     {
  -                             // Still a valid instance
  -                             
  -                             if (ctx.getId() == null)
  -                             {
  -                                     // Remove from cache
  -                                     
container.getInstanceCache().remove(mi.getId());
  -                                     
  -                                     // It has been removed -> send to free pool
  -                                     container.getInstancePool().free(ctx);
  -                             }
  -                             {
  -                                     // Return context
  -                                     container.getInstanceCache().release(ctx);
  -                             }
  -                     }
  -             }
  -     }
  -}
  -
  +/*
  +* jBoss, the OpenSource EJB server
  +*
  +* Distributable under GPL license.
  +* See terms of license at gnu.org.
  +*/
  +package org.jboss.ejb.plugins;
  +
  +import java.lang.reflect.Method;
  +import java.rmi.RemoteException;
  +
  +import org.jboss.ejb.Container;
  +import org.jboss.ejb.InstanceCache;
  +import org.jboss.ejb.InstancePool;
  +import org.jboss.ejb.StatefulSessionContainer;
  +import org.jboss.ejb.StatefulSessionEnterpriseContext;
  +import org.jboss.ejb.EnterpriseContext;
  +import org.jboss.ejb.MethodInvocation;
  +import org.jboss.logging.Logger;
  +import org.jboss.metadata.SessionMetaData;
  +import javax.transaction.Transaction;
  +import javax.transaction.RollbackException;
  +import javax.transaction.Status;
  +import javax.transaction.Synchronization;
  +
  +import javax.ejb.EJBException;
  +
  +
  +/**
  +*   This container acquires the given instance. 
  +*
  +*   @see <related>
  +*   @author Rickard �berg ([EMAIL PROTECTED])
  +*   @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
  +*   @version $Revision: 1.4 $
  +*/
  +public class StatefulSessionInstanceInterceptor
  +extends AbstractInterceptor
  +{
  +     // Constants ----------------------------------------------------
  +     
  +     // Attributes ---------------------------------------------------
  +     protected StatefulSessionContainer container;
  +     
  +     // Static -------------------------------------------------------
  +     
  +     // Constructors -------------------------------------------------
  +     
  +     // Public -------------------------------------------------------
  +     
  +     public void setContainer(Container container) 
  +     { 
  +             this.container = (StatefulSessionContainer)container; 
  +     }
  +     
  +     public  Container getContainer()
  +     {
  +             return container;
  +     }
  +     // Interceptor implementation -----------------------------------
  +     public Object invokeHome(MethodInvocation mi)
  +     throws Exception
  +     {
  +             // Get context
  +             
  +             // get a new context from the pool (this is a home method call)
  +             EnterpriseContext ctx = container.getInstancePool().get();
  +             
  +             
  +             // set the context on the methodInvocation
  +             mi.setEnterpriseContext(ctx);
  +             
  +             // It is a new context for sure so we can lock it
  +             ctx.lock();
  +             
  +             
  +             try
  +             {
  +                     // Invoke through interceptors
  +                     return getNext().invokeHome(mi);
  +             } finally
  +             {
  +                     // Still free? Not free if create() was called successfully
  +                     if (ctx.getId() == null)
  +                     {
  +                             
  +                             
container.getInstancePool().free(mi.getEnterpriseContext()); 
  +                     } else
  +                     {
  +                             // DEBUG  Logger.log("Session was created; not 
returned to pool");
  +                             
  +                             // Create was called succesfully we go to the cache
  +                             synchronized (ctx) {
  +                                     
  +                                     // Release the lock
  +                                     ctx.unlock();
  +                                     
  +                                     //Let the waiters know
  +                                     //ctx.notifyAll();
  +                             }
  +                     }
  +             }
  +     }
  +     
  +     
  +     private void register(EnterpriseContext ctx, Transaction tx)
  +     {
  +             // Create a new synchronization
  +             InstanceSynchronization synch = new InstanceSynchronization(tx, ctx);
  +             
  +             try {
  +                     // OSH: An extra check to avoid warning.
  +                     // Can go when we are sure that we no longer get
  +                     // the JTA violation warning.
  +                     if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
  +                             
  +                             return;
  +                     }
  +                     
  +                     // We want to be notified when the transaction commits
  +                     tx.registerSynchronization(synch);
  +             
  +             } catch (RollbackException e) {
  +             
  +             } catch (Exception e) {
  +                     
  +                     throw new EJBException(e);
  +             
  +             }
  +     }
  +     
  +     public Object invoke(MethodInvocation mi)
  +     throws Exception
  +     {
  +             // Get context
  +             EnterpriseContext ctx = container.getInstanceCache().get(mi.getId());
  +             
  +             // Associate it with the method invocation
  +             mi.setEnterpriseContext(ctx);
  +             
  +             
  +             // We synchronize the locking logic (so we can be reentrant)
  +             synchronized (ctx) 
  +             {
  +                     
  +                     // BMT beans will lock and replace tx no matter what, CMT do 
work on transaction
  +                     if 
(!((SessionMetaData)container.getBeanMetaData()).isBeanManagedTx()) {
  +                             
  +                             // Do we have a running transaction with the context
  +                             if (ctx.getTransaction() != null &&
  +                                     // And are we trying to enter with another 
transaction
  +                                     
!ctx.getTransaction().equals(mi.getTransaction()))
  +                             {
  +                                     // Calls must be in the same transaction
  +                                     throw new RemoteException("Application Error: 
tried to enter Stateful bean with different transaction context");
  +                             }
  +                             
  +                             //If the instance will participate in a new 
transaction we register a sync for it
  +                             if (ctx.getTransaction() == null && 
mi.getTransaction() != null) {
  +                                     
  +                                     register(ctx, mi.getTransaction());
  +                             
  +                             }
  +                     }
  +                     
  +                     if (!ctx.isLocked()){
  +                             
  +                             //take it!
  +                             ctx.lock();  
  +                     }
  +                     
  +                     else 
  +                     {
  +                             
  +                             // Calls must be in the same transaction
  +                             throw new RemoteException("Application Error: no 
concurrent calls on stateful beans");
  +                     }
  +             } 
  +             
  +             try
  +             {
  +                     // Invoke through interceptors
  +                     return getNext().invoke(mi);
  +             } catch (RemoteException e)
  +             {
  +                     // Discard instance
  +                     container.getInstanceCache().remove(mi.getId());
  +                     ctx = null;
  +                     
  +                     throw e;
  +             } catch (RuntimeException e)
  +             {
  +                     // Discard instance
  +                     container.getInstanceCache().remove(mi.getId());
  +                     ctx = null;
  +                     
  +                     throw e;
  +             } catch (Error e)
  +             {
  +                     // Discard instance
  +                     container.getInstanceCache().remove(mi.getId());
  +                     ctx = null;
  +                     
  +                     throw e;
  +             } finally 
  +             {
  +                     if (ctx != null)
  +                     {
  +                             // Still a valid instance
  +                             
  +                             // release it
  +                             ctx.unlock();
  +                             
  +                             // if removed, remove from cache
  +                             if (ctx.getId() == null)
  +                             {
  +                                     // Remove from cache
  +                                     
container.getInstanceCache().remove(mi.getId());
  +                             }
  +                     }
  +             }
  +     }
  +     
  +     // Inner classes -------------------------------------------------
  +     
  +     private class InstanceSynchronization
  +     implements Synchronization
  +     {
  +             /**
  +             *  The transaction we follow.
  +             */
  +             private Transaction tx;
  +             
  +             /**
  +             *  The context we manage.
  +             */
  +             private EnterpriseContext ctx;
  +             
  +             // a utility boolean for session sync
  +             boolean notifySession = false;
  +             
  +             // Utility methods for the notifications
  +             Method beforeCompletion, afterCompletion;
  +             
  +             
  +             /**
  +             *  Create a new instance synchronization instance.
  +             */
  +             InstanceSynchronization(Transaction tx, EnterpriseContext ctx)
  +             {
  +                     this.tx = tx;
  +                     this.ctx = ctx;
  +                     
  +                     // Let's compute it now
  +                     notifySession = (ctx.getInstance() instanceof 
javax.ejb.SessionSynchronization);
  +                     
  +                     if (notifySession) {
  +                             try {
  +                                     
  +                                     // Get the class we are working on
  +                                     Class sync = 
Class.forName("javax.ejb.SessionSynchronization");
  +                                     
  +                                     // Lookup the methods on it
  +                                     beforeCompletion = 
sync.getMethod("beforeCompletion", new Class[0]);
  +                                     
  +                                     afterCompletion =  
sync.getMethod("afterCompletion", new Class[] {Integer.TYPE});
  +                             }
  +                             catch (Exception e) { Logger.exception(e);}
  +                     }
  +             }
  +             
  +             // Synchronization implementation -----------------------------
  +             
  +             public void beforeCompletion()
  +             {
  +                     Logger.log("beforeCompletion called");
  +                     
  +                     // lock the context the transaction is being commited (no need 
for sync)
  +                     ctx.lock();
  +                     
  +                     if (notifySession) {
  +                             try {
  +                                     
  +                                     beforeCompletion.invoke(ctx.getInstance(), new 
Object[0]);
  +                             }
  +                             catch (Exception e) { Logger.exception(e);}
  +                     }
  +             }
  +             
  +             public void afterCompletion(int status)
  +             {
  +                     Logger.log("afterCompletion called");
  +                     
  +                     // finish the transaction association
  +                     ctx.setTransaction(null);
  +                     
  +                     // unlock this context
  +                     ctx.unlock();
  +                     
  +                     if (notifySession) {
  +                             
  +                             try {
  +                                     
  +                                     afterCompletion.invoke(ctx.getInstance(), new 
Object[] {new Integer(status)});
  +                             }
  +                             catch (Exception e) {Logger.exception(e);}
  +                     }
  +             
  +             
  +             }
  +     }
  +}
  +
  
  
  
  1.3       +6 -1      
jboss/src/main/org/jboss/ejb/plugins/StatelessSessionInstanceInterceptor.java
  
  Index: StatelessSessionInstanceInterceptor.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/StatelessSessionInstanceInterceptor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- StatelessSessionInstanceInterceptor.java  2000/06/16 13:10:23     1.2
  +++ StatelessSessionInstanceInterceptor.java  2000/09/26 18:58:32     1.3
  @@ -39,7 +39,7 @@
    *
    *   @see <related>
    *   @author Rickard �berg ([EMAIL PROTECTED])
  - *   @version $Revision: 1.2 $
  + *   @version $Revision: 1.3 $
    */
   public class StatelessSessionInstanceInterceptor
      extends AbstractInterceptor
  @@ -77,6 +77,9 @@
         // Get context
         mi.setEnterpriseContext(container.getInstancePool().get());
         
  +       // There is no need for synchronization since the instance is always fresh 
also there should
  +       // never be a tx associated with the instance.
  +      
         try
         {
            // Invoke through interceptors
  @@ -86,6 +89,8 @@
            // Return context
            container.getInstancePool().free(mi.getEnterpriseContext());
         }
  +       
      }
  +   
   }
   
  
  
  
  1.1                  jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java
  
  Index: TxInterceptorCMT.java
  ===================================================================
  /*
  * jBoss, the OpenSource EJB server
  *
  * Distributable under GPL license.
  * See terms of license at gnu.org.
  */
  package org.jboss.ejb.plugins;
  
  import java.lang.reflect.Method;
  import java.rmi.RemoteException;
  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.ejb.EJBException;
  
  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;
  import org.jboss.metadata.BeanMetaData;
  import org.jboss.metadata.MethodMetaData;
  
  /**
  *   <description>
  *
  *   @see <related>
  *   @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.1 $
  */
  public class TxInterceptorCMT
  extends AbstractInterceptor
  {
      
      // Attributes ----------------------------------------------------
      private TxManager 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();
          
          // 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
      *
      * @param   id
      * @param   m
      * @param   args
      * @return
      * @exception   Exception
      */
      public Object invoke(MethodInvocation mi) throws Exception {
          return runWithTransactions(true, mi);
      }
      
      private void printMethod(Method m, byte type) {
          String name;
          switch(type) {
              case MetaData.TX_MANDATORY:
                  name = "TX_MANDATORY";
              break;
              case MetaData.TX_NEVER:
                  name = "TX_NEVER";
              break;
              case MetaData.TX_NOT_SUPPORTED:
                  name = "TX_NOT_SUPPORTED";
              break;
              case MetaData.TX_REQUIRED:
                  name = "TX_REQUIRED";
              break;
              case MetaData.TX_REQUIRES_NEW:
                  name = "TX_REQUIRES_NEW";
              break;
              case MetaData.TX_SUPPORTS:
                  name = "TX_SUPPORTS";
              break;
              default:
                  name = "TX_UNKNOWN";
          }
          Logger.debug(name+" for "+m.getName());
      }
      
      private Object invokeNext(boolean remoteInvocation, MethodInvocation mi) throws 
Exception {
          if (remoteInvocation) {
              return getNext().invoke(mi);
          } else {
              return getNext().invokeHome(mi);
          }
      }
      
      /*
      * 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 
      * 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 {
          
          // 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.log("Current transaction in MI is 
"+mi.getTransaction()); 
          //DEBUG       Logger.log("Current method "+mi.getMethod().getName());        
   
          byte transType = getTransactionMethod(mi.getMethod(), remoteInvocation);
          
          printMethod(mi.getMethod(), transType);
          
          switch (transType) {
              
              case MetaData.TX_NOT_SUPPORTED: 
                  {
                      
                      
                      // 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();
                      
                      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);
                          }
                      }
                  }
                  
                  
              case MetaData.TX_REQUIRED:      
                  {
                      
                      if (oldTransaction == null) { // No tx running
                          
                          // Create tx 
                          tm.begin();
                          
                          // get the tx
                          newTransaction = tm.getTransaction();
                          
                          // Let the method invocation know
                          mi.setTransaction(newTransaction);            
                      }
                      
                      else { // We have a tx propagated
                          
                          // Associate it with the thread
                          tm.associateThread(oldTransaction);
                      }
                      
                      // Continue invocation
                      try       {
                          
                          return invokeNext(remoteInvocation,mi );
                      } 
                      catch (RemoteException e) {
                          
                          if (newTransaction != null) {
                              
                              //We started it, 
                              newTransaction.rollback();
                          }
                          
                          throw e;
                      } 
                      catch (RuntimeException e) {
                          
                          if (newTransaction != null) {
                              
                              // We started it
                              newTransaction.rollback();
                          }
                          
                          throw new ServerException("Exception occurred", e);
                      } 
                      catch (Error e) {
                          
                          if (newTransaction != null) {
                              
                              // we started it
                              newTransaction.rollback();
                          }
                          throw new ServerException("Exception 
occurred:"+e.getMessage());
                      } 
                      
                      finally {
                          
                          //DEBUG Logger.log("TxInterceptorCMT: in finally");
                          Logger.log("TxInterceptorCMT: In finally");
                          
                          // Only do something if we started the transaction
                          if (newTransaction != null) {
                              
                              // Marked rollback
                              if (newTransaction.getStatus() == 
Status.STATUS_MARKED_ROLLBACK) {
                                  
                                  // actually roll it back 
                                  newTransaction.rollback();
                              }
                              
                              //Still running
                              else if(newTransaction.getStatus() == 
Status.STATUS_ACTIVE) {
                                  
                                  // Commit tx
                                  // This will happen if
                                  // a) everything goes well
                                  // b) app. exception was thrown
                                  Logger.log("TxInterceptorCMT:before commit");
                                  newTransaction.commit();
                                  Logger.log("TxInterceptorCMT:after commit");
                              
                              }
                              
                              // reassociate the oldTransaction with the 
methodInvocation (even null)
                              mi.setTransaction(oldTransaction);
                          }
                      }
                  }
                  
              case MetaData.TX_SUPPORTS: 
                  {
                      
                      if (oldTransaction != null) { // We have a tx propagated
                          
                          // Associate it with the thread
                          tm.associateThread(oldTransaction);
                      }
                      
                      // 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
                  
                  }
                  
              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.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
                          newTransaction.rollback();
                          
                          throw e;
                      } 
                      catch (RuntimeException e) {
                          
                          // We started it for sure
                          newTransaction.rollback();
                          
                          throw new ServerException("Exception occurred", e);
                      } 
                      catch (Error e) {
                          
                          // We started it for sure
                          newTransaction.rollback();
                          
                          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);
                          }
                      } 
                  }
                  
              case MetaData.TX_MANDATORY: 
                  {
                      
                      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 );
                      }
                  }
                  
              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.log("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 
          if (result == MetaData.TX_UNKNOWN) result = MetaData.TX_REQUIRED;
              
          methodTx.put(m, new Byte(result));
          return result;
      }
      
      // Inner classes -------------------------------------------------
      
  }
  
  
  

Reply via email to