You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/01/13 03:25:49 UTC

svn commit: r495820 - in /incubator/openejb/trunk/openejb3: container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ container/openejb-core/src/main/java/org/apache/openejb/core/ container/openejb-core/src/main/java/org/apache/openejb...

Author: dain
Date: Fri Jan 12 18:25:48 2007
New Revision: 495820

URL: http://svn.apache.org/viewvc?view=rev&rev=495820
Log:
OPENEJB-442 added support for Stateful Session Bean Extended Persistence Context with tests

Added:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulUserTransaction.java
Modified:
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreContext.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContext.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulEncUserTransaction.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Index.java
    incubator/openejb/trunk/openejb3/container/openejb-persistence/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulBean.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulPojoBean.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulBean.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulObject.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/resources/META-INF/ejb-jar.xml
    incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulContextLookupTests.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulJndiEncTests.java
    incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulPojoContextLookupTests.java

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Fri Jan 12 18:25:48 2007
@@ -16,6 +16,27 @@
  */
 package org.apache.openejb.assembler.classic;
 
+import java.io.File;
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.persistence.EntityManagerFactory;
+import javax.resource.spi.ConnectionManager;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+
 import org.apache.openejb.Container;
 import org.apache.openejb.DeploymentInfo;
 import org.apache.openejb.EnvProps;
@@ -23,12 +44,14 @@
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.core.ConnectorReference;
+import org.apache.openejb.core.CoreContainerSystem;
 import org.apache.openejb.core.CoreDeploymentInfo;
+import org.apache.openejb.core.SimpleTransactionSynchronizationRegistry;
 import org.apache.openejb.core.TemporaryClassLoader;
-import org.apache.openejb.core.CoreContainerSystem;
 import org.apache.openejb.javaagent.Agent;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.persistence.GlobalJndiDataSourceResolver;
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
 import org.apache.openejb.persistence.PersistenceDeployer;
 import org.apache.openejb.persistence.PersistenceDeployerException;
@@ -42,26 +65,6 @@
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.StaticRecipe;
 
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.InitialContext;
-import javax.persistence.EntityManagerFactory;
-import javax.resource.spi.ConnectionManager;
-import javax.resource.spi.ManagedConnectionFactory;
-import javax.transaction.TransactionManager;
-import java.io.File;
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
 public class Assembler extends AssemblerTool implements org.apache.openejb.spi.Assembler {
 
     public static final Logger logger = Logger.getInstance("OpenEJB.startup", Assembler.class.getPackage().getName());
@@ -515,6 +518,25 @@
         props.put(serviceInfo.id, service);
 
         this.transactionManager = (TransactionManager) service;
+
+        // todo find a better place for this
+
+        // TransactionSynchronizationRegistry
+        TransactionSynchronizationRegistry synchronizationRegistry ;
+        if (transactionManager instanceof TransactionSynchronizationRegistry) {
+            synchronizationRegistry = (TransactionSynchronizationRegistry) transactionManager;
+        } else {
+            // todo this sould be built
+            synchronizationRegistry = new SimpleTransactionSynchronizationRegistry(transactionManager);
+        }
+        Assembler.getContext().put(TransactionSynchronizationRegistry.class.getName(), synchronizationRegistry);
+        SystemInstance.get().setComponent(TransactionSynchronizationRegistry.class, synchronizationRegistry);
+
+        // JtaEntityManagerRegistry
+        // todo this sould be built
+        JtaEntityManagerRegistry jtaEntityManagerRegistry = new JtaEntityManagerRegistry(synchronizationRegistry);
+        Assembler.getContext().put(JtaEntityManagerRegistry.class.getName(), jtaEntityManagerRegistry);
+        SystemInstance.get().setComponent(JtaEntityManagerRegistry.class, jtaEntityManagerRegistry);
     }
 
     private URL toUrl(String jarPath) throws OpenEJBException {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java Fri Jan 12 18:25:48 2007
@@ -25,6 +25,7 @@
 import org.apache.openejb.core.ivm.naming.IvmContext;
 import org.apache.openejb.util.Messages;
 import org.apache.openejb.util.SafeToolkit;
+import org.apache.openejb.util.Index;
 
 import javax.persistence.EntityManagerFactory;
 import java.io.File;
@@ -32,6 +33,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 class EnterpriseBeanBuilder {
     protected static final Messages messages = new Messages("org.apache.openejb.util.resources");
@@ -173,6 +175,15 @@
             StatefulBeanInfo statefulBeanInfo = (StatefulBeanInfo) bean;
             deployment.setPrePassivate(getCallback(ejbClass, statefulBeanInfo.prePassivate));
             deployment.setPostActivate(getCallback(ejbClass, statefulBeanInfo.postActivate));
+
+            Map<EntityManagerFactory, Map> extendedEntityManagerFactories = new HashMap<EntityManagerFactory, Map>();
+            for (PersistenceContextInfo info : statefulBeanInfo.jndiEnc.persistenceContextRefs) {
+                if (info.extended) {
+                    EntityManagerFactory entityManagerFactory = jndiEncBuilder.findEntityManagerFactory(info.persistenceUnitName);
+                    extendedEntityManagerFactories.put(entityManagerFactory, info.properties);
+                }
+            }
+            deployment.setExtendedEntityManagerFactories(new Index<EntityManagerFactory, Map>(extendedEntityManagerFactories));
         }
 
         if (ejbType.isSession() || ejbType.isMessageDriven()) {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiEncBuilder.java Fri Jan 12 18:25:48 2007
@@ -21,7 +21,6 @@
 import org.apache.openejb.persistence.JtaEntityManager;
 import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.core.CoreUserTransaction;
-import org.apache.openejb.core.SimpleTransactionSynchronizationRegistry;
 import org.apache.openejb.core.ivm.naming.IntraVmJndiReference;
 import org.apache.openejb.core.ivm.naming.IvmContext;
 import org.apache.openejb.core.ivm.naming.JndiReference;
@@ -145,18 +144,11 @@
 
         // bind TransactionSynchronizationRegistry
         TransactionSynchronizationRegistry synchronizationRegistry = (TransactionSynchronizationRegistry) Assembler.getContext().get(TransactionSynchronizationRegistry.class.getName());
-        if (synchronizationRegistry == null) {
-            // todo this should be move to the main service assembler
-            if (transactionManager instanceof TransactionSynchronizationRegistry) {
-                synchronizationRegistry = (TransactionSynchronizationRegistry) transactionManager;
-            } else {
-                synchronizationRegistry = new SimpleTransactionSynchronizationRegistry(transactionManager);
-            }
-            // todo make sure this gets into the system instance
-            Assembler.getContext().put(TransactionSynchronizationRegistry.class.getName(), synchronizationRegistry);
-        }
         bindings.put("java:comp/TransactionSynchronizationRegistry", synchronizationRegistry);
 
+        // get JtaEntityManagerRegistry
+        JtaEntityManagerRegistry jtaEntityManagerRegistry = (JtaEntityManagerRegistry) Assembler.getContext().get(JtaEntityManagerRegistry.class.getName());
+
         // bind UserTransaction if bean managed transactions
         if (beanManagedTransactions) {
             Object userTransaction = referenceWrapper.wrap(new CoreUserTransaction(transactionManager));
@@ -261,46 +253,16 @@
         
         for (int i = 0; i < persistenceUnitRefs.length; i++){
         	PersistenceUnitInfo puRefInfo = persistenceUnitRefs[i];
-            Reference reference = null;
-            EntityManagerFactory factory = null;
-            if (puRefInfo.persistenceUnitName != null) {    
-            	if(puRefInfo.persistenceUnitName.indexOf("#") == -1){
-            		factory = entityManagerFactories.get(puRefInfo.persistenceUnitName);
-            	}else{
-            		factory = findEntityManagerFactory(allFactories,jarPath,puRefInfo.persistenceUnitName);
-            	}
-            }else if(entityManagerFactories.size() == 1){
-            	factory = entityManagerFactories.values().toArray(new EntityManagerFactory[1])[0];
-            }else{
-            	throw new OpenEJBException("Deployment failed as the Persistence Unit could not be located. Try adding the 'persistence-unit-name' tag in ejb-jar.xml ");
-            }
-            
-            reference = new PersistenceUnitReference(factory);
+            EntityManagerFactory factory = findEntityManagerFactory(puRefInfo.persistenceUnitName);
+
+            Reference reference = new PersistenceUnitReference(factory);
             bindings.put(normalize(puRefInfo.referenceName), wrapReference(reference));
         }
 
         for (int i = 0; i < persistenceContextRefs.length; i++) {
             PersistenceContextInfo contextInfo = persistenceContextRefs[i];
+            EntityManagerFactory factory = findEntityManagerFactory(contextInfo.persistenceUnitName);
 
-            EntityManagerFactory factory;
-            if (contextInfo.persistenceUnitName != null) {
-                if (contextInfo.persistenceUnitName.indexOf("#") == -1) {
-                    factory = entityManagerFactories.get(contextInfo.persistenceUnitName);
-                } else {
-                    factory = findEntityManagerFactory(allFactories, jarPath, contextInfo.persistenceUnitName);
-                }
-            } else if (entityManagerFactories.size() == 1) {
-                factory = entityManagerFactories.values().toArray(new EntityManagerFactory[1])[0];
-            } else {
-                throw new OpenEJBException("Deployment failed as the Persistence Unit could not be located. Try adding the 'persistence-unit-name' tag in ejb-jar.xml ");
-            }
-
-            JtaEntityManagerRegistry jtaEntityManagerRegistry = (JtaEntityManagerRegistry) Assembler.getContext().get(JtaEntityManagerRegistry.class.getName());
-            if (jtaEntityManagerRegistry == null) {
-                // todo make sure this gets into the system instance
-                jtaEntityManagerRegistry = new JtaEntityManagerRegistry(synchronizationRegistry);
-                Assembler.getContext().put(JtaEntityManagerRegistry.class.getName(), jtaEntityManagerRegistry);
-            }
             JtaEntityManager jtaEntityManager = new JtaEntityManager(jtaEntityManagerRegistry, factory, contextInfo.properties, contextInfo.extended);
             Reference reference = new PersistenceContextReference(jtaEntityManager);
             bindings.put(normalize(contextInfo.referenceName), wrapReference(reference));
@@ -375,7 +337,7 @@
         }
 
         public Object wrap(UserTransaction userTransaction) {
-            return new org.apache.openejb.core.stateful.StatefulEncUserTransaction((CoreUserTransaction) userTransaction);
+            return new org.apache.openejb.core.stateful.StatefulEncUserTransaction(userTransaction);
         }
     }
 
@@ -400,6 +362,22 @@
         }
     }
     
+    public EntityManagerFactory findEntityManagerFactory(String persistenceName) throws OpenEJBException {
+        EntityManagerFactory factory;
+        if (persistenceName != null) {
+            if (persistenceName.indexOf("#") == -1) {
+                factory = entityManagerFactories.get(persistenceName);
+            } else {
+                factory = findEntityManagerFactory(allFactories, jarPath, persistenceName);
+            }
+        } else if (entityManagerFactories.size() == 1) {
+            factory = entityManagerFactories.values().toArray(new EntityManagerFactory[1])[0];
+        } else {
+            throw new OpenEJBException("Deployment failed as the Persistence Unit could not be located. Try adding the 'persistence-unit-name' tag in ejb-jar.xml ");
+        }
+        return factory;
+    }
+
     /**
      * This method will currently support paths like ../../xyz/ejbmodule.jar#PuName, ././xyz/ejbmodule.jar#PuName
      * and ejbmodule.jar#PuName. For all other types of path it will throw an exception stating an invalid

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreContext.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreContext.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreContext.java Fri Jan 12 18:25:48 2007
@@ -26,6 +26,8 @@
 import javax.naming.NamingException;
 import javax.transaction.Status;
 import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.util.List;
 
 import org.apache.openejb.DeploymentInfo;
 import org.apache.openejb.InterfaceType;
@@ -49,7 +51,7 @@
 
     public final static byte EJBHOME_METHOD = (byte) 5;
 
-    private final CoreUserTransaction userTransaction;
+    private final UserTransaction userTransaction;
     private final SecurityService securityService;
     private final TransactionManager transactionManager;
 
@@ -59,6 +61,12 @@
         this.userTransaction = new CoreUserTransaction(transactionManager);
     }
 
+    protected CoreContext(TransactionManager transactionManager, SecurityService securityService, UserTransaction userTransaction) {
+        this.transactionManager = transactionManager;
+        this.securityService = securityService;
+        this.userTransaction = userTransaction;
+    }
+
     private TransactionManager getTransactionManager() {
         return transactionManager;
     }
@@ -176,18 +184,21 @@
 
         ThreadContext threadContext = ThreadContext.getThreadContext();
         org.apache.openejb.DeploymentInfo di = threadContext.getDeploymentInfo();
-        if (di.isBeanManagedTransaction())
+        if (di.isBeanManagedTransaction()) {
             throw new IllegalStateException("bean-managed transaction beans can not access the getRollbackOnly( ) method");
+        }
 
         checkBeanState(ROLLBACK_METHOD);
         try {
             int status = getTransactionManager().getStatus();
-            if (status == Status.STATUS_MARKED_ROLLBACK || status == Status.STATUS_ROLLEDBACK)
+            if (status == Status.STATUS_MARKED_ROLLBACK || status == Status.STATUS_ROLLEDBACK) {
                 return true;
-            else if (status == Status.STATUS_NO_TRANSACTION)// this would be true for Supports tx attribute where no tx was propagated
+            } else if (status == Status.STATUS_NO_TRANSACTION) {
+                // this would be true for Supports tx attribute where no tx was propagated
                 throw new IllegalStateException("No current transaction");
-            else
+            } else {
                 return false;
+            }
         } catch (javax.transaction.SystemException se) {
             throw new RuntimeException("Transaction service has thrown a SystemException");
         }
@@ -196,8 +207,9 @@
     public void setRollbackOnly() {
         ThreadContext threadContext = ThreadContext.getThreadContext();
         org.apache.openejb.DeploymentInfo di = threadContext.getDeploymentInfo();
-        if (di.isBeanManagedTransaction())
+        if (di.isBeanManagedTransaction()) {
             throw new IllegalStateException("bean-managed transaction beans can not access the setRollbackOnly( ) method");
+        }
 
         checkBeanState(ROLLBACK_METHOD);
 
@@ -216,8 +228,9 @@
         if (di.isBeanManagedTransaction()) {
             checkBeanState(USER_TRANSACTION_METHOD);
             return userTransaction;
-        } else
+        } else {
             throw new java.lang.IllegalStateException("container-managed transaction beans can not access the UserTransaction");
+        }
     }
 
     /**

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java Fri Jan 12 18:25:48 2007
@@ -33,6 +33,7 @@
 import javax.ejb.SessionBean;
 import javax.ejb.MessageDrivenBean;
 import javax.ejb.TimedObject;
+import javax.persistence.EntityManagerFactory;
 
 import org.apache.openejb.Container;
 import org.apache.openejb.RpcContainer;
@@ -64,6 +65,7 @@
 import org.apache.openejb.core.interceptor.InterceptorData;
 import org.apache.openejb.core.mdb.MessageDrivenBeanManagedTxPolicy;
 import org.apache.openejb.util.proxy.ProxyManager;
+import org.apache.openejb.util.Index;
 
 /**
  * @org.apache.xbean.XBean element="deployment"
@@ -93,7 +95,7 @@
     private EJBLocalHome ejbLocalHomeRef;
     private BusinessLocalHome businessLocalHomeRef;
     private BusinessRemoteHome businessRemoteHomeRef;
-    private final HashMap<Class, Object> data = new HashMap();
+    private final Map<Class, Object> data = new HashMap<Class, Object>();
 
 
     private Object containerData;
@@ -114,6 +116,7 @@
     private String jarPath;
     private final Map<String, String> activationProperties = new HashMap<String, String>();
     private final List<Injection> injections = new ArrayList<Injection>();
+    private Index<EntityManagerFactory,Map> extendedEntityManagerFactories;
 
     public Class getInterface(InterfaceType interfaceType) {
         switch(interfaceType){
@@ -212,18 +215,28 @@
         createMethodMap();
     }
 
+    @SuppressWarnings({"unchecked"})
     public <T> T get(Class<T> type) {
         return (T)data.get(type);
     }
 
+    @SuppressWarnings({"unchecked"})
     public <T> T set(Class<T> type, T value) {
         return (T) data.put(type, value);
     }
-    
+
     public List<Injection> getInjections() {
         return injections;
     }
 
+    public Index<EntityManagerFactory,Map> getExtendedEntityManagerFactories() {
+        return extendedEntityManagerFactories;
+    }
+
+    public void setExtendedEntityManagerFactories(Index<EntityManagerFactory, Map> extendedEntityManagerFactories) {
+        this.extendedEntityManagerFactories = extendedEntityManagerFactories;
+    }
+
     public Object getContainerData() {
         return containerData;
     }
@@ -515,8 +528,9 @@
            context(REQUIRES_NEW, SUPPORTS) and no client to handle exceptions (MANDATORY, NEVER).
          */
         if (componentType.isMessageDriven() && !isBeanManagedTransaction && container instanceof TransactionContainer) {
-            if (policy.policyType != policy.NotSupported && policy.policyType != policy.Required) {
-                if (method.equals(this.ejbTimeout) && policy.policyType == policy.RequiresNew) {
+            if (policy.policyType != TransactionPolicy.NotSupported && policy.policyType != TransactionPolicy.Required) {
+
+                if (method.equals(this.ejbTimeout) && policy.policyType == TransactionPolicy.RequiresNew) {
                     // do nothing. This is allowed as the timer callback method for a message driven bean
                     // can also have a transaction policy of RequiresNew Sec 5.4.12 of Ejb 3.0 Core Spec
                 } else {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java Fri Jan 12 18:25:48 2007
@@ -17,7 +17,13 @@
 package org.apache.openejb.core.stateful;
 
 import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
 import javax.transaction.Transaction;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
+
+import org.apache.openejb.util.Index;
 
 public class BeanEntry implements Serializable {
     private static final long serialVersionUID = 5940667199866151048L;
@@ -28,6 +34,11 @@
     private long timeStamp;
     private long timeOutInterval;
     protected transient Transaction beanTransaction;
+    // todo if we keyed by an entity manager factory id we would not have to make this transient and rebuild the index below
+    // This would require that we crete an id and that we track it
+    // alternatively, we could use ImmutableArtifact with some read/write replace magic
+    private transient Map<EntityManagerFactory, EntityManager> entityManagers;
+    private EntityManager[] entityManagerArray;
 
     protected BeanEntry(Object beanInstance, Object primKey, long timeOut) {
         bean = beanInstance;
@@ -50,4 +61,25 @@
             timeStamp = System.currentTimeMillis();
         }
     }
-}         
+
+    public Map<EntityManagerFactory, EntityManager> getEntityManagers(Index<EntityManagerFactory, Map> factories) {
+        if (entityManagers == null && entityManagerArray != null) {
+            entityManagers = new HashMap<EntityManagerFactory, EntityManager>();
+            for (int i = 0; i < entityManagerArray.length; i++) {
+                EntityManagerFactory entityManagerFactory = factories.getKey(i);
+                EntityManager entityManager = entityManagerArray[i];
+                entityManagers.put(entityManagerFactory, entityManager);
+            }
+        }
+        return entityManagers;
+    }
+
+    public void setEntityManagers(Index<EntityManagerFactory, EntityManager> entityManagers) {
+        this.entityManagers = entityManagers;
+        if (entityManagers != null) {
+            entityManagerArray = entityManagers.values().toArray(new EntityManager[entityManagers.size()]);
+        } else {
+            entityManagerArray = null;
+        }
+    }
+}

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java Fri Jan 12 18:25:48 2007
@@ -22,6 +22,9 @@
 import org.apache.openejb.ProxyInfo;
 import org.apache.openejb.ApplicationException;
 import org.apache.openejb.RpcContainer;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
+import org.apache.openejb.persistence.EntityManagerAlreadyRegisteredException;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
 import org.apache.openejb.core.CoreDeploymentInfo;
@@ -33,14 +36,18 @@
 import org.apache.openejb.util.Index;
 
 import javax.ejb.SessionBean;
+import javax.ejb.EJBException;
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionRequiredException;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
 import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
 import java.rmi.RemoteException;
 import java.rmi.dgc.VMID;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.ArrayList;
 
 /**
  * @org.apache.xbean.XBean element="statefulContainer"
@@ -52,6 +59,8 @@
     private final TransactionManager transactionManager;
     private final SecurityService securityService;
     private final StatefulInstanceManager instanceManager;
+    // todo this should be part of the constructor
+    private final JtaEntityManagerRegistry entityManagerRegistry = SystemInstance.get().getComponent(JtaEntityManagerRegistry.class);
 
     /**
      * Index used for getDeployments() and getDeploymentInfo(deploymentId).
@@ -64,7 +73,7 @@
         this.transactionManager = transactionManager;
         this.securityService = securityService;
 
-        instanceManager = new StatefulInstanceManager(transactionManager, securityService, passivator, timeOut, poolSize, bulkPassivate);
+        instanceManager = new StatefulInstanceManager(transactionManager, securityService, entityManagerRegistry, passivator, timeOut, poolSize, bulkPassivate);
     }
 
     private class Data {
@@ -225,14 +234,19 @@
         // generate a new primary key
         Object primaryKey = newPrimaryKey();
 
+
         ThreadContext createContext = new ThreadContext(deploymentInfo, primaryKey, securityIdentity);
         createContext.setCurrentOperation(Operation.OP_CREATE);
         ThreadContext oldCallContext = ThreadContext.enter(createContext);
         try {
             checkAuthorization(deploymentInfo, callMethod, securityIdentity);
 
+            // create the extended entity managers
+            Index<EntityManagerFactory, EntityManager> entityManagers = createEntityManagers(deploymentInfo);
+
             // allocate a new instance
             Object bean = instanceManager.newInstance(primaryKey, deploymentInfo.getBeanClass());
+            instanceManager.setEntityManagers(primaryKey, entityManagers);
 
             // Invoke postConstructs or create(...)
             if (bean instanceof SessionBean) {
@@ -245,7 +259,6 @@
                 }
             }
 
-
             instanceManager.poolInstance(primaryKey, bean);
 
             Class callingClass = callMethod.getDeclaringClass();
@@ -275,6 +288,7 @@
                     }
                 }
             } finally {
+                // todo destroy extended persistence contexts
                 instanceManager.freeInstance(callContext.getPrimaryKey());
             }
         } finally {
@@ -327,6 +341,7 @@
 
         Object returnValue = null;
         try {
+            registerEntityManagers(callContext);
             returnValue = runMethod.invoke(bean, args);
         } catch (InvocationTargetException ite) {// handle enterprise bean exception
             if (ite.getTargetException() instanceof RuntimeException) {
@@ -352,11 +367,70 @@
             txPolicy.handleSystemException(re, bean, txContext);
 
         } finally {
-
+            unregisterEntityManagers(callContext);
             txPolicy.afterInvoke(bean, txContext);
         }
 
         return returnValue;
+    }
+
+    private Index<EntityManagerFactory, EntityManager> createEntityManagers(CoreDeploymentInfo deploymentInfo) {
+        // create the extended entity managers
+        Index<EntityManagerFactory, Map> factories = deploymentInfo.getExtendedEntityManagerFactories();
+        Index<EntityManagerFactory,EntityManager> entityManagers = null;
+        if (factories != null && factories.size() > 0) {
+            entityManagers = new Index<EntityManagerFactory, EntityManager>(new ArrayList<EntityManagerFactory>(factories.keySet()));
+            for (Map.Entry<EntityManagerFactory, Map> entry : factories.entrySet()) {
+                EntityManagerFactory entityManagerFactory = entry.getKey();
+                Map properties = entry.getValue();
+
+
+                EntityManager entityManager = entityManagerRegistry.getInheritedEntityManager(entityManagerFactory);
+                if (entityManager == null) {
+                    if (properties != null) {
+                        entityManager = entityManagerFactory.createEntityManager(properties);
+                    } else {
+                        entityManager = entityManagerFactory.createEntityManager();
+                    }
+                }
+                entityManagers.put(entityManagerFactory, entityManager);
+            }
+        }
+        return entityManagers;
+    }
+
+    private void registerEntityManagers(ThreadContext callContext) throws OpenEJBException {
+        if (entityManagerRegistry == null) return;
+
+        CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
+
+        // get the factories
+        Index<EntityManagerFactory, Map> factories = deploymentInfo.getExtendedEntityManagerFactories();
+        if (factories == null) return;
+
+        // get the managers for the factories
+        Object primaryKey = callContext.getPrimaryKey();
+        Map<EntityManagerFactory, EntityManager> entityManagers = instanceManager.getEntityManagers(primaryKey, factories);
+        if (entityManagers == null) return;
+
+        // register them
+        try {
+            entityManagerRegistry.addEntityManagers((String)deploymentInfo.getDeploymentID(), primaryKey, entityManagers);
+        } catch (EntityManagerAlreadyRegisteredException e) {
+            throw new EJBException(e);
+        }
+    }
+
+    private void unregisterEntityManagers(ThreadContext callContext) {
+        if (entityManagerRegistry == null) return;
+
+        CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
+
+        // get the managers for the factories
+        Object primaryKey = callContext.getPrimaryKey();
+
+        // register them
+        entityManagerRegistry.removeEntityManagers((String)deploymentInfo.getDeploymentID(), primaryKey);
     }
 
     public void discardInstance(Object bean, ThreadContext threadContext) {

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContext.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContext.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContext.java Fri Jan 12 18:25:48 2007
@@ -18,21 +18,23 @@
 
 import org.apache.openejb.RpcContainer;
 import org.apache.openejb.InterfaceType;
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreUserTransaction;
 import org.apache.openejb.core.ivm.EjbObjectProxyHandler;
 import org.apache.openejb.spi.SecurityService;
 
 import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
 import javax.xml.rpc.handler.MessageContext;
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 
 public class StatefulContext extends org.apache.openejb.core.CoreContext implements javax.ejb.SessionContext {
 
-    public StatefulContext(TransactionManager transactionManager, SecurityService securityService) {
-        super(transactionManager, securityService);
+    public StatefulContext(TransactionManager transactionManager, SecurityService securityService, UserTransaction userTransaction) {
+        super(transactionManager, securityService, userTransaction);
     }
 
     public void checkBeanState(byte methodCategory) throws IllegalStateException {
@@ -69,8 +71,9 @@
                     getPrimaryKey
                     getUserTransaction
                 */
-                if (methodCategory != EJBHOME_METHOD)
+                if (methodCategory != EJBHOME_METHOD) {
                     throw new IllegalStateException("Invalid operation attempted");
+                }
                 break;
             case OP_CREATE:
             case OP_REMOVE:
@@ -89,10 +92,11 @@
                     getRollbackOnly,
                     setRollbackOnly
                 */
-                if (methodCategory == ROLLBACK_METHOD)
+                if (methodCategory == ROLLBACK_METHOD) {
                     throw new IllegalStateException("Invalid operation attempted");
-                else
+                } else {
                     break;
+                }
             case OP_BUSINESS:
             case OP_AFTER_BEGIN:
             case OP_BEFORE_COMPLETION:
@@ -137,8 +141,10 @@
         private Object readResolve() throws ObjectStreamException {
             // DMB: Could easily be done generically with an recipie
             TransactionManager transactionManager = SystemInstance.get().getComponent(TransactionManager.class);
+            JtaEntityManagerRegistry jtaEntityManagerRegistry = SystemInstance.get().getComponent(JtaEntityManagerRegistry.class);
             SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class);
-            return new StatefulContext(transactionManager, securityService);
+            StatefulUserTransaction userTransaction = new StatefulUserTransaction(new CoreUserTransaction(transactionManager), jtaEntityManagerRegistry);
+            return new StatefulContext(transactionManager, securityService, userTransaction);
         }
     }
 }

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulEncUserTransaction.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulEncUserTransaction.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulEncUserTransaction.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulEncUserTransaction.java Fri Jan 12 18:25:48 2007
@@ -17,11 +17,13 @@
 package org.apache.openejb.core.stateful;
 
 import javax.naming.NameNotFoundException;
+import javax.transaction.UserTransaction;
 
-import org.apache.openejb.core.CoreUserTransaction;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ivm.naming.EncReference;
 import org.apache.openejb.core.ivm.naming.ObjectReference;
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
+import org.apache.openejb.loader.SystemInstance;
 
 
 /**
@@ -34,8 +36,9 @@
     /**
      * This constructor take a new CoreUserTransaction object as the object reference
      */
-    public StatefulEncUserTransaction(CoreUserTransaction reference) {
-        super(new ObjectReference(reference));
+    public StatefulEncUserTransaction(UserTransaction userTransaction) {
+        super(new ObjectReference(new StatefulUserTransaction(userTransaction,
+                SystemInstance.get().getComponent(JtaEntityManagerRegistry.class))));
     }
 
     /**

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java Fri Jan 12 18:25:48 2007
@@ -22,6 +22,7 @@
 import java.rmi.RemoteException;
 import java.util.Hashtable;
 import java.util.LinkedList;
+import java.util.Map;
 import javax.ejb.EJBException;
 import javax.ejb.SessionContext;
 import javax.naming.Context;
@@ -29,18 +30,23 @@
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionRolledbackException;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
 
 import org.apache.openejb.ApplicationException;
 import org.apache.openejb.Injection;
 import org.apache.openejb.InvalidateReferenceException;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.SystemException;
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.core.CoreDeploymentInfo;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreUserTransaction;
 import org.apache.openejb.core.ivm.IntraVmCopyMonitor;
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.util.Logger;
+import org.apache.openejb.util.Index;
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.Option;
 import org.apache.xbean.recipe.StaticRecipe;
@@ -61,10 +67,12 @@
 
     private final TransactionManager transactionManager;
     private final SecurityService securityService;
+    private final JtaEntityManagerRegistry jtaEntityManagerRegistry;
 
-    public StatefulInstanceManager(TransactionManager transactionManager, SecurityService securityService, Class passivatorClass, int timeout, int poolSize, int bulkPassivate) throws OpenEJBException {
+    public StatefulInstanceManager(TransactionManager transactionManager, SecurityService securityService, JtaEntityManagerRegistry jtaEntityManagerRegistry, Class passivatorClass, int timeout, int poolSize, int bulkPassivate) throws OpenEJBException {
         this.transactionManager = transactionManager;
         this.securityService = securityService;
+        this.jtaEntityManagerRegistry = jtaEntityManagerRegistry;
         this.lruQueue = new BeanEntryQueue(poolSize);
         if (poolSize == 0) {
             this.bulkPassivationSize = 1;
@@ -91,6 +99,16 @@
         entry.beanTransaction = beanTransaction;
     }
 
+    public Map<EntityManagerFactory, EntityManager> getEntityManagers(Object primaryKey, Index<EntityManagerFactory, Map> factories) throws OpenEJBException {
+        BeanEntry entry = getBeanEntry(primaryKey);
+        return entry.getEntityManagers(factories);
+    }
+
+    public void setEntityManagers(Object primaryKey, Index<EntityManagerFactory, EntityManager> entityManagers) throws OpenEJBException {
+        BeanEntry entry = getBeanEntry(primaryKey);
+        entry.setEntityManagers(entityManagers);
+    }
+
     public Object newInstance(Object primaryKey, Class beanClass) throws OpenEJBException {
         Object bean = null;
 
@@ -141,7 +159,8 @@
     }
 
     private SessionContext createSessionContext() {
-        return new StatefulContext(transactionManager, securityService);
+        StatefulUserTransaction userTransaction = new StatefulUserTransaction(new CoreUserTransaction(transactionManager), jtaEntityManagerRegistry);
+        return new StatefulContext(transactionManager, securityService, userTransaction);
     }
 
     public Object obtainInstance(Object primaryKey, ThreadContext callContext) throws OpenEJBException {

Added: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulUserTransaction.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulUserTransaction.java?view=auto&rev=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulUserTransaction.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulUserTransaction.java Fri Jan 12 18:25:48 2007
@@ -0,0 +1,86 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.core.stateful;
+
+import javax.transaction.UserTransaction;
+import javax.transaction.NotSupportedException;
+import javax.transaction.SystemException;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+
+import org.apache.openejb.persistence.JtaEntityManagerRegistry;
+import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreDeploymentInfo;
+import org.apache.openejb.BeanType;
+
+public class StatefulUserTransaction implements UserTransaction {
+    private final UserTransaction userTransaction;
+    private final JtaEntityManagerRegistry jtaEntityManagerRegistry;
+
+    public StatefulUserTransaction(UserTransaction userTransaction, JtaEntityManagerRegistry jtaEntityManagerRegistry) {
+        this.userTransaction = userTransaction;
+        this.jtaEntityManagerRegistry = jtaEntityManagerRegistry;
+    }
+
+    public void begin() throws NotSupportedException, SystemException {
+        userTransaction.begin();
+
+        // get the callContext
+        ThreadContext callContext = ThreadContext.getThreadContext();
+        if (callContext == null) {
+            // someone is using the user transaction out side of the component
+            return;
+        }
+
+        // get the deployment info
+        CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
+        if (deploymentInfo.getComponentType() != BeanType.STATEFUL) {
+            // some other non-stateful ejb is using our user transaction
+            return;
+        }
+
+        // get the primary key
+        Object primaryKey = callContext.getPrimaryKey();
+        if (primaryKey == null) {
+            // is is not a bean method
+            return;
+        }
+        jtaEntityManagerRegistry.transactionStarted((String)deploymentInfo.getDeploymentID(), primaryKey);
+    }
+
+    public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException {
+        userTransaction.commit();
+    }
+
+    public int getStatus() throws SystemException {
+        return userTransaction.getStatus();
+    }
+
+    public void rollback() throws IllegalStateException, SecurityException, SystemException {
+        userTransaction.rollback();
+    }
+
+    public void setRollbackOnly() throws IllegalStateException, SystemException {
+        userTransaction.setRollbackOnly();
+    }
+
+    public void setTransactionTimeout(int i) throws SystemException {
+        userTransaction.setTransactionTimeout(i);
+    }
+}

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Index.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Index.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Index.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Index.java Fri Jan 12 18:25:48 2007
@@ -26,7 +26,6 @@
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
-import java.util.Collection;
 
 /**
  * @version $Revision$ $Date$
@@ -40,7 +39,7 @@
 
     public Index(Map<K,V> map) {
         entries = new IndexEntry[map.size()];
-        keyIndicies = new LinkedHashMap(map.size());
+        keyIndicies = new LinkedHashMap<K,Integer>(map.size());
 
         int i = 0;
         for (Entry<K, V> entry : map.entrySet()) {
@@ -52,9 +51,21 @@
         entrySet = new IndexEntrySet();
     }
 
+    public Index(List<K> keys) {
+        entries = new IndexEntry[keys.size()];
+        keyIndicies = new LinkedHashMap<K,Integer>(keys.size());
+        for (int i = 0; i < keys.size(); i++) {
+            K key = keys.get(i);
+            entries[i] = new IndexEntry<K,V>(key, null);
+            keyIndicies.put(key, new Integer(i));
+        }
+
+        entrySet = new IndexEntrySet();
+    }
+
     public Index(K[] keys) {
         entries = new IndexEntry[keys.length];
-        keyIndicies = new LinkedHashMap(keys.length);
+        keyIndicies = new LinkedHashMap<K,Integer>(keys.length);
         for (int i = 0; i < keys.length; i++) {
             K key = keys[i];
             entries[i] = new IndexEntry<K,V>(key, null);
@@ -64,19 +75,20 @@
         entrySet = new IndexEntrySet();
     }
 
-    public List<V> valuesList() {
+    public List<V> values() {
         if (indexValueList == null) {
             indexValueList = new IndexValueList<V>();
         }
         return indexValueList;
     }
 
-    public Collection<V> values() {
-        return valuesList();
+    public Set<Entry<K,V>> entrySet() {
+        return entrySet;
     }
 
-    public Set entrySet() {
-        return entrySet;
+    public K getKey(int index) {
+        if (index < 0 || index >= entries.length) throw new IndexOutOfBoundsException("" + index);
+        return entries[index].getKey();
     }
 
     public V get(int index) {
@@ -93,7 +105,7 @@
     }
 
     public V put(K key, V value) {
-        int i = indexOf((K) key);
+        int i = indexOf(key);
         if (i < 0) {
             throw new IllegalArgumentException("Index does not contain this key and new entries cannot be added: " + (K) key);
         }
@@ -109,7 +121,7 @@
     }
 
     public int indexOf(K key) {
-        Integer index = (Integer) keyIndicies.get(key);
+        Integer index = keyIndicies.get(key);
         if (index == null) {
             return -1;
         }
@@ -142,6 +154,9 @@
 
     public Object[] toArray() {
         return toArray(new Object[entries.length]);
+    }
+
+    public static interface ListSet extends List, Set {
     }
 
     public Object[] toArray(Object values[]) {

Modified: incubator/openejb/trunk/openejb3/container/openejb-persistence/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-persistence/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-persistence/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-persistence/src/main/java/org/apache/openejb/persistence/JtaEntityManagerRegistry.java Fri Jan 12 18:25:48 2007
@@ -19,7 +19,7 @@
 
 
 import java.util.Map;
-import java.util.TreeMap;
+import java.util.HashMap;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.TransactionRequiredException;
@@ -167,11 +167,15 @@
 
     private class ExtendedRegistry {
         private final Map<InstanceId, Map<EntityManagerFactory, EntityManager>> entityManagersByDeploymentId =
-                new TreeMap<InstanceId, Map<EntityManagerFactory, EntityManager>>();
+                new HashMap<InstanceId, Map<EntityManagerFactory, EntityManager>>();
 
         private void addEntityManagers(InstanceId instanceId, Map<EntityManagerFactory, EntityManager> entityManagers) throws EntityManagerAlreadyRegisteredException {
-            if (instanceId == null) throw new NullPointerException("instanceId is null");
-            if (entityManagers == null) throw new NullPointerException("entityManagers is null");
+            if (instanceId == null) {
+                throw new NullPointerException("instanceId is null");
+            }
+            if (entityManagers == null) {
+                throw new NullPointerException("entityManagers is null");
+            }
 
             if (isTransactionActive()) {
                 for (Map.Entry<EntityManagerFactory, EntityManager> entry : entityManagers.entrySet()) {
@@ -199,7 +203,9 @@
         }
 
         private EntityManager getInheritedEntityManager(EntityManagerFactory entityManagerFactory) {
-            if (entityManagerFactory == null) throw new NullPointerException("entityManagerFactory is null");
+            if (entityManagerFactory == null) {
+                throw new NullPointerException("entityManagerFactory is null");
+            }
 
             for (Map<EntityManagerFactory, EntityManager> entityManagers : entityManagersByDeploymentId.values()) {
                 EntityManager entityManager = entityManagers.get(entityManagerFactory);
@@ -223,8 +229,12 @@
                 return;
             }
 
-            for (EntityManager entityManager : entityManagers.values()) {
+            for (Map.Entry<EntityManagerFactory, EntityManager> entry : entityManagers.entrySet()) {
+                EntityManagerFactory entityManagerFactory = entry.getKey();
+                EntityManager entityManager = entry.getValue();
                 entityManager.joinTransaction();
+                EntityManagerTxKey txKey = new EntityManagerTxKey(entityManagerFactory);
+                transactionRegistry.putResource(txKey, entityManager);
             }
         }
     }

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulBean.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulBean.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulBean.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulBean.java Fri Jan 12 18:25:48 2007
@@ -27,10 +27,12 @@
 import javax.ejb.EJBException;
 import javax.ejb.SessionContext;
 import javax.ejb.SessionSynchronization;
+import javax.ejb.CreateException;
 import javax.naming.InitialContext;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityManager;
 import javax.sql.DataSource;
+import javax.transaction.UserTransaction;
 import java.rmi.RemoteException;
 
 /**
@@ -42,6 +44,10 @@
 
     private String name;
     private SessionContext ejbContext;
+    private EntityManager extendedEntityManager;
+
+    // Used for testing propigation
+    private static EntityManager inheritedDelegate;
 
     //=============================
     // Home interface methods
@@ -54,8 +60,7 @@
      * @throws javax.ejb.CreateException
      * @see EncStatefulHome#create
      */
-    public void ejbCreate(String name)
-            throws javax.ejb.CreateException {
+    public void ejbCreate(String name) throws CreateException {
         this.name = name;
     }
     //
@@ -307,6 +312,117 @@
 
                 // call a do nothing method to assure entity manager actually exists
                 em.getFlushMode();
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+
+    public void lookupExtendedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                if (extendedEntityManager != null) {
+                    Assert.assertSame("Extended entity manager should be the same instance that was found last time",
+                            extendedEntityManager,
+                            em);
+                    Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                            extendedEntityManager.getDelegate(),
+                            em.getDelegate());
+                }
+                extendedEntityManager = em;
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void lookupPropagatedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                // get the raw entity manager so we can test it below
+                inheritedDelegate = (EntityManager) em.getDelegate();
+
+                // The extended entity manager is not propigated to a non-extended entity manager unless there is a transaction
+                EntityManager nonExtendedEm = (EntityManager)ctx.lookup("java:comp/env/persistence/TestContext");
+                nonExtendedEm.getFlushMode();
+                EntityManager nonExtendedDelegate = ((EntityManager) nonExtendedEm.getDelegate());
+                Assert.assertTrue("non-extended entity manager should be open", nonExtendedDelegate.isOpen());
+                Assert.assertNotSame("Extended non-extended entity manager shound not be the same instance as extendend entity manager when accessed out side of a transactions",
+                        inheritedDelegate,
+                        nonExtendedDelegate);
+
+                // When the non-extended entity manager is accessed within a transaction is should see the stateful extended context.
+                //
+                // Note: this code also tests EBJ 3.0 Persistence spec 5.9.1 "UserTransaction is begun within the method, the
+                // container associates the persistence context with the JTA transaction and calls EntityManager.joinTransaction."
+                // If our the extended entity manager were not associted with the transaction, the non-extended entity manager would
+                // not see it.
+                UserTransaction userTransaction = ejbContext.getUserTransaction();
+                userTransaction.begin();
+                try {
+                    Assert.assertSame("Extended non-extended entity manager to be same instance as extendend entity manager",
+                            inheritedDelegate,
+                            nonExtendedEm.getDelegate());
+                } finally {
+                    userTransaction.commit();
+                }
+
+                // When a stateful bean with an extended entity manager creates another stateful bean, the new bean will
+                // inherit the extended entity manager (assuming it contains an extended entity manager for the same persistence
+                // unit).
+                EncStatefulHome home = (EncStatefulHome) ejbContext.getEJBHome();
+                EncStatefulObject encStatefulObject = home.create("PropagatedPersistenceContext");
+
+                // test the new stateful bean recieved the context
+                encStatefulObject.testPropgation();
+
+                // remove the bean
+                encStatefulObject.remove();
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void testPropgation() throws TestFailureException {
+        if (inheritedDelegate == null) return;
+        try {
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                EntityManager delegate = (EntityManager) em.getDelegate();
+                Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                        inheritedDelegate,
+                        delegate);
             } catch (Exception e){
                 Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
             }

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulPojoBean.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulPojoBean.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulPojoBean.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/ContextLookupStatefulPojoBean.java Fri Jan 12 18:25:48 2007
@@ -22,27 +22,28 @@
 import org.apache.openejb.test.entity.bmp.BasicBmpHome;
 import org.apache.openejb.test.entity.bmp.BasicBmpObject;
 
-import javax.ejb.SessionSynchronization;
 import javax.ejb.SessionContext;
-import javax.ejb.EJBException;
 import javax.sql.DataSource;
 import javax.naming.InitialContext;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityManager;
+import javax.transaction.UserTransaction;
 
 import junit.framework.Assert;
 import junit.framework.AssertionFailedError;
 
-import java.rmi.RemoteException;
-
 /**
  * @author <a href="mailto:david.blevins@visi.com">David Blevins</a>
  * @author <a href="mailto:Richard@Monson-Haefel.com">Richard Monson-Haefel</a>
  */
 public class ContextLookupStatefulPojoBean {
 
+    private EntityManager extendedEntityManager;
     private SessionContext ejbContext;
 
+    // Used for testing propigation
+    private static EntityManager inheritedDelegate;
+
     public void lookupEntityBean() throws TestFailureException {
         try {
             try {
@@ -291,6 +292,118 @@
             throw new TestFailureException(afe);
         }
     }
+
+    public void lookupExtendedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                if (extendedEntityManager != null) {
+                    Assert.assertSame("Extended entity manager should be the same instance that was found last time",
+                            extendedEntityManager,
+                            em);
+                    Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                            extendedEntityManager.getDelegate(),
+                            em.getDelegate());
+                }
+                extendedEntityManager = em;
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void lookupPropagatedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                // get the raw entity manager so we can test it below
+                inheritedDelegate = (EntityManager) em.getDelegate();
+
+                // The extended entity manager is not propigated to a non-extended entity manager unless there is a transaction
+                EntityManager nonExtendedEm = (EntityManager)ctx.lookup("java:comp/env/persistence/TestContext");
+                nonExtendedEm.getFlushMode();
+                EntityManager nonExtendedDelegate = ((EntityManager) nonExtendedEm.getDelegate());
+                Assert.assertTrue("non-extended entity manager should be open", nonExtendedDelegate.isOpen());
+                Assert.assertNotSame("Extended non-extended entity manager shound not be the same instance as extendend entity manager when accessed out side of a transactions",
+                        inheritedDelegate,
+                        nonExtendedDelegate);
+
+                // When the non-extended entity manager is accessed within a transaction is should see the stateful extended context.
+                //
+                // Note: this code also tests EBJ 3.0 Persistence spec 5.9.1 "UserTransaction is begun within the method, the
+                // container associates the persistence context with the JTA transaction and calls EntityManager.joinTransaction."
+                // If our the extended entity manager were not associted with the transaction, the non-extended entity manager would
+                // not see it.
+                UserTransaction userTransaction = ejbContext.getUserTransaction();
+                userTransaction.begin();
+                try {
+                    Assert.assertSame("Extended non-extended entity manager to be same instance as extendend entity manager",
+                            inheritedDelegate,
+                            nonExtendedEm.getDelegate());
+                } finally {
+                    userTransaction.commit();
+                }
+
+                // When a stateful bean with an extended entity manager creates another stateful bean, the new bean will
+                // inherit the extended entity manager (assuming it contains an extended entity manager for the same persistence
+                // unit).
+                EncStatefulHome home = (EncStatefulHome) ejbContext.getEJBHome();
+                EncStatefulObject encStatefulObject = home.create("PropagatedPersistenceContext");
+
+                // test the new stateful bean recieved the context
+                encStatefulObject.testPropgation();
+
+                // remove the bean
+                encStatefulObject.remove();
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void testPropgation() throws TestFailureException {
+        if (inheritedDelegate == null) return;
+        try {
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                EntityManager delegate = (EntityManager) em.getDelegate();
+                Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                        inheritedDelegate,
+                        delegate);
+            } catch (Exception e){
+                e.printStackTrace();
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
 
     /**
      * Set the associated session context. The container calls this method

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulBean.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulBean.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulBean.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulBean.java Fri Jan 12 18:25:48 2007
@@ -21,10 +21,12 @@
 import javax.ejb.EJBException;
 import javax.ejb.SessionContext;
 import javax.ejb.SessionSynchronization;
+import javax.ejb.CreateException;
 import javax.naming.InitialContext;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityManager;
 import javax.sql.DataSource;
+import javax.transaction.UserTransaction;
 
 import junit.framework.Assert;
 import junit.framework.AssertionFailedError;
@@ -45,8 +47,11 @@
     
     private String name;
     private SessionContext ejbContext;
-    
-    
+    private EntityManager extendedEntityManager;
+
+    // Used for testing propigation
+    private static EntityManager inheritedDelegate;
+
     //=============================
     // Home interface methods
     //    
@@ -57,8 +62,7 @@
      * @exception javax.ejb.CreateException
      * @see EncStatefulHome#create
      */
-    public void ejbCreate(String name)
-    throws javax.ejb.CreateException{
+    public void ejbCreate(String name) throws CreateException{
         this.name = name;
     }
     //    
@@ -350,6 +354,126 @@
                 // call a do nothing method to assure entity manager actually exists
                 em.getFlushMode();
             } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void lookupExtendedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                if (extendedEntityManager != null) {
+                    Assert.assertSame("Extended entity manager should be the same instance that was found last time",
+                            extendedEntityManager,
+                            em);
+                    Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                            extendedEntityManager.getDelegate(),
+                            em.getDelegate());
+                }
+                extendedEntityManager = em;
+
+                UserTransaction userTransaction = ejbContext.getUserTransaction();
+                userTransaction.begin();
+                try {
+                    em.getFlushMode();
+                } finally {
+                    userTransaction.commit();
+                }
+            } catch (Exception e){
+                e.printStackTrace();
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void lookupPropagatedPersistenceContext() throws TestFailureException{
+        try{
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                // get the raw entity manager so we can test it below
+                inheritedDelegate = (EntityManager) em.getDelegate();
+
+                // The extended entity manager is not propigated to a non-extended entity manager unless there is a transaction
+                EntityManager nonExtendedEm = (EntityManager)ctx.lookup("java:comp/env/persistence/TestContext");
+                nonExtendedEm.getFlushMode();
+                EntityManager nonExtendedDelegate = ((EntityManager) nonExtendedEm.getDelegate());
+                Assert.assertTrue("non-extended entity manager should be open", nonExtendedDelegate.isOpen());
+                Assert.assertNotSame("Extended non-extended entity manager shound not be the same instance as extendend entity manager when accessed out side of a transactions",
+                        inheritedDelegate,
+                        nonExtendedDelegate);
+
+                // When the non-extended entity manager is accessed within a transaction is should see the stateful extended context.
+                //
+                // Note: this code also tests EBJ 3.0 Persistence spec 5.9.1 "UserTransaction is begun within the method, the
+                // container associates the persistence context with the JTA transaction and calls EntityManager.joinTransaction."
+                // If our the extended entity manager were not associted with the transaction, the non-extended entity manager would
+                // not see it.
+                UserTransaction userTransaction = ejbContext.getUserTransaction();
+                userTransaction.begin();
+                try {
+                    Assert.assertSame("Extended non-extended entity manager to be same instance as extendend entity manager",
+                            inheritedDelegate,
+                            nonExtendedEm.getDelegate());
+                } finally {
+                    userTransaction.commit();
+                }
+
+                // When a stateful bean with an extended entity manager creates another stateful bean, the new bean will
+                // inherit the extended entity manager (assuming it contains an extended entity manager for the same persistence
+                // unit).
+                EncStatefulHome home = (EncStatefulHome) ejbContext.getEJBHome();
+                EncStatefulObject encStatefulObject = home.create("PropagatedPersistenceContext");
+
+                // test the new stateful bean recieved the context
+                encStatefulObject.testPropgation();
+
+                // remove the bean
+                encStatefulObject.remove();
+            } catch (Exception e){
+                Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+            }
+        } catch (AssertionFailedError afe){
+            throw new TestFailureException(afe);
+        }
+    }
+
+    public void testPropgation() throws TestFailureException {
+        if (inheritedDelegate == null) return;
+        try {
+            try{
+                InitialContext ctx = new InitialContext();
+                Assert.assertNotNull("The InitialContext is null", ctx);
+                EntityManager em = (EntityManager)ctx.lookup("java:comp/env/persistence/ExtendedTestContext");
+                Assert.assertNotNull("The EntityManager is null", em);
+
+                // call a do nothing method to assure entity manager actually exists
+                em.getFlushMode();
+
+                EntityManager delegate = (EntityManager) em.getDelegate();
+                Assert.assertSame("Extended entity manager delegate should be the same instance that was found last time",
+                        inheritedDelegate,
+                        delegate);
+            } catch (Exception e){
+                e.printStackTrace();
                 Assert.fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
             }
         } catch (AssertionFailedError afe){

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulObject.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulObject.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulObject.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/java/org/apache/openejb/test/stateful/EncStatefulObject.java Fri Jan 12 18:25:48 2007
@@ -34,6 +34,9 @@
     public void lookupResource() throws TestFailureException, RemoteException;
     public void lookupPersistenceUnit() throws TestFailureException, RemoteException;
     public void lookupPersistenceContext() throws TestFailureException, RemoteException;
+    public void lookupExtendedPersistenceContext() throws TestFailureException, RemoteException;
+    public void lookupPropagatedPersistenceContext() throws TestFailureException, RemoteException;
+    public void testPropgation() throws TestFailureException, RemoteException;
 
     public void lookupStringEntry()  throws TestFailureException, RemoteException;
     public void lookupDoubleEntry()  throws TestFailureException, RemoteException;

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/resources/META-INF/ejb-jar.xml
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/resources/META-INF/ejb-jar.xml?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/resources/META-INF/ejb-jar.xml (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-beans/src/main/resources/META-INF/ejb-jar.xml Fri Jan 12 18:25:48 2007
@@ -961,7 +961,6 @@
         <persistence-context-ref-name>persistence/TestContext</persistence-context-ref-name>
         <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
       </persistence-context-ref>
-
     </session>
 
     <!--
@@ -1069,6 +1068,14 @@
         <persistence-context-ref-name>persistence/TestContext</persistence-context-ref-name>
         <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
       </persistence-context-ref>
+      <persistence-context-ref>
+        <description>
+          Persistence context for testing the functionality.
+        </description>
+        <persistence-context-ref-name>persistence/ExtendedTestContext</persistence-context-ref-name>
+        <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
+        <persistence-context-type>Extended</persistence-context-type>
+      </persistence-context-ref>
     </session>
 
     <!--
@@ -1176,6 +1183,14 @@
         <persistence-context-ref-name>persistence/TestContext</persistence-context-ref-name>
         <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
       </persistence-context-ref>
+      <persistence-context-ref>
+        <description>
+          Persistence context for testing the functionality.
+        </description>
+        <persistence-context-ref-name>persistence/ExtendedTestContext</persistence-context-ref-name>
+        <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
+        <persistence-context-type>Extended</persistence-context-type>
+      </persistence-context-ref>
     </session>
 
     <!--
@@ -1282,6 +1297,14 @@
         </description>
         <persistence-context-ref-name>persistence/TestContext</persistence-context-ref-name>
         <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
+      </persistence-context-ref>
+      <persistence-context-ref>
+        <description>
+          Persistence context for testing the functionality.
+        </description>
+        <persistence-context-ref-name>persistence/ExtendedTestContext</persistence-context-ref-name>
+        <persistence-unit-name>openjpa-test-unit</persistence-unit-name>
+        <persistence-context-type>Extended</persistence-context-type>
       </persistence-context-ref>
     </session>
 

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulContextLookupTests.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulContextLookupTests.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulContextLookupTests.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulContextLookupTests.java Fri Jan 12 18:25:48 2007
@@ -209,4 +209,27 @@
         }
     }
 
+    public void test16_lookupExtendedPersistenceContext() {
+        try{
+            ejbObject.lookupExtendedPersistenceContext();
+
+            // call again to assure extended persistence context instance is the same
+            ejbObject.lookupExtendedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
+    public void test17_lookupPropagatedPersistenceContext() {
+        try{
+            ejbObject.lookupPropagatedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
 }

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulJndiEncTests.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulJndiEncTests.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulJndiEncTests.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulJndiEncTests.java Fri Jan 12 18:25:48 2007
@@ -209,4 +209,27 @@
         }
     }
 
+    public void test16_lookupExtendedPersistenceContext() {
+        try{
+            ejbObject.lookupExtendedPersistenceContext();
+
+            // call again to assure extended persistence context instance is the same
+            ejbObject.lookupExtendedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
+    public void test17_lookupPropagatedPersistenceContext() {
+        try{
+            ejbObject.lookupPropagatedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
 }

Modified: incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulPojoContextLookupTests.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulPojoContextLookupTests.java?view=diff&rev=495820&r1=495819&r2=495820
==============================================================================
--- incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulPojoContextLookupTests.java (original)
+++ incubator/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/stateful/StatefulPojoContextLookupTests.java Fri Jan 12 18:25:48 2007
@@ -209,4 +209,27 @@
         }
     }
 
+    public void test16_lookupExtendedPersistenceContext() {
+        try{
+            ejbObject.lookupExtendedPersistenceContext();
+
+            // call again to assure extended persistence context instance is the same
+            ejbObject.lookupExtendedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
+    public void test17_lookupPropagatedPersistenceContext() {
+        try{
+            ejbObject.lookupPropagatedPersistenceContext();
+        } catch (TestFailureException e){
+            throw e.error;
+        } catch (Exception e){
+            fail("Received Exception "+e.getClass()+ " : "+e.getMessage());
+        }
+    }
+
 }