User: salborini
Date: 00/09/26 13:18:53
Modified: src/main/org/jboss/ejb/plugins BMPPersistenceManager.java
CMPPersistenceManager.java
EntityInstanceInterceptor.java
EntityInstancePool.java
EntitySynchronizationInterceptor.java
NoPassivationEntityInstanceCache.java
NoPassivationStatefulSessionInstanceCache.java
RandomEntityInstanceCache.java
StatefulSessionFilePersistenceManager.java
StatefulSessionInstanceInterceptor.java
TxInterceptorCMT.java
Log:
Removed DOS ^M at the end of each line
Revision Changes Path
1.9 +315 -315 jboss/src/main/org/jboss/ejb/plugins/BMPPersistenceManager.java
Index: BMPPersistenceManager.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/BMPPersistenceManager.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- BMPPersistenceManager.java 2000/09/26 18:39:06 1.8
+++ BMPPersistenceManager.java 2000/09/26 20:18:50 1.9
@@ -1,315 +1,315 @@
-/*
-* 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.lang.reflect.InvocationTargetException;
-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import java.util.Collection;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-
-import javax.ejb.EntityBean;
-import javax.ejb.CreateException;
-import javax.ejb.FinderException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.EntityInstanceCache;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.logging.Logger;
-
-
-/**
-* <description>
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.8 $
-*/
-public class BMPPersistenceManager
-implements EntityPersistenceManager
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- EntityContainer con;
-
- Method ejbLoad;
- Method ejbStore;
- Method ejbActivate;
- Method ejbPassivate;
- Method ejbRemove;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container c)
- {
- con = (EntityContainer)c;
- }
-
- public void init()
- throws Exception
- {
- ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
- ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
- ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
- ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new Class[0]);
- ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
- }
-
- public void start()
- {
- }
-
- public void stop()
- {
- }
-
- public void destroy()
- {
- }
-
- public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
- throws RemoteException, CreateException
- {
- // Get methods
- try
- {
- Method createMethod = null;
- Method postCreateMethod = null;
-
- // try to get the create method
- try {
- createMethod = con.getBeanClass().getMethod("ejbCreate",
m.getParameterTypes());
- } catch (NoSuchMethodException nsme) {
- throw new CreateException("corresponding ejbCreate not found " +
parametersToString(m.getParameterTypes()) + nsme);
- }
-
- // try to get the post create method
- try {
- postCreateMethod = con.getBeanClass().getMethod("ejbPostCreate",
m.getParameterTypes());
- } catch (NoSuchMethodException nsme) {
- throw new CreateException("corresponding ejbPostCreate not found " +
parametersToString(m.getParameterTypes()) + nsme);
- }
-
- Object id = null;
- try {
- // Call ejbCreate
- id = createMethod.invoke(ctx.getInstance(), args);
- } catch (InvocationTargetException ite) {
- throw new CreateException("Create failed(could not call ejbCreate):"+ite);
- }
-
- // set the id
- ctx.setId(id);
-
- // Create a new CacheKey
- Object cacheKey = ((EntityInstanceCache)
con.getInstanceCache()).createCacheKey( id );
-
- // Give it to the context
- ctx.setCacheKey(cacheKey);
-
- // We are going in cache so lock the instance (no need to synch we are
alone on it)
- ctx.lock();
-
- // Insert in cache, it is now safe
- ((EntityInstanceCache) con.getInstanceCache()).insert(ctx);
-
- // Create EJBObject
- ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(cacheKey));
-
- try {
- postCreateMethod.invoke(ctx.getInstance(), args);
- } catch (InvocationTargetException ite) {
- throw new CreateException("Create failed(could not call ejbPostCreate):"
+ ite);
- }
-
- // } 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 Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException
- {
- // call the finder method
- Object objectId = callFinderMethod(finderMethod, args, ctx);
-
- // get the cache, create a new key and return this new key
- return ((EntityInstanceCache)con.getInstanceCache()).createCacheKey(
objectId );
- }
-
- public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException
- {
- // call the finder method
- Object result = callFinderMethod(finderMethod, args, ctx);
-
- if (result == null) {
- // for EJB 1.0 compliance
- // if the bean couldn't find any matching entities
- // it returns null, so we return an empty collection
- return new ArrayList();
- }
-
- if (result instanceof java.util.Enumeration) {
- // to preserve 1.0 spec compatiblity
- ArrayList array = new ArrayList();
- Enumeration enum = (Enumeration) result;
- while (enum.hasMoreElements() == true) {
- // Wrap a cache key around the given object id/primary key
- array.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(enum.nextElement()));
- }
- return array;
- }
- else if (result instanceof java.util.Collection) {
-
- ArrayList array = new ArrayList(((Collection) result).size());
- Iterator enum = ((Collection) result).iterator();
- while (enum.hasNext()) {
- // Wrap a cache key around the given object id/primary key
- array.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(enum.next()));
- }
- return array;
- }
- else {
- // so we received something that's not valid
- // throw an exception reporting it
- throw new RemoteException("result of finder method is not a valid return
type: " + result.getClass());
- }
- }
-
- public void activateEntity(EntityEnterpriseContext ctx)
- throws RemoteException
- {
- try
- {
- ejbActivate.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Activate failed", e);
- }
- }
-
- public void loadEntity(EntityEnterpriseContext ctx)
- throws RemoteException
- {
- try
- {
- ejbLoad.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Load failed", e);
- }
- }
-
- public void storeEntity(EntityEnterpriseContext ctx)
- throws RemoteException
- {
- // Logger.log("Store entity");
- try
- {
- ejbStore.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Store failed", e);
- }
- }
-
- public void passivateEntity(EntityEnterpriseContext ctx)
- throws RemoteException
- {
- try
- {
- ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Passivate failed", e);
- }
- }
-
- public void removeEntity(EntityEnterpriseContext ctx)
- throws RemoteException
- {
- try
- {
- ejbRemove.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Remove failed", e);
- }
- }
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // Private -------------------------------------------------------
- private Object callFinderMethod(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException
- {
- // get the finder method
- Method callMethod = null;
- try {
- callMethod = getFinderMethod(con.getBeanClass(), finderMethod, args);
- } catch (NoSuchMethodException me) {
- // debug
- //Logger.exception(me);
- throw new RemoteException("couldn't find finder method in bean class. " +
me.toString());
- }
-
- // invoke the finder method
- Object result = null;
- try {
- result = callMethod.invoke(ctx.getInstance(), args);
- } catch (InvocationTargetException e) {
- Throwable targetException = e.getTargetException();
- if (targetException instanceof FinderException) {
- throw (FinderException)targetException;
- }
- else {
- throw new ServerException("exception occured while invoking finder
method", (Exception)targetException);
- }
- } catch (Exception e) {
- // debug
- // DEBUG Logger.exception(e);
- throw new ServerException("exception occured while invoking finder
method",e);
- }
-
- return result;
- }
-
- private Method getFinderMethod(Class beanClass, Method finderMethod, Object[]
args) throws NoSuchMethodException {
- String methodName = "ejbF" + finderMethod.getName().substring(1);
- return beanClass.getMethod(methodName, finderMethod.getParameterTypes());
- }
-
- private String parametersToString(Object []a) {
- String r = new String();
- for(int i=0;i<a.length;i++) r = r + ", " + a[i];
- return r;
- }
-
- // 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.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.ejb.EntityBean;
+import javax.ejb.CreateException;
+import javax.ejb.FinderException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.EntityInstanceCache;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.logging.Logger;
+
+
+/**
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.9 $
+*/
+public class BMPPersistenceManager
+implements EntityPersistenceManager
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ EntityContainer con;
+
+ Method ejbLoad;
+ Method ejbStore;
+ Method ejbActivate;
+ Method ejbPassivate;
+ Method ejbRemove;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container c)
+ {
+ con = (EntityContainer)c;
+ }
+
+ public void init()
+ throws Exception
+ {
+ ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
+ ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
+ ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
+ ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new Class[0]);
+ ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
+ }
+
+ public void start()
+ {
+ }
+
+ public void stop()
+ {
+ }
+
+ public void destroy()
+ {
+ }
+
+ public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
+ throws RemoteException, CreateException
+ {
+ // Get methods
+ try
+ {
+ Method createMethod = null;
+ Method postCreateMethod = null;
+
+ // try to get the create method
+ try {
+ createMethod = con.getBeanClass().getMethod("ejbCreate",
m.getParameterTypes());
+ } catch (NoSuchMethodException nsme) {
+ throw new CreateException("corresponding ejbCreate not found " +
parametersToString(m.getParameterTypes()) + nsme);
+ }
+
+ // try to get the post create method
+ try {
+ postCreateMethod = con.getBeanClass().getMethod("ejbPostCreate",
m.getParameterTypes());
+ } catch (NoSuchMethodException nsme) {
+ throw new CreateException("corresponding ejbPostCreate not found " +
parametersToString(m.getParameterTypes()) + nsme);
+ }
+
+ Object id = null;
+ try {
+ // Call ejbCreate
+ id = createMethod.invoke(ctx.getInstance(), args);
+ } catch (InvocationTargetException ite) {
+ throw new CreateException("Create failed(could not call ejbCreate):"+ite);
+ }
+
+ // set the id
+ ctx.setId(id);
+
+ // Create a new CacheKey
+ Object cacheKey = ((EntityInstanceCache)
con.getInstanceCache()).createCacheKey( id );
+
+ // Give it to the context
+ ctx.setCacheKey(cacheKey);
+
+ // We are going in cache so lock the instance (no need to synch we are
alone on it)
+ ctx.lock();
+
+ // Insert in cache, it is now safe
+ ((EntityInstanceCache) con.getInstanceCache()).insert(ctx);
+
+ // Create EJBObject
+ ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(cacheKey));
+
+ try {
+ postCreateMethod.invoke(ctx.getInstance(), args);
+ } catch (InvocationTargetException ite) {
+ throw new CreateException("Create failed(could not call ejbPostCreate):"
+ ite);
+ }
+
+ // } 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 Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException
+ {
+ // call the finder method
+ Object objectId = callFinderMethod(finderMethod, args, ctx);
+
+ // get the cache, create a new key and return this new key
+ return ((EntityInstanceCache)con.getInstanceCache()).createCacheKey(
objectId );
+ }
+
+ public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException
+ {
+ // call the finder method
+ Object result = callFinderMethod(finderMethod, args, ctx);
+
+ if (result == null) {
+ // for EJB 1.0 compliance
+ // if the bean couldn't find any matching entities
+ // it returns null, so we return an empty collection
+ return new ArrayList();
+ }
+
+ if (result instanceof java.util.Enumeration) {
+ // to preserve 1.0 spec compatiblity
+ ArrayList array = new ArrayList();
+ Enumeration enum = (Enumeration) result;
+ while (enum.hasMoreElements() == true) {
+ // Wrap a cache key around the given object id/primary key
+ array.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(enum.nextElement()));
+ }
+ return array;
+ }
+ else if (result instanceof java.util.Collection) {
+
+ ArrayList array = new ArrayList(((Collection) result).size());
+ Iterator enum = ((Collection) result).iterator();
+ while (enum.hasNext()) {
+ // Wrap a cache key around the given object id/primary key
+ array.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(enum.next()));
+ }
+ return array;
+ }
+ else {
+ // so we received something that's not valid
+ // throw an exception reporting it
+ throw new RemoteException("result of finder method is not a valid return
type: " + result.getClass());
+ }
+ }
+
+ public void activateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException
+ {
+ try
+ {
+ ejbActivate.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Activate failed", e);
+ }
+ }
+
+ public void loadEntity(EntityEnterpriseContext ctx)
+ throws RemoteException
+ {
+ try
+ {
+ ejbLoad.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Load failed", e);
+ }
+ }
+
+ public void storeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException
+ {
+ // Logger.log("Store entity");
+ try
+ {
+ ejbStore.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Store failed", e);
+ }
+ }
+
+ public void passivateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException
+ {
+ try
+ {
+ ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Passivate failed", e);
+ }
+ }
+
+ public void removeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException
+ {
+ try
+ {
+ ejbRemove.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Remove failed", e);
+ }
+ }
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+ private Object callFinderMethod(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException
+ {
+ // get the finder method
+ Method callMethod = null;
+ try {
+ callMethod = getFinderMethod(con.getBeanClass(), finderMethod, args);
+ } catch (NoSuchMethodException me) {
+ // debug
+ //Logger.exception(me);
+ throw new RemoteException("couldn't find finder method in bean class. " +
me.toString());
+ }
+
+ // invoke the finder method
+ Object result = null;
+ try {
+ result = callMethod.invoke(ctx.getInstance(), args);
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ if (targetException instanceof FinderException) {
+ throw (FinderException)targetException;
+ }
+ else {
+ throw new ServerException("exception occured while invoking finder
method", (Exception)targetException);
+ }
+ } catch (Exception e) {
+ // debug
+ // DEBUG Logger.exception(e);
+ throw new ServerException("exception occured while invoking finder
method",e);
+ }
+
+ return result;
+ }
+
+ private Method getFinderMethod(Class beanClass, Method finderMethod, Object[]
args) throws NoSuchMethodException {
+ String methodName = "ejbF" + finderMethod.getName().substring(1);
+ return beanClass.getMethod(methodName, finderMethod.getParameterTypes());
+ }
+
+ private String parametersToString(Object []a) {
+ String r = new String();
+ for(int i=0;i<a.length;i++) r = r + ", " + a[i];
+ return r;
+ }
+
+ // Inner classes -------------------------------------------------
+}
+
1.7 +274 -274 jboss/src/main/org/jboss/ejb/plugins/CMPPersistenceManager.java
Index: CMPPersistenceManager.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/CMPPersistenceManager.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- CMPPersistenceManager.java 2000/09/26 18:39:58 1.6
+++ CMPPersistenceManager.java 2000/09/26 20:18:50 1.7
@@ -1,274 +1,274 @@
-/*
-* 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.lang.reflect.InvocationTargetException;
-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.ArrayList;
-
-import javax.ejb.EntityBean;
-import javax.ejb.CreateException;
-import javax.ejb.FinderException;
-import javax.ejb.RemoveException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.ejb.EntityInstanceCache;
-import org.jboss.ejb.EntityPersistenceStore;
-
-/**
-* The CMP Persistence Manager implements the semantics of the CMP
-* EJB 1.1 call back specification.
-*
-* This Manager works with a "EntityPersistenceStore" that takes care of the
-* physical storing of instances (JAWS, JDBC O/R, FILE, Object).
-*
-* @see <related>
-* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.6 $
-*/
-public class CMPPersistenceManager
-implements EntityPersistenceManager {
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- EntityContainer con;
- // Physical persistence implementation
- EntityPersistenceStore store;
-
- // The EJB Methods, the reason for this class
- Method ejbLoad;
- Method ejbStore;
- Method ejbActivate;
- Method ejbPassivate;
- Method ejbRemove;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container c) {
- con = (EntityContainer)c;
- if (store != null) store.setContainer(c);
- }
-
-
- public void setPersistenceStore(EntityPersistenceStore store) {
- this.store= store;
-
- //Give it the container
- if (con!= null) store.setContainer(con);
- }
-
- public void init()
- throws Exception {
-
- // The common EJB methods
- ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
- ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
- ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
- ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new Class[0]);
- ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
-
- // Initialize the sto re
- store.init();
- }
-
- public void start()
- throws Exception {
-
- store.start();
- }
-
- public void stop() {
- store.stop();
- }
-
- public void destroy() {
- store.destroy();
- }
-
- public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
- throws RemoteException, CreateException {
- // Get methods
- try {
-
- Method createMethod = con.getBeanClass().getMethod("ejbCreate",
m.getParameterTypes());
- Method postCreateMethod = con.getBeanClass().getMethod("ejbPostCreate",
m.getParameterTypes());
-
- // Call ejbCreate on the target bean
- createMethod.invoke(ctx.getInstance(), args);
-
- // Have the store persist the new instance, the return is the key
- Object id = store.createEntity(m, args, ctx);
-
- // Set the key on the target context
- ctx.setId(id);
-
- // Create a new CacheKey
- Object cacheKey = ((EntityInstanceCache)
con.getInstanceCache()).createCacheKey( id );
-
- // Give it to the context
- ctx.setCacheKey(cacheKey);
-
-
- // insert instance in cache, it is safe
- ((EntityInstanceCache) con.getInstanceCache()).insert(ctx);
-
- // Create EJBObject
-
ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(cacheKey));
-
- postCreateMethod.invoke(ctx.getInstance(), args);
-
- }
- 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 Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException {
-
- // The store will find the entity and return the primaryKey
- Object id = store.findEntity(finderMethod, args, ctx);
-
- // We return the cache key
- return ((EntityInstanceCache) con.getInstanceCache()).createCacheKey(id);
- }
-
- public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException {
-
- // The store will find the id and return a collection of PrimaryKeys
- Collection ids = store.findEntities(finderMethod, args, ctx);
-
- // Build a collection of cacheKeys
- ArrayList list = new ArrayList(ids.size());
- Iterator idEnum = ids.iterator();
- while(idEnum.hasNext()) {
-
- // Get a cache key for it
- list.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(idEnum.next()));
- }
-
- return list;
- }
-
- /*
- * activateEntity(EnterpriseContext ctx)
- *
- * The method calls the target beans for spec compliant callbacks.
- * Since these are pure EJB calls it is not obvious that the store should
- * expose the interfaces. In case of jaws however we found that store specific
- * contexts could be set in the activateEntity calls and hence a propagation of
- * the call made sense. The persistence store is called for "extension"
purposes.
- *
- * @see activateEntity on EntityPersistenceStore.java
- */
- public void activateEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- // Call bean
- try
- {
- ejbActivate.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Activation failed", e);
- }
-
- store.activateEntity(ctx);
- }
-
- public void loadEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- try {
-
- // Have the store deal with create the fields of the instance
- store.loadEntity(ctx);
-
- // Call ejbLoad on bean instance, wake up!
- ejbLoad.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e) {
- throw new ServerException("Load failed", e);
- }
- }
-
- public void storeEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
- // Logger.log("Store entity");
- try {
-
- // Prepare the instance for storage
- ejbStore.invoke(ctx.getInstance(), new Object[0]);
-
- // Have the store deal with storing the fields of the instance
- store.storeEntity(ctx);
- }
-
- catch (Exception e) {
- throw new ServerException("Store failed", e);
- }
- }
-
- public void passivateEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- try {
-
- // Prepare the instance for passivation
- ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e) {
-
- throw new ServerException("Passivation failed", e);
- }
-
- store.passivateEntity(ctx);
- }
-
- public void removeEntity(EntityEnterpriseContext ctx)
- throws RemoteException, RemoveException {
-
- try {
-
- // Call ejbRemove
- ejbRemove.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e){
-
- throw new RemoveException("Could not remove "+ctx.getId());
- }
-
- store.removeEntity(ctx);
- }
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // 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.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+import javax.ejb.EntityBean;
+import javax.ejb.CreateException;
+import javax.ejb.FinderException;
+import javax.ejb.RemoveException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.ejb.EntityInstanceCache;
+import org.jboss.ejb.EntityPersistenceStore;
+
+/**
+* The CMP Persistence Manager implements the semantics of the CMP
+* EJB 1.1 call back specification.
+*
+* This Manager works with a "EntityPersistenceStore" that takes care of the
+* physical storing of instances (JAWS, JDBC O/R, FILE, Object).
+*
+* @see <related>
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.7 $
+*/
+public class CMPPersistenceManager
+implements EntityPersistenceManager {
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ EntityContainer con;
+ // Physical persistence implementation
+ EntityPersistenceStore store;
+
+ // The EJB Methods, the reason for this class
+ Method ejbLoad;
+ Method ejbStore;
+ Method ejbActivate;
+ Method ejbPassivate;
+ Method ejbRemove;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container c) {
+ con = (EntityContainer)c;
+ if (store != null) store.setContainer(c);
+ }
+
+
+ public void setPersistenceStore(EntityPersistenceStore store) {
+ this.store= store;
+
+ //Give it the container
+ if (con!= null) store.setContainer(con);
+ }
+
+ public void init()
+ throws Exception {
+
+ // The common EJB methods
+ ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
+ ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
+ ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
+ ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new Class[0]);
+ ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
+
+ // Initialize the sto re
+ store.init();
+ }
+
+ public void start()
+ throws Exception {
+
+ store.start();
+ }
+
+ public void stop() {
+ store.stop();
+ }
+
+ public void destroy() {
+ store.destroy();
+ }
+
+ public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
+ throws RemoteException, CreateException {
+ // Get methods
+ try {
+
+ Method createMethod = con.getBeanClass().getMethod("ejbCreate",
m.getParameterTypes());
+ Method postCreateMethod = con.getBeanClass().getMethod("ejbPostCreate",
m.getParameterTypes());
+
+ // Call ejbCreate on the target bean
+ createMethod.invoke(ctx.getInstance(), args);
+
+ // Have the store persist the new instance, the return is the key
+ Object id = store.createEntity(m, args, ctx);
+
+ // Set the key on the target context
+ ctx.setId(id);
+
+ // Create a new CacheKey
+ Object cacheKey = ((EntityInstanceCache)
con.getInstanceCache()).createCacheKey( id );
+
+ // Give it to the context
+ ctx.setCacheKey(cacheKey);
+
+
+ // insert instance in cache, it is safe
+ ((EntityInstanceCache) con.getInstanceCache()).insert(ctx);
+
+ // Create EJBObject
+
ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(cacheKey));
+
+ postCreateMethod.invoke(ctx.getInstance(), args);
+
+ }
+ 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 Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException {
+
+ // The store will find the entity and return the primaryKey
+ Object id = store.findEntity(finderMethod, args, ctx);
+
+ // We return the cache key
+ return ((EntityInstanceCache) con.getInstanceCache()).createCacheKey(id);
+ }
+
+ public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException {
+
+ // The store will find the id and return a collection of PrimaryKeys
+ Collection ids = store.findEntities(finderMethod, args, ctx);
+
+ // Build a collection of cacheKeys
+ ArrayList list = new ArrayList(ids.size());
+ Iterator idEnum = ids.iterator();
+ while(idEnum.hasNext()) {
+
+ // Get a cache key for it
+ list.add(((EntityInstanceCache)
con.getInstanceCache()).createCacheKey(idEnum.next()));
+ }
+
+ return list;
+ }
+
+ /*
+ * activateEntity(EnterpriseContext ctx)
+ *
+ * The method calls the target beans for spec compliant callbacks.
+ * Since these are pure EJB calls it is not obvious that the store should
+ * expose the interfaces. In case of jaws however we found that store specific
+ * contexts could be set in the activateEntity calls and hence a propagation of
+ * the call made sense. The persistence store is called for "extension"
purposes.
+ *
+ * @see activateEntity on EntityPersistenceStore.java
+ */
+ public void activateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ // Call bean
+ try
+ {
+ ejbActivate.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Activation failed", e);
+ }
+
+ store.activateEntity(ctx);
+ }
+
+ public void loadEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ try {
+
+ // Have the store deal with create the fields of the instance
+ store.loadEntity(ctx);
+
+ // Call ejbLoad on bean instance, wake up!
+ ejbLoad.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e) {
+ throw new ServerException("Load failed", e);
+ }
+ }
+
+ public void storeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+ // Logger.log("Store entity");
+ try {
+
+ // Prepare the instance for storage
+ ejbStore.invoke(ctx.getInstance(), new Object[0]);
+
+ // Have the store deal with storing the fields of the instance
+ store.storeEntity(ctx);
+ }
+
+ catch (Exception e) {
+ throw new ServerException("Store failed", e);
+ }
+ }
+
+ public void passivateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ try {
+
+ // Prepare the instance for passivation
+ ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e) {
+
+ throw new ServerException("Passivation failed", e);
+ }
+
+ store.passivateEntity(ctx);
+ }
+
+ public void removeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException, RemoveException {
+
+ try {
+
+ // Call ejbRemove
+ ejbRemove.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e){
+
+ throw new RemoveException("Could not remove "+ctx.getId());
+ }
+
+ store.removeEntity(ctx);
+ }
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+}
+
1.9 +261 -261
jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java
Index: EntityInstanceInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- EntityInstanceInterceptor.java 2000/09/26 18:41:15 1.8
+++ EntityInstanceInterceptor.java 2000/09/26 20:18:50 1.9
@@ -1,261 +1,261 @@
-/*
-* 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.util.Map;
-import java.util.HashMap;
-import java.util.ArrayList;
-
-import javax.ejb.EJBObject;
-import javax.ejb.CreateException;
-import javax.ejb.EJBException;
-import javax.ejb.NoSuchEntityException;
-import javax.ejb.RemoveException;
-import javax.ejb.EntityBean;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.InstanceCache;
-import org.jboss.ejb.InstancePool;
-import org.jboss.ejb.MethodInvocation;
-import org.jboss.ejb.CacheKey;
-import org.jboss.metadata.EntityMetaData;
-
-/**
-* This container acquires the given instance.
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.8 $
-*/
-public class EntityInstanceInterceptor
-extends AbstractInterceptor
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- protected EntityContainer container;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = (EntityContainer)container;
- }
-
- public Container getContainer()
- {
- return container;
- }
-
- // Interceptor implementation --------------------------------------
- public Object invokeHome(MethodInvocation mi)
- throws Exception
- {
- // Get context
- EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstancePool().get();
- mi.setEnterpriseContext(ctx);
-
- // It is a new context for sure so we can lock it (no need for sync
(not in cache))
- ctx.lock();
-
- try
- {
- // Invoke through interceptors
- return getNext().invokeHome(mi);
- } finally
- {
- // Still free? Not free if create() was called successfully
- if (mi.getEnterpriseContext().getId() == null)
- {
- // Free that context
- ctx.unlock();
-
-
container.getInstancePool().free(mi.getEnterpriseContext());
- }
- else
- {
- // DEBUG Logger.log("Entity was created; not
returned to pool");
- synchronized (ctx) {
-
- // Release the lock
- ctx.unlock();
-
- //Let the waiters know
- ctx.notifyAll();
- }
- }
- }
- }
-
- public Object invoke(MethodInvocation mi)
- throws Exception
- {
- // The id store is a CacheKey in the case of Entity
- CacheKey key = (CacheKey) mi.getId();
-
- // Get context
- EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstanceCache().get(key);
-
- // Set it on the method invocation
- mi.setEnterpriseContext(ctx);
-
- // We synchronize the locking logic (so that the invoke is
unsynchronized and can be reentrant)
- synchronized (ctx)
- {
- // 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()))
- {
- // Let's put the thread to sleep a lock release will
wake the thread
- try{ctx.wait();}
- catch (InterruptedException ie) {}
-
- // Try your luck again
- return invoke(mi);
- }
-
- if (!ctx.isLocked()){
-
- //take it!
- ctx.lock();
- }
-
- else
- {
- if (!isCallAllowed(mi)) {
-
- // Let's put the thread to sleep a lock
release will wake the thread
- try{ctx.wait();}
- catch (InterruptedException ie) {}
-
- // Try your luck again
- return invoke(mi);
- }
-
- // The call is allowed, do increment the lock though
(ctx already locked)
- ctx.lock();
- }
-
- }
-
- try {
-
- // Go on, you won
- return getNext().invoke(mi);
-
- }
- catch (RemoteException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
-
- throw e;
- } catch (RuntimeException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
-
- throw e;
- } catch (Error e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
-
- throw e;
- } finally
- {
- // Logger.log("Release instance for "+id);
- if (ctx != null)
- {
-
- synchronized (ctx) {
-
- // unlock the context
- ctx.unlock();
-
- if (ctx.getId() == null)
- {
- // Remove from cache
-
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
-
- // It has been removed -> send to free
pool
- container.getInstancePool().free(ctx);
- }
-
- // notify the thread waiting on ctx
- ctx.notifyAll();
- }
- }
- }
- }
-
- // Private --------------------------------------------------------
-
- private static Method getEJBHome;
- private static Method getHandle;
- private static Method getPrimaryKey;
- private static Method isIdentical;
- private static Method remove;
- static
- {
- try
- {
- Class[] noArg = new Class[0];
- getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
- getHandle = EJBObject.class.getMethod("getHandle", noArg);
- getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey",
noArg);
- isIdentical = EJBObject.class.getMethod("isIdentical", new
Class[] {EJBObject.class});
- remove = EJBObject.class.getMethod("remove", noArg);
- }
- catch (Exception x) {x.printStackTrace();}
- }
-
- private boolean isCallAllowed(MethodInvocation mi)
- {
- boolean reentrant =
((EntityMetaData)container.getBeanMetaData()).isReentrant();
-
- if (reentrant)
- {
- return true;
- }
- else
- {
- Method m = mi.getMethod();
- if (m.equals(getEJBHome) ||
- m.equals(getHandle) ||
- m.equals(getPrimaryKey) ||
- m.equals(isIdentical) ||
- m.equals(remove))
- {
- return true;
- }
- }
-
- return false;
- }
-}
-
+/*
+* 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.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import javax.ejb.EJBObject;
+import javax.ejb.CreateException;
+import javax.ejb.EJBException;
+import javax.ejb.NoSuchEntityException;
+import javax.ejb.RemoveException;
+import javax.ejb.EntityBean;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.InstanceCache;
+import org.jboss.ejb.InstancePool;
+import org.jboss.ejb.MethodInvocation;
+import org.jboss.ejb.CacheKey;
+import org.jboss.metadata.EntityMetaData;
+
+/**
+* This container acquires the given instance.
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.9 $
+*/
+public class EntityInstanceInterceptor
+extends AbstractInterceptor
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ protected EntityContainer container;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container container)
+ {
+ this.container = (EntityContainer)container;
+ }
+
+ public Container getContainer()
+ {
+ return container;
+ }
+
+ // Interceptor implementation --------------------------------------
+ public Object invokeHome(MethodInvocation mi)
+ throws Exception
+ {
+ // Get context
+ EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstancePool().get();
+ mi.setEnterpriseContext(ctx);
+
+ // It is a new context for sure so we can lock it (no need for sync
(not in cache))
+ ctx.lock();
+
+ try
+ {
+ // Invoke through interceptors
+ return getNext().invokeHome(mi);
+ } finally
+ {
+ // Still free? Not free if create() was called successfully
+ if (mi.getEnterpriseContext().getId() == null)
+ {
+ // Free that context
+ ctx.unlock();
+
+
container.getInstancePool().free(mi.getEnterpriseContext());
+ }
+ else
+ {
+ // DEBUG Logger.log("Entity was created; not
returned to pool");
+ synchronized (ctx) {
+
+ // Release the lock
+ ctx.unlock();
+
+ //Let the waiters know
+ ctx.notifyAll();
+ }
+ }
+ }
+ }
+
+ public Object invoke(MethodInvocation mi)
+ throws Exception
+ {
+ // The id store is a CacheKey in the case of Entity
+ CacheKey key = (CacheKey) mi.getId();
+
+ // Get context
+ EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstanceCache().get(key);
+
+ // Set it on the method invocation
+ mi.setEnterpriseContext(ctx);
+
+ // We synchronize the locking logic (so that the invoke is
unsynchronized and can be reentrant)
+ synchronized (ctx)
+ {
+ // 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()))
+ {
+ // Let's put the thread to sleep a lock release will
wake the thread
+ try{ctx.wait();}
+ catch (InterruptedException ie) {}
+
+ // Try your luck again
+ return invoke(mi);
+ }
+
+ if (!ctx.isLocked()){
+
+ //take it!
+ ctx.lock();
+ }
+
+ else
+ {
+ if (!isCallAllowed(mi)) {
+
+ // Let's put the thread to sleep a lock
release will wake the thread
+ try{ctx.wait();}
+ catch (InterruptedException ie) {}
+
+ // Try your luck again
+ return invoke(mi);
+ }
+
+ // The call is allowed, do increment the lock though
(ctx already locked)
+ ctx.lock();
+ }
+
+ }
+
+ try {
+
+ // Go on, you won
+ return getNext().invoke(mi);
+
+ }
+ catch (RemoteException e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
+
+ throw e;
+ } catch (RuntimeException e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
+
+ throw e;
+ } catch (Error e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
+
+ throw e;
+ } finally
+ {
+ // Logger.log("Release instance for "+id);
+ if (ctx != null)
+ {
+
+ synchronized (ctx) {
+
+ // unlock the context
+ ctx.unlock();
+
+ if (ctx.getId() == null)
+ {
+ // Remove from cache
+
((EntityContainer)getContainer()).getInstanceCache().remove(key.id);
+
+ // It has been removed -> send to free
pool
+ container.getInstancePool().free(ctx);
+ }
+
+ // notify the thread waiting on ctx
+ ctx.notifyAll();
+ }
+ }
+ }
+ }
+
+ // Private --------------------------------------------------------
+
+ private static Method getEJBHome;
+ private static Method getHandle;
+ private static Method getPrimaryKey;
+ private static Method isIdentical;
+ private static Method remove;
+ static
+ {
+ try
+ {
+ Class[] noArg = new Class[0];
+ getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
+ getHandle = EJBObject.class.getMethod("getHandle", noArg);
+ getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey",
noArg);
+ isIdentical = EJBObject.class.getMethod("isIdentical", new
Class[] {EJBObject.class});
+ remove = EJBObject.class.getMethod("remove", noArg);
+ }
+ catch (Exception x) {x.printStackTrace();}
+ }
+
+ private boolean isCallAllowed(MethodInvocation mi)
+ {
+ boolean reentrant =
((EntityMetaData)container.getBeanMetaData()).isReentrant();
+
+ if (reentrant)
+ {
+ return true;
+ }
+ else
+ {
+ Method m = mi.getMethod();
+ if (m.equals(getEJBHome) ||
+ m.equals(getHandle) ||
+ m.equals(getPrimaryKey) ||
+ m.equals(isIdentical) ||
+ m.equals(remove))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
1.6 +78 -78 jboss/src/main/org/jboss/ejb/plugins/EntityInstancePool.java
Index: EntityInstancePool.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntityInstancePool.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- EntityInstancePool.java 2000/09/26 18:44:05 1.5
+++ EntityInstancePool.java 2000/09/26 20:18:50 1.6
@@ -1,78 +1,78 @@
-/*
- * jBoss, the OpenSource EJB server
- *
- * Distributable under GPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.ejb.plugins;
-
-import java.rmi.RemoteException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.EntityEnterpriseContext;
-
-/**
- * <description>
- *
- * @see <related>
- * @author Rickard �berg ([EMAIL PROTECTED])
- * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
- * @version $Revision: 1.5 $
- */
-public class EntityInstancePool
- extends AbstractInstancePool
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- /**
- * Return an instance to the free pool. Reset state
- *
- * Called in 3 cases:
- * a) Done with finder method
- * b) Removed
- * c) Passivated
- *
- * @param ctx
- */
- public synchronized void free(EnterpriseContext ctx)
- {
- // If transaction still present don't do anything (let the instance be GC)
- if (ctx.getTransaction() != null) return ;
-
- // Reset instance
- ((EntityEnterpriseContext)ctx).setValid(false);
- ((EntityEnterpriseContext)ctx).setInvoked(false);
-
- super.free(ctx);
- }
-
- // Z implementation ----------------------------------------------
- public void start()
- throws Exception
- {
- }
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
- protected EnterpriseContext create(Object instance, Container con)
- throws RemoteException
- {
- // MF FIXME why pass con and then use getContainer()
- return new EntityEnterpriseContext(instance, getContainer());
- }
-
- // 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.rmi.RemoteException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.EntityEnterpriseContext;
+
+/**
+ * <description>
+ *
+ * @see <related>
+ * @author Rickard �berg ([EMAIL PROTECTED])
+ * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+ * @version $Revision: 1.6 $
+ */
+public class EntityInstancePool
+ extends AbstractInstancePool
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ /**
+ * Return an instance to the free pool. Reset state
+ *
+ * Called in 3 cases:
+ * a) Done with finder method
+ * b) Removed
+ * c) Passivated
+ *
+ * @param ctx
+ */
+ public synchronized void free(EnterpriseContext ctx)
+ {
+ // If transaction still present don't do anything (let the instance be GC)
+ if (ctx.getTransaction() != null) return ;
+
+ // Reset instance
+ ((EntityEnterpriseContext)ctx).setValid(false);
+ ((EntityEnterpriseContext)ctx).setInvoked(false);
+
+ super.free(ctx);
+ }
+
+ // Z implementation ----------------------------------------------
+ public void start()
+ throws Exception
+ {
+ }
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+ protected EnterpriseContext create(Object instance, Container con)
+ throws RemoteException
+ {
+ // MF FIXME why pass con and then use getContainer()
+ return new EntityEnterpriseContext(instance, getContainer());
+ }
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+}
+
1.16 +423 -423
jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java
Index: EntitySynchronizationInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- EntitySynchronizationInterceptor.java 2000/09/26 18:47:13 1.15
+++ EntitySynchronizationInterceptor.java 2000/09/26 20:18:50 1.16
@@ -1,423 +1,423 @@
-/*
-* 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.Map;
-import java.util.HashMap;
-import java.util.ArrayList;
-
-import javax.ejb.EJBObject;
-import javax.ejb.CreateException;
-import javax.ejb.EJBException;
-import javax.ejb.NoSuchEntityException;
-import javax.ejb.RemoveException;
-import javax.ejb.EntityBean;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.InstanceCache;
-import org.jboss.ejb.InstancePool;
-import org.jboss.ejb.MethodInvocation;
-
-import org.jboss.logging.Logger;
-
-/**
-* This container filter takes care of EntityBean persistance.
-* Specifically, it calls ejbStore at appropriate times
-*
-* Possible options:
-* After each call
-* On tx commit
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.15 $
-*/
-public class EntitySynchronizationInterceptor
-extends AbstractInterceptor
-{
- // Constants -----------------------------------------------------
-
- /**
- * Cache a "ready" instance between transactions.
- * Data will <em>not</em> be reloaded from persistent storage when
- * a new transaction is started.
- * This option should only be used if the instance has exclusive
- * access to its persistent storage.
- */
- public static final int A = 0; // Keep instance cached
-
- /**
- * Cache a "ready" instance between transactions and reload data
- * from persistent storage on transaction start.
- */
- public static final int B = 1; // Invalidate state
-
- /**
- * Passivate instance after each transaction.
- */
- public static final int C = 2; // Passivate
-
- // Attributes ----------------------------------------------------
-
- /**
- * The current commit option.
- */
- protected int commitOption = A;
-
- /**
- * The container of this interceptor.
- */
- protected EntityContainer container;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = (EntityContainer)container;
- }
-
- public Container getContainer()
- {
- return container;
- }
-
- /**
- * Setter for property commitOption.
- */
- public void setCommitOption(int commitOption)
- {
- this.commitOption = commitOption;
- }
-
- /**
- * Getter for property commitOption.
- */
- public int getCommitOption()
- {
- return commitOption;
- }
-
- /**
- * Register a transaction synchronization callback with a context.
- */
- private void register(EntityEnterpriseContext 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) {
-
- ctx.setValid(false);
-
- return;
- }
-
- // We want to be notified when the transaction commits
- tx.registerSynchronization(synch);
-
- } catch (RollbackException e) {
-
- // The state in the instance is to be discarded, we force a
reload of state
- ctx.setValid(false);
-
- } catch (Exception e) {
-
- throw new EJBException(e);
-
- }
- }
-
- private void deregister(EntityEnterpriseContext ctx)
- {
- // MF FIXME: I suspect this is redundant now
- // (won't the pool clean it up?)
-
- // Deassociate ctx with tx
- // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
- // OSH: Pool seems to do this: ctx.setInvoked(false);
- }
-
- // Interceptor implementation --------------------------------------
-
- public Object invokeHome(MethodInvocation mi)
- throws Exception
- {
- try {
- return getNext().invokeHome(mi);
- } finally {
- // Anonymous was sent in, so if it has an id it was created
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
- if (ctx.getId() != null) {
- Transaction tx = mi.getTransaction();
-
- if (tx != null && tx.getStatus() ==
Status.STATUS_ACTIVE)
- register(ctx, tx); // Set tx
-
- // Currently synched with underlying storage
- ctx.setValid(true);
- }
- }
- }
-
- public Object invoke(MethodInvocation mi)
- throws Exception
- {
- // We are going to work with the context a lot
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
-
- // The Tx coming as part of the Method Invocation
- Transaction tx = mi.getTransaction();
-
- //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
- //Logger.debug("newTx: "+ tx);
-
- // Is my state valid?
- if (!ctx.isValid()) {
-
- // If not tell the persistence manager to load the state
-
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
-
- // Now the state is valid
- ctx.setValid(true);
- }
-
- // So we can go on with the invocation
- Logger.log("Tx is "+ ((tx == null)? "null" : tx.toString()));
-
- // Invocation with a running Transaction
-
- if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
-
- try {
-
- //Invoke down the chain
- return getNext().invoke(mi);
-
- }
-
- finally {
-
- // Do we have a valid bean (not removed)
- if (ctx.getId() != null) {
-
- // If the context was not invoked previously...
- if (!ctx.isInvoked()) {
-
- // It is now and this will cause
ejbStore to be called...
- ctx.setInvoked(true);
-
- // ... on a transaction callback that
we register here.
- register(ctx, tx);
- }
- }
-
- // Entity was removed
- else {
-
- if (ctx.getTransaction() != null) {
-
- //DEBUG Logger.debug("CTX out:
isValid():"+ctx.isValid()+" isInvoked():"+ctx.isInvoked());
- //DEBUG Logger.debug("PresentTx:"+tx);
-
- // If a ctx still has a transaction we
would need to deresgister the sync
- // The simplest is to tell the pool to
kill the instance if tx is present
-
- }
- }
- }
- }
-
- //
- else { // No tx
- try {
- Object result = getNext().invoke(mi);
-
- // Store after each invocation -- not on exception
though, or removal
- // And skip reads too ("get" methods)
- // OSH FIXME: Isn't this startsWith("get")
optimization a violation of
- // the EJB specification? Think of
SequenceBean.getNext().
- if (ctx.getId() != null &&
!mi.getMethod().getName().startsWith("get"))
-
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
-
- return result;
- } catch (Exception e) {
- // Exception - force reload on next call
- ctx.setValid(false);
- throw e;
- }
- }
- }
-
-
- // Protected ----------------------------------------------------
-
- // Inner classes -------------------------------------------------
-
- private class InstanceSynchronization
- implements Synchronization
- {
- /**
- * The transaction we follow.
- */
- private Transaction tx;
-
- /**
- * The context we manage.
- */
- private EntityEnterpriseContext ctx;
-
- /**
- * Create a new instance synchronization instance.
- */
- InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
- {
- this.tx = tx;
- this.ctx = ctx;
- }
-
- // Synchronization implementation -----------------------------
-
- public void beforeCompletion()
- {
- Logger.log("beforeCompletion called for ctx "+ctx.hashCode());
-
- if (ctx.getId() != null) {
- try {
- try {
-
- // MF FIXME: should we throw an
exception if lock is present (app error)
- // it would mean that someone is
commiting when all the work is not done
-
- // Store instance if business method
was invoked
- if (ctx.isInvoked()) {
-
- //DEBUG
Logger.log("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
-
-
Logger.log("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
-
-
container.getPersistenceManager().storeEntity(ctx);
- }
- } catch (NoSuchEntityException e) {
- // Object has been removed -- ignore
- }
- } catch (RemoteException e) {
- Logger.exception(e);
-
- // Store failed -> rollback!
- try {
- tx.setRollbackOnly();
- } catch (SystemException ex) {
- // DEBUG ex.printStackTrace();
- }
- }
- }
- }
-
- public void afterCompletion(int status)
- {
- if (ctx.getId() != null) {
- Logger.log("afterCompletion called for ctx
"+ctx.hashCode());
- // If rolled back -> invalidate instance
- if (status == Status.STATUS_ROLLEDBACK) {
- try {
-
- // finish the transaction association
- ctx.setTransaction(null);
-
- ctx.setValid(false);
-
- // remove from the cache
-
container.getInstanceCache().remove(ctx.getId());
-
- // return to pool
- container.getInstancePool().free(ctx);
-
- // wake threads waiting
- synchronized(ctx) { ctx.notifyAll();}
-
- } catch (Exception e) {
- // Ignore
- }
-
-
-
- } else {
- // The transaction is done
- ctx.setTransaction(null);
-
- // We are afterCompletion so the invoked can
be set to false (db sync is done)
- ctx.setInvoked(false);
-
- switch (commitOption) {
- // Keep instance cached after tx commit
- case A:
- try {
- // The state is still
valid (only point of access is us)
- ctx.setValid(true);
-
- } catch (Exception e) {
- Logger.debug(e);
- }
- break;
-
- // Keep instance active, but
invalidate state
- case B:
- try {
- // Invalidate state
(there might be other points of entry)
- ctx.setValid(false);
-
- } catch (Exception e) {
- Logger.debug(e);
- }
- break;
-
- // Invalidate everything AND Passivate
instance
- case C:
- try {
-
- // Passivate instance
-
container.getPersistenceManager().passivateEntity(ctx);
-
- // Remove from the
cache, it is not active anymore
-
container.getInstanceCache().remove(ctx.getId());
-
- // Back to the pool
-
container.getInstancePool().free(ctx);
- } catch (Exception e) {
- Logger.debug(e);
- }
- break;
- }
- }
- }
- // Notify all who are waiting for this tx to end, they are
waiting since the locking logic
- synchronized (ctx) {ctx.notifyAll();}
- }
- }
-}
-
+/*
+* 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.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import javax.ejb.EJBObject;
+import javax.ejb.CreateException;
+import javax.ejb.EJBException;
+import javax.ejb.NoSuchEntityException;
+import javax.ejb.RemoveException;
+import javax.ejb.EntityBean;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.InstanceCache;
+import org.jboss.ejb.InstancePool;
+import org.jboss.ejb.MethodInvocation;
+
+import org.jboss.logging.Logger;
+
+/**
+* This container filter takes care of EntityBean persistance.
+* Specifically, it calls ejbStore at appropriate times
+*
+* Possible options:
+* After each call
+* On tx commit
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.16 $
+*/
+public class EntitySynchronizationInterceptor
+extends AbstractInterceptor
+{
+ // Constants -----------------------------------------------------
+
+ /**
+ * Cache a "ready" instance between transactions.
+ * Data will <em>not</em> be reloaded from persistent storage when
+ * a new transaction is started.
+ * This option should only be used if the instance has exclusive
+ * access to its persistent storage.
+ */
+ public static final int A = 0; // Keep instance cached
+
+ /**
+ * Cache a "ready" instance between transactions and reload data
+ * from persistent storage on transaction start.
+ */
+ public static final int B = 1; // Invalidate state
+
+ /**
+ * Passivate instance after each transaction.
+ */
+ public static final int C = 2; // Passivate
+
+ // Attributes ----------------------------------------------------
+
+ /**
+ * The current commit option.
+ */
+ protected int commitOption = A;
+
+ /**
+ * The container of this interceptor.
+ */
+ protected EntityContainer container;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container container)
+ {
+ this.container = (EntityContainer)container;
+ }
+
+ public Container getContainer()
+ {
+ return container;
+ }
+
+ /**
+ * Setter for property commitOption.
+ */
+ public void setCommitOption(int commitOption)
+ {
+ this.commitOption = commitOption;
+ }
+
+ /**
+ * Getter for property commitOption.
+ */
+ public int getCommitOption()
+ {
+ return commitOption;
+ }
+
+ /**
+ * Register a transaction synchronization callback with a context.
+ */
+ private void register(EntityEnterpriseContext 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) {
+
+ ctx.setValid(false);
+
+ return;
+ }
+
+ // We want to be notified when the transaction commits
+ tx.registerSynchronization(synch);
+
+ } catch (RollbackException e) {
+
+ // The state in the instance is to be discarded, we force a
reload of state
+ ctx.setValid(false);
+
+ } catch (Exception e) {
+
+ throw new EJBException(e);
+
+ }
+ }
+
+ private void deregister(EntityEnterpriseContext ctx)
+ {
+ // MF FIXME: I suspect this is redundant now
+ // (won't the pool clean it up?)
+
+ // Deassociate ctx with tx
+ // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
+ // OSH: Pool seems to do this: ctx.setInvoked(false);
+ }
+
+ // Interceptor implementation --------------------------------------
+
+ public Object invokeHome(MethodInvocation mi)
+ throws Exception
+ {
+ try {
+ return getNext().invokeHome(mi);
+ } finally {
+ // Anonymous was sent in, so if it has an id it was created
+ EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
+ if (ctx.getId() != null) {
+ Transaction tx = mi.getTransaction();
+
+ if (tx != null && tx.getStatus() ==
Status.STATUS_ACTIVE)
+ register(ctx, tx); // Set tx
+
+ // Currently synched with underlying storage
+ ctx.setValid(true);
+ }
+ }
+ }
+
+ public Object invoke(MethodInvocation mi)
+ throws Exception
+ {
+ // We are going to work with the context a lot
+ EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
+
+ // The Tx coming as part of the Method Invocation
+ Transaction tx = mi.getTransaction();
+
+ //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("newTx: "+ tx);
+
+ // Is my state valid?
+ if (!ctx.isValid()) {
+
+ // If not tell the persistence manager to load the state
+
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
+
+ // Now the state is valid
+ ctx.setValid(true);
+ }
+
+ // So we can go on with the invocation
+ Logger.log("Tx is "+ ((tx == null)? "null" : tx.toString()));
+
+ // Invocation with a running Transaction
+
+ if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
+
+ try {
+
+ //Invoke down the chain
+ return getNext().invoke(mi);
+
+ }
+
+ finally {
+
+ // Do we have a valid bean (not removed)
+ if (ctx.getId() != null) {
+
+ // If the context was not invoked previously...
+ if (!ctx.isInvoked()) {
+
+ // It is now and this will cause
ejbStore to be called...
+ ctx.setInvoked(true);
+
+ // ... on a transaction callback that
we register here.
+ register(ctx, tx);
+ }
+ }
+
+ // Entity was removed
+ else {
+
+ if (ctx.getTransaction() != null) {
+
+ //DEBUG Logger.debug("CTX out:
isValid():"+ctx.isValid()+" isInvoked():"+ctx.isInvoked());
+ //DEBUG Logger.debug("PresentTx:"+tx);
+
+ // If a ctx still has a transaction we
would need to deresgister the sync
+ // The simplest is to tell the pool to
kill the instance if tx is present
+
+ }
+ }
+ }
+ }
+
+ //
+ else { // No tx
+ try {
+ Object result = getNext().invoke(mi);
+
+ // Store after each invocation -- not on exception
though, or removal
+ // And skip reads too ("get" methods)
+ // OSH FIXME: Isn't this startsWith("get")
optimization a violation of
+ // the EJB specification? Think of
SequenceBean.getNext().
+ if (ctx.getId() != null &&
!mi.getMethod().getName().startsWith("get"))
+
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
+
+ return result;
+ } catch (Exception e) {
+ // Exception - force reload on next call
+ ctx.setValid(false);
+ throw e;
+ }
+ }
+ }
+
+
+ // Protected ----------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+ private class InstanceSynchronization
+ implements Synchronization
+ {
+ /**
+ * The transaction we follow.
+ */
+ private Transaction tx;
+
+ /**
+ * The context we manage.
+ */
+ private EntityEnterpriseContext ctx;
+
+ /**
+ * Create a new instance synchronization instance.
+ */
+ InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
+ {
+ this.tx = tx;
+ this.ctx = ctx;
+ }
+
+ // Synchronization implementation -----------------------------
+
+ public void beforeCompletion()
+ {
+ Logger.log("beforeCompletion called for ctx "+ctx.hashCode());
+
+ if (ctx.getId() != null) {
+ try {
+ try {
+
+ // MF FIXME: should we throw an
exception if lock is present (app error)
+ // it would mean that someone is
commiting when all the work is not done
+
+ // Store instance if business method
was invoked
+ if (ctx.isInvoked()) {
+
+ //DEBUG
Logger.log("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
+
+
Logger.log("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
+
+
container.getPersistenceManager().storeEntity(ctx);
+ }
+ } catch (NoSuchEntityException e) {
+ // Object has been removed -- ignore
+ }
+ } catch (RemoteException e) {
+ Logger.exception(e);
+
+ // Store failed -> rollback!
+ try {
+ tx.setRollbackOnly();
+ } catch (SystemException ex) {
+ // DEBUG ex.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void afterCompletion(int status)
+ {
+ if (ctx.getId() != null) {
+ Logger.log("afterCompletion called for ctx
"+ctx.hashCode());
+ // If rolled back -> invalidate instance
+ if (status == Status.STATUS_ROLLEDBACK) {
+ try {
+
+ // finish the transaction association
+ ctx.setTransaction(null);
+
+ ctx.setValid(false);
+
+ // remove from the cache
+
container.getInstanceCache().remove(ctx.getId());
+
+ // return to pool
+ container.getInstancePool().free(ctx);
+
+ // wake threads waiting
+ synchronized(ctx) { ctx.notifyAll();}
+
+ } catch (Exception e) {
+ // Ignore
+ }
+
+
+
+ } else {
+ // The transaction is done
+ ctx.setTransaction(null);
+
+ // We are afterCompletion so the invoked can
be set to false (db sync is done)
+ ctx.setInvoked(false);
+
+ switch (commitOption) {
+ // Keep instance cached after tx commit
+ case A:
+ try {
+ // The state is still
valid (only point of access is us)
+ ctx.setValid(true);
+
+ } catch (Exception e) {
+ Logger.debug(e);
+ }
+ break;
+
+ // Keep instance active, but
invalidate state
+ case B:
+ try {
+ // Invalidate state
(there might be other points of entry)
+ ctx.setValid(false);
+
+ } catch (Exception e) {
+ Logger.debug(e);
+ }
+ break;
+
+ // Invalidate everything AND Passivate
instance
+ case C:
+ try {
+
+ // Passivate instance
+
container.getPersistenceManager().passivateEntity(ctx);
+
+ // Remove from the
cache, it is not active anymore
+
container.getInstanceCache().remove(ctx.getId());
+
+ // Back to the pool
+
container.getInstancePool().free(ctx);
+ } catch (Exception e) {
+ Logger.debug(e);
+ }
+ break;
+ }
+ }
+ }
+ // Notify all who are waiting for this tx to end, they are
waiting since the locking logic
+ synchronized (ctx) {ctx.notifyAll();}
+ }
+ }
+}
+
1.11 +166 -166
jboss/src/main/org/jboss/ejb/plugins/NoPassivationEntityInstanceCache.java
Index: NoPassivationEntityInstanceCache.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/NoPassivationEntityInstanceCache.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- NoPassivationEntityInstanceCache.java 2000/09/26 18:53:55 1.10
+++ NoPassivationEntityInstanceCache.java 2000/09/26 20:18:51 1.11
@@ -1,166 +1,166 @@
-/*
-* jBoss, the OpenSource EJB server
-*
-* Distributable under GPL license.
-* See terms of license at gnu.org.
-*/
-package org.jboss.ejb.plugins;
-
-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Stack;
-import java.util.LinkedList;
-import java.util.Collections;
-import java.util.Iterator;
-
-import javax.transaction.SystemException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.EntityInstanceCache;
-import org.jboss.ejb.InstanceCache;
-import org.jboss.ejb.InstancePool;
-import org.jboss.ejb.InstancePoolContainer;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.ejb.CacheKey;
-
-import org.jboss.metadata.EntityMetaData;
-
-/**
-* <description>
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @author <a href="mailto:[EMAIL PROTECTED]">Andy Schaefer</a>
-* @version $Revision: 1.10 $
-*/
-public class NoPassivationEntityInstanceCache
-implements EntityInstanceCache
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- Container con;
-
- Map cache = Collections.synchronizedMap(new HashMap());
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
-
- /**
- * Set the callback to the container. This is for initialization.
- * The IM may extract the configuration from the container.
- *
- * @param c
- */
- public void setContainer(Container c)
- {
- this.con = c;
- }
-
- public void init()
- throws Exception
- {
- }
-
- public void start()
- throws Exception
- {
- }
-
- public void stop()
- {
- }
-
- public void destroy()
- {
- }
-
- public Object createCacheKey( Object id ) {
-
- return new CacheKey( id );
- }
-
- /**
- * get(Object CacheKey)
- *
- * We base our lookups on the CacheKey.
- */
-
- public synchronized EnterpriseContext get(Object id)
- throws RemoteException
- {
-
- // Use the CacheKey for the rest of the method
- CacheKey cacheKey = (CacheKey) id;
-
- EntityEnterpriseContext ctx;
-
- // Lookup the instance
- ctx = (EntityEnterpriseContext)cache.get(cacheKey);
-
- if (ctx == null) // Not in fast cache under that cacheKey
- {
-
- // Get new instance from pool
- ctx =
(EntityEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
-
- // The context only knows about the Database id
- ctx.setId(cacheKey.id);
-
- // Activate it
- ((EntityContainer)con).getPersistenceManager().activateEntity(ctx);
-
- // insert
- cache.put(cacheKey, ctx);
- }
-
-
- // At this point we own the instance with the given identity
-
- // Tell the context the key
- ctx.setCacheKey(cacheKey);
-
- // DEBUG Logger.log("Got entity:"+ctx.getId());
-
- return ctx;
- }
-
- public synchronized void insert (EnterpriseContext ctx) {
-
- // Cache can know about the instance now
- cache.put(((EntityEnterpriseContext) ctx).getCacheKey(), ctx);
- }
-
- /*
- * Remove works with the cachekey that the cache constructs. Leakage will
happen if the cache key
- * doesn't consistently see
- * m1 = new CacheKey(id); and
- * m2 = new CacheKey(id);
- * as hashCode equals and equals. The implementation of org.jboss.CacheKey
behaves correctly
- *
- */
- public synchronized void remove(Object id)
- {
- // remove usually comes with the id of the db instance
- cache.remove(createCacheKey(id));
- }
-
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // 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.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.LinkedList;
+import java.util.Collections;
+import java.util.Iterator;
+
+import javax.transaction.SystemException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.EntityInstanceCache;
+import org.jboss.ejb.InstanceCache;
+import org.jboss.ejb.InstancePool;
+import org.jboss.ejb.InstancePoolContainer;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.ejb.CacheKey;
+
+import org.jboss.metadata.EntityMetaData;
+
+/**
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @author <a href="mailto:[EMAIL PROTECTED]">Andy Schaefer</a>
+* @version $Revision: 1.11 $
+*/
+public class NoPassivationEntityInstanceCache
+implements EntityInstanceCache
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ Container con;
+
+ Map cache = Collections.synchronizedMap(new HashMap());
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+
+ /**
+ * Set the callback to the container. This is for initialization.
+ * The IM may extract the configuration from the container.
+ *
+ * @param c
+ */
+ public void setContainer(Container c)
+ {
+ this.con = c;
+ }
+
+ public void init()
+ throws Exception
+ {
+ }
+
+ public void start()
+ throws Exception
+ {
+ }
+
+ public void stop()
+ {
+ }
+
+ public void destroy()
+ {
+ }
+
+ public Object createCacheKey( Object id ) {
+
+ return new CacheKey( id );
+ }
+
+ /**
+ * get(Object CacheKey)
+ *
+ * We base our lookups on the CacheKey.
+ */
+
+ public synchronized EnterpriseContext get(Object id)
+ throws RemoteException
+ {
+
+ // Use the CacheKey for the rest of the method
+ CacheKey cacheKey = (CacheKey) id;
+
+ EntityEnterpriseContext ctx;
+
+ // Lookup the instance
+ ctx = (EntityEnterpriseContext)cache.get(cacheKey);
+
+ if (ctx == null) // Not in fast cache under that cacheKey
+ {
+
+ // Get new instance from pool
+ ctx =
(EntityEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
+
+ // The context only knows about the Database id
+ ctx.setId(cacheKey.id);
+
+ // Activate it
+ ((EntityContainer)con).getPersistenceManager().activateEntity(ctx);
+
+ // insert
+ cache.put(cacheKey, ctx);
+ }
+
+
+ // At this point we own the instance with the given identity
+
+ // Tell the context the key
+ ctx.setCacheKey(cacheKey);
+
+ // DEBUG Logger.log("Got entity:"+ctx.getId());
+
+ return ctx;
+ }
+
+ public synchronized void insert (EnterpriseContext ctx) {
+
+ // Cache can know about the instance now
+ cache.put(((EntityEnterpriseContext) ctx).getCacheKey(), ctx);
+ }
+
+ /*
+ * Remove works with the cachekey that the cache constructs. Leakage will
happen if the cache key
+ * doesn't consistently see
+ * m1 = new CacheKey(id); and
+ * m2 = new CacheKey(id);
+ * as hashCode equals and equals. The implementation of org.jboss.CacheKey
behaves correctly
+ *
+ */
+ public synchronized void remove(Object id)
+ {
+ // remove usually comes with the id of the db instance
+ cache.remove(createCacheKey(id));
+ }
+
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+}
1.10 +138 -138
jboss/src/main/org/jboss/ejb/plugins/NoPassivationStatefulSessionInstanceCache.java
Index: NoPassivationStatefulSessionInstanceCache.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/NoPassivationStatefulSessionInstanceCache.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- NoPassivationStatefulSessionInstanceCache.java 2000/09/26 18:55:50 1.9
+++ NoPassivationStatefulSessionInstanceCache.java 2000/09/26 20:18:51 1.10
@@ -1,138 +1,138 @@
-/*
-* jBoss, the OpenSource EJB server
-*
-* Distributable under GPL license.
-* See terms of license at gnu.org.
-*/
-package org.jboss.ejb.plugins;
-
-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Stack;
-import java.util.Collections;
-
-import javax.transaction.SystemException;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.StatefulSessionContainer;
-import org.jboss.ejb.InstanceCache;
-import org.jboss.ejb.InstancePool;
-import org.jboss.ejb.InstancePoolContainer;
-import org.jboss.ejb.StatefulSessionPersistenceManager;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.StatefulSessionEnterpriseContext;
-import org.jboss.logging.Logger;
-
-
-/**
-* <description>
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.9 $
-*/
-public class NoPassivationStatefulSessionInstanceCache
-implements InstanceCache
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- Container con;
-
- Map active = new HashMap();
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
-
- /**
- * Set the callback to the container. This is for initialization.
- * The IM may extract the configuration from the container.
- *
- * @param c
- */
- public void setContainer(Container c)
- {
- this.con = c;
- }
-
- public void init()
- throws Exception
- {
- }
-
- public void start()
- throws Exception
- {
- }
-
- public void stop()
- {
- }
-
- public void destroy()
- {
- }
-
- public synchronized EnterpriseContext get(Object id)
- throws RemoteException
- {
-
- //DEBUG Logger.log("Stateful cache looking for ID "+id);
- Logger.log("Stateful cache looking for ID "+id);
-
- // Do we have the context in cache?
- StatefulSessionEnterpriseContext ctx =
- (StatefulSessionEnterpriseContext)active.get(id);
-
- // We don't have it in cache
- if (ctx == null) {
-
- // Get new instance from pool (bogus in our case)
- ctx =
(StatefulSessionEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
-
- // Activate
- ctx.setId(id);
-
- try {
-
-
((StatefulSessionContainer)con).getPersistenceManager().activateSession(ctx);
- }
- catch (Exception e) {
-
- throw new RemoteException("Object was not found");
- }
-
- insert(ctx);
- }
- // The context has the instance as well and the right id
- return ctx;
- }
-
- public synchronized void insert(EnterpriseContext ctx)
- {
- active.put(ctx.getId(), ctx) ;
- }
-
-
-
- public synchronized void remove(Object id)
- {
- Object ctx = active.remove(id);
- }
-
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // 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.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.Collections;
+
+import javax.transaction.SystemException;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.StatefulSessionContainer;
+import org.jboss.ejb.InstanceCache;
+import org.jboss.ejb.InstancePool;
+import org.jboss.ejb.InstancePoolContainer;
+import org.jboss.ejb.StatefulSessionPersistenceManager;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.StatefulSessionEnterpriseContext;
+import org.jboss.logging.Logger;
+
+
+/**
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.10 $
+*/
+public class NoPassivationStatefulSessionInstanceCache
+implements InstanceCache
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ Container con;
+
+ Map active = new HashMap();
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+
+ /**
+ * Set the callback to the container. This is for initialization.
+ * The IM may extract the configuration from the container.
+ *
+ * @param c
+ */
+ public void setContainer(Container c)
+ {
+ this.con = c;
+ }
+
+ public void init()
+ throws Exception
+ {
+ }
+
+ public void start()
+ throws Exception
+ {
+ }
+
+ public void stop()
+ {
+ }
+
+ public void destroy()
+ {
+ }
+
+ public synchronized EnterpriseContext get(Object id)
+ throws RemoteException
+ {
+
+ //DEBUG Logger.log("Stateful cache looking for ID "+id);
+ Logger.log("Stateful cache looking for ID "+id);
+
+ // Do we have the context in cache?
+ StatefulSessionEnterpriseContext ctx =
+ (StatefulSessionEnterpriseContext)active.get(id);
+
+ // We don't have it in cache
+ if (ctx == null) {
+
+ // Get new instance from pool (bogus in our case)
+ ctx =
(StatefulSessionEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
+
+ // Activate
+ ctx.setId(id);
+
+ try {
+
+
((StatefulSessionContainer)con).getPersistenceManager().activateSession(ctx);
+ }
+ catch (Exception e) {
+
+ throw new RemoteException("Object was not found");
+ }
+
+ insert(ctx);
+ }
+ // The context has the instance as well and the right id
+ return ctx;
+ }
+
+ public synchronized void insert(EnterpriseContext ctx)
+ {
+ active.put(ctx.getId(), ctx) ;
+ }
+
+
+
+ public synchronized void remove(Object id)
+ {
+ Object ctx = active.remove(id);
+ }
+
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+}
1.9 +153 -153
jboss/src/main/org/jboss/ejb/plugins/RandomEntityInstanceCache.java
Index: RandomEntityInstanceCache.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/RandomEntityInstanceCache.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- RandomEntityInstanceCache.java 2000/09/26 18:57:16 1.8
+++ RandomEntityInstanceCache.java 2000/09/26 20:18:51 1.9
@@ -1,153 +1,153 @@
-/*
-* jBoss, the OpenSource EJB server
-*
-* Distributable under GPL license.
-* See terms of license at gnu.org.
-*/
-package org.jboss.ejb.plugins;
-
-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.HashMap;
-import java.util.LinkedList;
-
-import org.jboss.ejb.Container;
-import org.jboss.ejb.EntityContainer;
-import org.jboss.ejb.InstanceCache;
-import org.jboss.ejb.InstancePool;
-import org.jboss.ejb.EntityPersistenceManager;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.EntityEnterpriseContext;
-
-import org.jboss.logging.Logger;
-
-/**
-* <description>
-*
-* @see <related>
-* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.8 $
-*/
-public class RandomEntityInstanceCache
-extends NoPassivationEntityInstanceCache
-{
-
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- boolean running = false; // Passivator thread running?
-
- int minActive = 100; // Always try to passivate if more than this nr are active
-
- long timeout = 60*1000L; // Passivation sweep sleep time
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void start()
- throws Exception
- {
- running = true;
- new Thread(new Passivator()).start();
- }
-
- public void stop()
- {
- running = false;
- }
-
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
- class Passivator
- implements Runnable
- {
- //RandomEntityInstanceCache cache;
-
- public void run()
- {
- Logger.debug("Passivator started");
- // Passivation loop
- while(running)
- {
- // Logger.log("Clearing cache");
- // Passivate old. Lock cache first
- //synchronized(RandomEntityInstanceCache.this)
- synchronized(cache)
- {
- // Do not use cache (many to one entries)
- int currentActive = cache.size();
- if (currentActive > minActive)
- {
- InstancePool pool = ((EntityContainer)con).getInstancePool();
-
- Logger.debug("Too many active instances:"+currentActive);
-
- // Passivate some instance; they need to be unlocked though
-
- //KeySet has cacheKeys (currentActive>0)
- Iterator keys = cache.keySet().iterator();
-
- while(keys.hasNext())
- {
-
- Object key = keys.next();
-
- //Get the context
- EntityEnterpriseContext ctx =
- (EntityEnterpriseContext) cache.get(key);
-
-
- // Make sure we can work on it
- Logger.debug("Checking:"+ctx.getId());
-
- //TODO do the Locking logic
- try
- {
- Logger.debug("Passivating:"+ctx.getId());
-
- // Passivate the entry
-
((EntityContainer)con).getPersistenceManager().passivateEntity(ctx);
-
- // Remove the entry
- cache.remove(key);
-
- //keep the count
- currentActive--;
- }
-
- catch (Exception e) { Logger.log("Could not passivate
instance");}
-
- // Are we done?
- if (currentActive == minActive) break;
- }
-
- }
- }
- // DEBUG Logger.log("Passivation done");
- Logger.log("Passivation done");
-
- // Sleep
- try
- {
- Thread.sleep(timeout);
- } catch (InterruptedException e)
- {
- // Ignore
- }
-
- }
- }
- }
-}
\ No newline at end of file
+/*
+* jBoss, the OpenSource EJB server
+*
+* Distributable under GPL license.
+* See terms of license at gnu.org.
+*/
+package org.jboss.ejb.plugins;
+
+import java.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EntityContainer;
+import org.jboss.ejb.InstanceCache;
+import org.jboss.ejb.InstancePool;
+import org.jboss.ejb.EntityPersistenceManager;
+import org.jboss.ejb.EnterpriseContext;
+import org.jboss.ejb.EntityEnterpriseContext;
+
+import org.jboss.logging.Logger;
+
+/**
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.9 $
+*/
+public class RandomEntityInstanceCache
+extends NoPassivationEntityInstanceCache
+{
+
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ boolean running = false; // Passivator thread running?
+
+ int minActive = 100; // Always try to passivate if more than this nr are active
+
+ long timeout = 60*1000L; // Passivation sweep sleep time
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void start()
+ throws Exception
+ {
+ running = true;
+ new Thread(new Passivator()).start();
+ }
+
+ public void stop()
+ {
+ running = false;
+ }
+
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+ class Passivator
+ implements Runnable
+ {
+ //RandomEntityInstanceCache cache;
+
+ public void run()
+ {
+ Logger.debug("Passivator started");
+ // Passivation loop
+ while(running)
+ {
+ // Logger.log("Clearing cache");
+ // Passivate old. Lock cache first
+ //synchronized(RandomEntityInstanceCache.this)
+ synchronized(cache)
+ {
+ // Do not use cache (many to one entries)
+ int currentActive = cache.size();
+ if (currentActive > minActive)
+ {
+ InstancePool pool = ((EntityContainer)con).getInstancePool();
+
+ Logger.debug("Too many active instances:"+currentActive);
+
+ // Passivate some instance; they need to be unlocked though
+
+ //KeySet has cacheKeys (currentActive>0)
+ Iterator keys = cache.keySet().iterator();
+
+ while(keys.hasNext())
+ {
+
+ Object key = keys.next();
+
+ //Get the context
+ EntityEnterpriseContext ctx =
+ (EntityEnterpriseContext) cache.get(key);
+
+
+ // Make sure we can work on it
+ Logger.debug("Checking:"+ctx.getId());
+
+ //TODO do the Locking logic
+ try
+ {
+ Logger.debug("Passivating:"+ctx.getId());
+
+ // Passivate the entry
+
((EntityContainer)con).getPersistenceManager().passivateEntity(ctx);
+
+ // Remove the entry
+ cache.remove(key);
+
+ //keep the count
+ currentActive--;
+ }
+
+ catch (Exception e) { Logger.log("Could not passivate
instance");}
+
+ // Are we done?
+ if (currentActive == minActive) break;
+ }
+
+ }
+ }
+ // DEBUG Logger.log("Passivation done");
+ Logger.log("Passivation done");
+
+ // Sleep
+ try
+ {
+ Thread.sleep(timeout);
+ } catch (InterruptedException e)
+ {
+ // Ignore
+ }
+
+ }
+ }
+ }
+}
1.8 +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.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- StatefulSessionFilePersistenceManager.java 2000/09/26 18:58:32 1.7
+++ StatefulSessionFilePersistenceManager.java 2000/09/26 20:18:51 1.8
@@ -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.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 -------------------------------------------------
-}
+/*
+ * 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.8 $
+ */
+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.5 +313 -313
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.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- StatefulSessionInstanceInterceptor.java 2000/09/26 18:58:32 1.4
+++ StatefulSessionInstanceInterceptor.java 2000/09/26 20:18:51 1.5
@@ -1,313 +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.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);}
- }
-
-
- }
- }
-}
-
+/*
+* 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.5 $
+*/
+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.2 +428 -428 jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java
Index: TxInterceptorCMT.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TxInterceptorCMT.java 2000/09/26 18:58:32 1.1
+++ TxInterceptorCMT.java 2000/09/26 20:18:51 1.2
@@ -1,428 +1,428 @@
-/*
-* 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 -------------------------------------------------
-
-}
+/*
+* 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.2 $
+*/
+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 -------------------------------------------------
+
+}