Author: andygumbrecht Date: Fri Jan 4 16:36:36 2013 New Revision: 1428958 URL: http://svn.apache.org/viewvc?rev=1428958&view=rev Log: Possible fix and test for org.apache.openejb.core.stateful.StatefulContainer#releaseInstance - Should not throw an exception if a bean transaction exists, rather ignore the 'release'? Please review.
http://openejb.979440.n4.nabble.com/Possible-fix-and-test-for-org-apache-openejb-core-stateful-StatefulContainer-releaseInstance-td4660080.html Added: openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulBeanManagedTest.java - copied, changed from r1428761, openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTest.java Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/Instance.java openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSessionBeanTest.java Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/Instance.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/Instance.java?rev=1428958&r1=1428957&r2=1428958&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/Instance.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/Instance.java Fri Jan 4 16:36:36 2013 @@ -46,7 +46,7 @@ public class Instance implements Seriali private boolean inUse; private SuspendedTransaction beanTransaction; - private Stack<Transaction> transaction = new Stack<Transaction>(); + private final Stack<Transaction> transaction = new Stack<Transaction>(); private final ReentrantLock lock = new ReentrantLock(); // todo if we keyed by an entity manager factory id we would not have to make this transient and rebuild the index below @@ -55,7 +55,7 @@ public class Instance implements Seriali private Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> entityManagers; private final JtaEntityManagerRegistry.EntityManagerTracker[] entityManagerArray; - public Instance(BeanContext beanContext, Object primaryKey, Object bean, CreationalContext creationalContext, Map<String, Object> interceptors, Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> entityManagers) { + public Instance(final BeanContext beanContext, final Object primaryKey, final Object bean, final CreationalContext creationalContext, final Map<String, Object> interceptors, final Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> entityManagers) { this.beanContext = beanContext; this.primaryKey = primaryKey; this.bean = bean; @@ -65,7 +65,7 @@ public class Instance implements Seriali this.entityManagerArray = null; } - public Instance(Object deploymentId, Object primaryKey, Object bean, CreationalContext creationalContext, Map<String, Object> interceptors, JtaEntityManagerRegistry.EntityManagerTracker[] entityManagerArray) { + public Instance(final Object deploymentId, final Object primaryKey, final Object bean, final CreationalContext creationalContext, final Map<String, Object> interceptors, final JtaEntityManagerRegistry.EntityManagerTracker[] entityManagerArray) { this.beanContext = SystemInstance.get().getComponent(ContainerSystem.class).getBeanContext(deploymentId); if (beanContext == null) { throw new IllegalArgumentException("Unknown deployment " + deploymentId); @@ -77,6 +77,7 @@ public class Instance implements Seriali this.entityManagerArray = entityManagerArray; } + @Override public Duration getTimeOut() { return beanContext.getStatefulTimeout(); } @@ -85,7 +86,7 @@ public class Instance implements Seriali return inUse; } - public synchronized void setInUse(boolean inUse) { + public synchronized void setInUse(final boolean inUse) { this.inUse = inUse; } @@ -93,7 +94,7 @@ public class Instance implements Seriali return beanTransaction; } - public synchronized void setBeanTransaction(SuspendedTransaction beanTransaction) { + public synchronized void setBeanTransaction(final SuspendedTransaction beanTransaction) { this.beanTransaction = beanTransaction; } @@ -105,7 +106,7 @@ public class Instance implements Seriali return lock; } - public synchronized void setTransaction(Transaction transaction) { + public synchronized void setTransaction(final Transaction transaction) { if (this.transaction.size() == 0 && transaction != null) { lock.lock(); this.transaction.push(transaction); @@ -123,12 +124,12 @@ public class Instance implements Seriali } } - public synchronized Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> getEntityManagers(Index<EntityManagerFactory, Map> factories) { + public synchronized Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> getEntityManagers(final Index<EntityManagerFactory, Map> factories) { if (entityManagers == null && entityManagerArray != null) { entityManagers = new HashMap<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker>(); for (int i = 0; i < entityManagerArray.length; i++) { - EntityManagerFactory entityManagerFactory = factories.getKey(i); - JtaEntityManagerRegistry.EntityManagerTracker entityManager = entityManagerArray[i]; + final EntityManagerFactory entityManagerFactory = factories.getKey(i); + final JtaEntityManagerRegistry.EntityManagerTracker entityManager = entityManagerArray[i]; entityManagers.put(entityManagerFactory, entityManager); } } @@ -154,14 +155,14 @@ public class Instance implements Seriali public final Map<String, Object> interceptors; public final JtaEntityManagerRegistry.EntityManagerTracker[] entityManagerArray; - public Serialization(Instance i) { + public Serialization(final Instance i) { deploymentId = i.beanContext.getDeploymentID(); primaryKey = i.primaryKey; bean = toSerializable(i.bean); creationalContext = i.creationalContext; interceptors = new HashMap<String, Object>(i.interceptors.size()); - for (Map.Entry<String, Object> e : i.interceptors.entrySet()) { + for (final Map.Entry<String, Object> e : i.interceptors.entrySet()) { if (e.getValue() == i.bean) { // need to use the same wrapped reference or well get two copies. interceptors.put(e.getKey(), bean); @@ -179,7 +180,7 @@ public class Instance implements Seriali } } - private static Object toSerializable(Object obj) { + private static Object toSerializable(final Object obj) { if (obj instanceof Serializable) { return obj; } else { Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java?rev=1428958&r1=1428957&r2=1428958&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java Fri Jan 4 16:36:36 2013 @@ -781,18 +781,14 @@ public class StatefulContainer implement private void releaseInstance(final Instance instance) { // Don't pool if the bean has been undeployed - if (instance.beanContext.isDestroyed()) + if (instance.beanContext.isDestroyed()) { return; - - // verify the instance is not associated with a bean-managed transaction - if (instance.getBeanTransaction() != null) { - throw new IllegalStateException("Instance has an active bean-managed transaction"); } // no longer in use instance.setInUse(false); - if (instance.getTransaction() == null && !containsExtendedPersistenceContext(instance.beanContext)) { + if (instance.getTransaction() == null && !containsExtendedPersistenceContext(instance.beanContext) && null == instance.getBeanTransaction()) { synchronized (instance.primaryKey) { // return to cache cache.checkIn(instance.primaryKey); Copied: openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulBeanManagedTest.java (from r1428761, openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTest.java) URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulBeanManagedTest.java?p2=openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulBeanManagedTest.java&p1=openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTest.java&r1=1428761&r2=1428958&rev=1428958&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTest.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulBeanManagedTest.java Fri Jan 4 16:36:36 2013 @@ -16,18 +16,32 @@ */ package org.apache.openejb.core.stateful; -import javax.ejb.LocalBean; -import javax.ejb.Stateful; -import javax.naming.InitialContext; - -import junit.framework.TestCase; import org.apache.openejb.assembler.classic.Assembler; import org.apache.openejb.assembler.classic.SecurityServiceInfo; import org.apache.openejb.assembler.classic.TransactionServiceInfo; -import org.apache.openejb.core.LocalInitialContextFactory; import org.apache.openejb.config.ConfigurationFactory; +import org.apache.openejb.core.LocalInitialContextFactory; import org.apache.openejb.jee.EjbJar; import org.apache.openejb.jee.StatefulBean; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.annotation.Resource; +import javax.ejb.LocalBean; +import javax.ejb.Remove; +import javax.ejb.Stateful; +import javax.ejb.TransactionManagement; +import javax.ejb.TransactionManagementType; +import javax.naming.InitialContext; +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.UserTransaction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; /** * This test case serves as a nice tiny template for other test cases @@ -35,40 +49,78 @@ import org.apache.openejb.jee.StatefulBe * * @version $Rev$ $Date$ */ -public class StatefulTest extends TestCase { +public class StatefulBeanManagedTest { - @Override - protected void setUp() throws Exception { + @BeforeClass + public static void beforeClass() throws Exception { System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName()); - ConfigurationFactory config = new ConfigurationFactory(); - Assembler assembler = new Assembler(); + final ConfigurationFactory config = new ConfigurationFactory(); + final Assembler assembler = new Assembler(); assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class)); assembler.createSecurityService(config.configureService(SecurityServiceInfo.class)); - EjbJar ejbJar = new EjbJar(); + final EjbJar ejbJar = new EjbJar(); ejbJar.addEnterpriseBean(new StatefulBean(MyBean.class)); assembler.createApplication(config.configureApplication(ejbJar)); } - public void test() throws Exception { - InitialContext context = new InitialContext(); - MyBean myBean = (MyBean) context.lookup("MyBeanLocalBean"); + @Test + public void testExpected() throws Exception { + final MyBean beanOne = (MyBean) new InitialContext().lookup("MyBeanLocalBean"); + + beanOne.one("bob"); + assertEquals("bob", beanOne.two()); + beanOne.three(); + + beanOne.one("sally"); + assertEquals("sally", beanOne.two()); + beanOne.three(); - assertEquals("pan", myBean.echo("nap")); + final MyBean beanTwo = (MyBean) new InitialContext().lookup("MyBeanLocalBean"); + + assertNull(beanTwo.two()); } + @Test(expected = javax.transaction.NotSupportedException.class) + public void testUnexpected() throws Exception { + + final MyBean beanOne = (MyBean) new InitialContext().lookup("MyBeanLocalBean"); + + final String bob = "bob"; + + beanOne.one("bob"); + assertEquals("bob", beanOne.two()); + + beanOne.one("sally"); + } @Stateful @LocalBean + @TransactionManagement(TransactionManagementType.BEAN) public static class MyBean { - public String echo(String string) { - StringBuilder sb = new StringBuilder(string); - return sb.reverse().toString(); + String string; + + @Resource + private UserTransaction transaction; + + public void one(final String string) throws SystemException, NotSupportedException { + this.transaction.begin(); + this.string = string; + } + + public String two() throws SystemException, NotSupportedException { + return this.string; + } + + @Remove + public void three() throws HeuristicRollbackException, HeuristicMixedException, RollbackException, SystemException { + this.string = null; + this.transaction.commit(); } } } Modified: openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSessionBeanTest.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSessionBeanTest.java?rev=1428958&r1=1428957&r2=1428958&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSessionBeanTest.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSessionBeanTest.java Fri Jan 4 16:36:36 2013 @@ -48,15 +48,15 @@ public class StatefulSessionBeanTest ext public void test() throws Exception { System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName()); - ConfigurationFactory config = new ConfigurationFactory(); - Assembler assembler = new Assembler(); + final ConfigurationFactory config = new ConfigurationFactory(); + final Assembler assembler = new Assembler(); assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class)); assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class)); assembler.createSecurityService(config.configureService(SecurityServiceInfo.class)); // containers - StatefulSessionContainerInfo statefulContainerInfo = config.configureService(StatefulSessionContainerInfo.class); + final StatefulSessionContainerInfo statefulContainerInfo = config.configureService(StatefulSessionContainerInfo.class); statefulContainerInfo.properties.setProperty("PoolSize", "0"); statefulContainerInfo.properties.setProperty("BulkPassivate", "1"); statefulContainerInfo.properties.setProperty("Frequency", "0"); @@ -66,14 +66,14 @@ public class StatefulSessionBeanTest ext StatefulSessionBeanTest.calls.clear(); - InitialContext ctx = new InitialContext(); - TargetHome home = (TargetHome) ctx.lookup("TargetBeanRemoteHome"); + final InitialContext ctx = new InitialContext(); + final TargetHome home = (TargetHome) ctx.lookup("TargetBeanRemoteHome"); assertNotNull(home); - Target target = home.create("Fuzz"); + final Target target = home.create("Fuzz"); assertNotNull(target); - String name = target.getName(); + final String name = target.getName(); assertEquals("Fuzz", name); target.remove(); @@ -82,15 +82,15 @@ public class StatefulSessionBeanTest ext } - private void assertCalls(Call... expectedCalls) { - List expected = Arrays.asList(expectedCalls); + private void assertCalls(final Call... expectedCalls) { + final List expected = Arrays.asList(expectedCalls); assertEquals(StatefulSessionBeanTest.join("\n", expected), StatefulSessionBeanTest.join("\n", StatefulSessionBeanTest.calls)); } public EjbModule buildTestApp() { - EjbJar ejbJar = new EjbJar(); + final EjbJar ejbJar = new EjbJar(); - StatefulBean bean = ejbJar.addEnterpriseBean(new StatefulBean(StatefulSessionBeanTest.TargetBean.class)); + final StatefulBean bean = ejbJar.addEnterpriseBean(new StatefulBean(StatefulSessionBeanTest.TargetBean.class)); bean.setHomeAndRemote(TargetHome.class, Target.class); return new EjbModule(this.getClass().getClassLoader(), this.getClass().getSimpleName(), "test", ejbJar, null); @@ -118,11 +118,12 @@ public class StatefulSessionBeanTest ext calls.add(Call.Constructor); } - public void setSessionContext(SessionContext sessionContext){ + @Override + public void setSessionContext(final SessionContext sessionContext){ calls.add(Call.SetSessionContext); } - public void ejbCreate(String name) throws CreateException { + public void ejbCreate(final String name) throws CreateException { calls.add(Call.EjbCreate); this.name = name; } @@ -132,14 +133,17 @@ public class StatefulSessionBeanTest ext return name; } + @Override public void ejbActivate() throws EJBException, RemoteException { calls.add(Enum.valueOf(Call.class, "EjbActivate" + (++activates))); } + @Override public void ejbPassivate() throws EJBException, RemoteException { calls.add(Enum.valueOf(Call.class, "EjbPassivate" + (++passivates))); } + @Override public void ejbRemove() throws EJBException, RemoteException { calls.add(Call.EjbRemove); } @@ -153,9 +157,9 @@ public class StatefulSessionBeanTest ext String getName(); } - private static String join(String delimeter, List items) { - StringBuffer sb = new StringBuffer(); - for (Object item : items) { + private static String join(final String delimeter, final List items) { + final StringBuffer sb = new StringBuffer(); + for (final Object item : items) { sb.append(item.toString()).append(delimeter); } return sb.toString();
