Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=688602&r1=688601&r2=688602&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
 Sun Aug 24 19:39:06 2008
@@ -61,7 +61,7 @@
           id="Default BMP Container"
           service="Container"
           types="BMP_ENTITY"
-          constructor="id, transactionManager, securityService, PoolSize"
+          constructor="id, securityService, PoolSize"
           class-name="org.apache.openejb.core.entity.EntityContainer">
 
     # Specifies the size of the bean pools for this
@@ -82,7 +82,7 @@
           id="Default Stateless Container"
           service="Container"
           types="STATELESS"
-          constructor="id, transactionManager, securityService, TimeOut, 
PoolSize, StrictPooling"
+          constructor="id, securityService, TimeOut, PoolSize, StrictPooling"
           class-name="org.apache.openejb.core.stateless.StatelessContainer">
 
     # Specifies the time to wait between invocations. This
@@ -124,7 +124,7 @@
           id="Default Singleton Container"
           service="Container"
           types="SINGLETON"
-          constructor="id, transactionManager, securityService"
+          constructor="id, securityService"
           class-name="org.apache.openejb.core.singleton.SingletonContainer">
 
     AccessTimeout = 30 seconds
@@ -141,7 +141,7 @@
           id="Default Stateful Container"
           service="Container"
           types="STATEFUL"
-          constructor="id, transactionManager, securityService, Passivator, 
TimeOut, PoolSize, BulkPassivate"
+          constructor="id, securityService, Passivator, TimeOut, PoolSize, 
BulkPassivate"
           class-name="org.apache.openejb.core.stateful.StatefulContainer">
 
     # The passivator is responsible for writing beans to disk
@@ -186,7 +186,7 @@
           id="Default MDB Container"
           service="Container"
           types="MESSAGE"
-          constructor="id, transactionManager, securityService, 
ResourceAdapter, MessageListenerInterface, ActivationSpecClass, InstanceLimit"
+          constructor="id, securityService, ResourceAdapter, 
MessageListenerInterface, ActivationSpecClass, InstanceLimit"
           class-name="org.apache.openejb.core.mdb.MdbContainer">
 
     # The resource adapter delivers messages to the container

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulContainerTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulContainerTest.java?rev=688602&r1=688601&r2=688602&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulContainerTest.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulContainerTest.java
 Sun Aug 24 19:39:06 2008
@@ -17,17 +17,11 @@
  */
 package org.apache.openejb.core.stateful;
 
-import junit.framework.TestCase;
-import org.apache.openejb.assembler.classic.Assembler;
-import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
-import org.apache.openejb.assembler.classic.SecurityServiceInfo;
-import org.apache.openejb.assembler.classic.StatefulSessionContainerInfo;
-import org.apache.openejb.assembler.classic.TransactionServiceInfo;
-import org.apache.openejb.config.ConfigurationFactory;
-import org.apache.openejb.core.ivm.naming.InitContextFactory;
-import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.jee.StatefulBean;
-
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Stack;
+import java.util.ArrayList;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.annotation.Resource;
@@ -38,18 +32,42 @@
 import javax.ejb.Remove;
 import javax.ejb.SessionContext;
 import javax.naming.InitialContext;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Stack;
-import java.util.ArrayList;
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.StatefulSessionContainerInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.core.ivm.naming.InitContextFactory;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatefulBean;
+import org.apache.openejb.loader.SystemInstance;
 
 /**
  * @version $Revision$ $Date$
  */
 public class StatefulContainerTest extends TestCase {
+    private List<Lifecycle> inTxExpectedLifecycle;
+    private List expectedLifecycle;
 
     public void testBusinessLocalInterface() throws Exception {
+        testBusinessLocalInterface(expectedLifecycle);
+    }
+
+    public void testBusinessRemoteInterfaceInTx() throws Exception {
+        TransactionManager transactionManager = 
SystemInstance.get().getComponent(TransactionManager.class);
+        transactionManager.begin();
+        try {
+            testBusinessRemoteInterface(inTxExpectedLifecycle);
+        } finally {
+            transactionManager.commit();
+        }
+    }
+
+    protected void testBusinessLocalInterface(List expectedLifecycle) throws 
Exception {
 
         // Do a create...
 
@@ -61,19 +79,42 @@
         Widget widget = (Widget) object;
 
         // Do a business method...
-        Stack<Lifecycle> lifecycle = widget.getLifecycle();
-        assertNotNull("lifecycle",lifecycle);
+        Stack<Object> actual = widget.getLifecycle();
+        assertNotNull("lifecycle", actual);
+
+        // test app exception
+        try {
+            widget.throwAppException();
+            fail("Expected application exception");
+        } catch (SQLException e) {
+            assertEquals("test", e.getMessage());
+        }
+
+        // Do another business method...
+        widget.afterAppException();
 
         // Do a remove...
         widget.destroy();
 
         // Check the lifecycle of the bean
-        List expected = 
Arrays.asList(StatefulContainerTest.Lifecycle.values());
-
-        assertEquals(StatefulContainerTest.join("\n", expected) , join("\n", 
WidgetBean.lifecycle));
+        assertEquals(StatefulContainerTest.join("\n", expectedLifecycle) , 
join("\n", WidgetBean.lifecycle));
     }
 
     public void testBusinessRemoteInterface() throws Exception {
+        testBusinessRemoteInterface(expectedLifecycle);
+    }
+
+    public void testBusinessLocalInterfaceInTx() throws Exception {
+        TransactionManager transactionManager = 
SystemInstance.get().getComponent(TransactionManager.class);
+        transactionManager.begin();
+        try {
+            testBusinessLocalInterface(inTxExpectedLifecycle);
+        } finally {
+            transactionManager.commit();
+        }
+    }
+
+    protected void testBusinessRemoteInterface(List expectedLifecycle) throws 
Exception {
         WidgetBean.lifecycle.clear();
 
         // Do a create...
@@ -86,10 +127,21 @@
         RemoteWidget widget = (RemoteWidget) object;
 
         // Do a business method...
-        Stack<Lifecycle> lifecycle = widget.getLifecycle();
+        Stack<Object> lifecycle = widget.getLifecycle();
         assertNotNull("lifecycle",lifecycle);
         assertNotSame("is copy", lifecycle, WidgetBean.lifecycle);
 
+        // test app exception
+        try {
+            widget.throwAppException();
+            fail("Expected application exception");
+        } catch (SQLException e) {
+            assertEquals("test", e.getMessage());
+        }
+
+        // Do another business method...
+        widget.afterAppException();
+
         // Do a remove...
         widget.destroy();
 
@@ -100,9 +152,7 @@
         }
 
         // Check the lifecycle of the bean
-        List expected = 
Arrays.asList(StatefulContainerTest.Lifecycle.values());
-
-        assertEquals(StatefulContainerTest.join("\n", expected) , join("\n", 
WidgetBean.lifecycle));
+        assertEquals(StatefulContainerTest.join("\n", expectedLifecycle) , 
join("\n", WidgetBean.lifecycle));
     }
 
     protected void setUp() throws Exception {
@@ -132,6 +182,14 @@
 
         WidgetBean.lifecycle.clear();
 
+        expectedLifecycle = Arrays.asList(Lifecycle.values());
+        inTxExpectedLifecycle = new ArrayList<Lifecycle>();
+        for (Lifecycle lifecycle : Lifecycle.values()) {
+            if (!lifecycle.name().startsWith("PRE_PASSIVATE") &&
+                    !lifecycle.name().startsWith("POST_ACTIVATE")) {
+                inTxExpectedLifecycle.add(lifecycle);
+            }
+        }
     }
 
     private static String join(String delimeter, List items){
@@ -144,7 +202,9 @@
 
     @Local
     public static interface Widget {
-        Stack<Lifecycle> getLifecycle();
+        Stack<Object> getLifecycle();
+        void throwAppException() throws SQLException;
+        void afterAppException();
         void destroy();
     }
 
@@ -154,39 +214,63 @@
     }
 
     public static enum Lifecycle {
-        CONSTRUCTOR, INJECTION, POST_CONSTRUCT, PRE_PASSIVATE1, 
POST_ACTIVATE1, BUSINESS_METHOD, PRE_PASSIVATE2, POST_ACTIVATE2,REMOVE, 
PRE_DESTROY,
+        // construction
+        CONSTRUCTOR, INJECTION, POST_CONSTRUCT, PRE_PASSIVATE1,
+        // business method
+        POST_ACTIVATE1, BUSINESS_METHOD, PRE_PASSIVATE2,
+        // throw app exception
+        POST_ACTIVATE2, PRE_PASSIVATE3,
+        // business method after app exception
+        POST_ACTIVATE3, PRE_PASSIVATE4,
+        // remove
+        POST_ACTIVATE4, REMOVE, PRE_DESTROY,
     }
 
     public static class WidgetBean implements Widget, RemoteWidget {
-        private static final long serialVersionUID = -8499745487520955081L;
-
         private int activates = 0;
         private int passivates = 0;
 
-        public static Stack<Lifecycle> lifecycle = new Stack<Lifecycle>();
+        public static Stack<Object> lifecycle = new Stack<Object>();
 
         public WidgetBean() {
             lifecycle.push(Lifecycle.CONSTRUCTOR);
         }
 
+        public void throwAppException() throws SQLException {
+            throw new SQLException("test");
+        }
+
+        public void afterAppException() {
+        }
+
         @Resource
         public void setContext(SessionContext context){
             lifecycle.push(Lifecycle.INJECTION);
         }
 
-        public Stack<Lifecycle> getLifecycle() {
+        public Stack<Object> getLifecycle() {
             lifecycle.push(Lifecycle.BUSINESS_METHOD);
             return lifecycle;
         }
 
         @PostActivate
         public void activate(){
-            lifecycle.push(Enum.valueOf(Lifecycle.class, "POST_ACTIVATE" + 
(++activates)));
+            String name = "POST_ACTIVATE" + (++activates);
+            try {
+                lifecycle.push(Enum.valueOf(Lifecycle.class, name));
+            } catch (Exception e) {
+                lifecycle.push(name);
+            }
         }
 
         @PrePassivate
         public void passivate(){
-            lifecycle.push(Enum.valueOf(Lifecycle.class, "PRE_PASSIVATE" + 
(++passivates)));
+            String name = "PRE_PASSIVATE" + (++passivates);
+            try {
+                lifecycle.push(Enum.valueOf(Lifecycle.class, name));
+            } catch (Exception e) {
+                lifecycle.push(name);
+            }
         }
 
         @PostConstruct

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java?rev=688602&r1=688601&r2=688602&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulSecurityPermissionsTest.java
 Sun Aug 24 19:39:06 2008
@@ -16,63 +16,54 @@
  */
 package org.apache.openejb.core.stateful;
 
+import java.rmi.RemoteException;
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.CreateException;
+import javax.ejb.EJBAccessException;
+import javax.ejb.EJBHome;
+import javax.ejb.EJBLocalHome;
+import javax.ejb.EJBLocalObject;
+import javax.ejb.EJBObject;
+import javax.ejb.Init;
+import javax.ejb.Local;
+import javax.ejb.LocalHome;
+import javax.ejb.Remote;
+import javax.ejb.RemoteHome;
+import javax.ejb.Remove;
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
 import junit.framework.TestCase;
-import org.apache.openejb.core.ivm.naming.InitContextFactory;
-import org.apache.openejb.core.ThreadContext;
-import org.apache.openejb.core.security.jacc.BasicJaccProvider;
-import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration;
-import org.apache.openejb.core.security.AbstractSecurityService;
-import org.apache.openejb.core.security.jaas.UserPrincipal;
-import org.apache.openejb.core.security.jaas.GroupPrincipal;
-import org.apache.openejb.core.transaction.TransactionPolicy;
 import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.EjbJarInfo;
 import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
-import org.apache.openejb.assembler.classic.TransactionServiceInfo;
 import org.apache.openejb.assembler.classic.SecurityServiceInfo;
-import org.apache.openejb.assembler.classic.EjbJarInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
 import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.core.ivm.naming.InitContextFactory;
+import org.apache.openejb.core.security.AbstractSecurityService;
+import org.apache.openejb.core.security.jaas.GroupPrincipal;
+import org.apache.openejb.core.security.jaas.UserPrincipal;
+import org.apache.openejb.core.security.jacc.BasicJaccProvider;
+import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration;
 import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.jee.StatefulBean;
-import org.apache.openejb.jee.ContainerTransaction;
-import org.apache.openejb.jee.TransAttribute;
-import org.apache.openejb.jee.MethodIntf;
 import org.apache.openejb.jee.MethodPermission;
+import org.apache.openejb.jee.StatefulBean;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.SecurityService;
 
-import javax.naming.InitialContext;
-import javax.ejb.LocalHome;
-import javax.ejb.RemoteHome;
-import javax.ejb.TransactionAttribute;
-import javax.ejb.TransactionAttributeType;
-import javax.ejb.Init;
-import javax.ejb.Remove;
-import javax.ejb.Local;
-import javax.ejb.Remote;
-import javax.ejb.EJBHome;
-import javax.ejb.CreateException;
-import javax.ejb.EJBObject;
-import javax.ejb.EJBLocalHome;
-import javax.ejb.EJBLocalObject;
-import javax.ejb.EJBAccessException;
-import javax.annotation.security.RolesAllowed;
-import javax.annotation.security.PermitAll;
-import javax.annotation.security.DenyAll;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.Subject;
-import javax.security.jacc.PolicyContextException;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.HashSet;
-import java.util.Collections;
-import java.rmi.RemoteException;
-import java.security.ProtectionDomain;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.Permissions;
-import java.security.PermissionCollection;
-
 /**
  * @version $Rev$ $Date$
  */

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTransactionAttributesTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTransactionAttributesTest.java?rev=688602&r1=688601&r2=688602&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTransactionAttributesTest.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulTransactionAttributesTest.java
 Sun Aug 24 19:39:06 2008
@@ -19,17 +19,14 @@
 import junit.framework.TestCase;
 import org.apache.openejb.assembler.classic.Assembler;
 import org.apache.openejb.assembler.classic.EjbJarInfo;
-import org.apache.openejb.assembler.classic.MethodAttributeInfo;
 import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
 import org.apache.openejb.assembler.classic.SecurityServiceInfo;
 import org.apache.openejb.assembler.classic.TransactionServiceInfo;
 import org.apache.openejb.config.ConfigurationFactory;
 import org.apache.openejb.core.ThreadContext;
-import org.apache.openejb.core.transaction.TransactionPolicy;
 import org.apache.openejb.core.ivm.naming.InitContextFactory;
 import org.apache.openejb.jee.ContainerTransaction;
 import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.jee.StatelessBean;
 import org.apache.openejb.jee.TransAttribute;
 import org.apache.openejb.jee.MethodIntf;
 import org.apache.openejb.jee.StatefulBean;
@@ -48,10 +45,8 @@
 import javax.ejb.Init;
 import javax.ejb.Remove;
 import javax.naming.InitialContext;
-import java.lang.reflect.Method;
 import java.rmi.RemoteException;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @version $Rev$ $Date$
@@ -326,7 +321,7 @@
 
         public String attribute() {
             ThreadContext context = ThreadContext.getThreadContext();
-            return context.get(TransactionPolicy.Type.class).toString();
+            return context.getTransactionPolicy().toString();
         }
 
         @Init

Added: 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringBeanTransactionPolicy.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringBeanTransactionPolicy.java?rev=688602&view=auto
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringBeanTransactionPolicy.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringBeanTransactionPolicy.java
 Sun Aug 24 19:39:06 2008
@@ -0,0 +1,245 @@
+/**
+ *
+ * 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.spring;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.UserTransaction;
+import static javax.transaction.Status.STATUS_NO_TRANSACTION;
+import static javax.transaction.Status.STATUS_MARKED_ROLLBACK;
+import static javax.transaction.Status.STATUS_ACTIVE;
+
+import org.apache.openejb.SystemException;
+import org.apache.openejb.core.transaction.BeanTransactionPolicy;
+import org.apache.openejb.core.transaction.TransactionType;
+import org.springframework.transaction.HeuristicCompletionException;
+import org.springframework.transaction.NestedTransactionNotSupportedException;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.UnexpectedRollbackException;
+import static 
org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+
+public class SpringBeanTransactionPolicy extends SpringTransactionPolicy 
implements BeanTransactionPolicy {
+    private final UserTransaction userTransaction;
+    private DefaultTransactionStatus beanTransaction;
+    private int timeout;
+
+    public SpringBeanTransactionPolicy(PlatformTransactionManager 
transactionManager) {
+        super(transactionManager, TransactionType.BeanManaged);
+        userTransaction = new SpringUserTransaction();
+    }
+
+    protected DefaultTransactionStatus getTransactionStatus() {
+        return beanTransaction != null ? beanTransaction : 
super.getTransactionStatus();
+    }
+
+    public SuspendedTransaction suspendUserTransaction() throws 
SystemException {
+        throw new SystemException(new 
UnsupportedOperationException("SpringTransactionPolicy does not support 
transaction suspension"));
+    }
+
+    public void resumeUserTransaction(SuspendedTransaction 
suspendedTransaction) throws SystemException {
+        throw new SystemException(new 
UnsupportedOperationException("SpringTransactionPolicy does not support 
transaction resumption"));
+    }
+
+    public UserTransaction getUserTransaction() {
+        if (getTransactionStatus().isCompleted()) {
+            throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+        }
+        return userTransaction;
+    }
+
+    private class SpringUserTransaction implements UserTransaction {
+        public int getStatus() {
+            if (getTransactionStatus().isCompleted() || beanTransaction == 
null) {
+                return STATUS_NO_TRANSACTION;
+            } else if (isRollbackOnly()) {
+                return STATUS_MARKED_ROLLBACK;
+            } else {
+                return STATUS_ACTIVE;
+            }
+        }
+
+        public void begin() throws NotSupportedException, 
javax.transaction.SystemException {
+            if (getTransactionStatus().isCompleted()) {
+                throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+            }
+
+            if (beanTransaction != null) {
+                // we could support nested transactions
+                throw new NotSupportedException("Current thread is already 
associated with a transaction");
+            }
+
+            try {
+                // create transaction definition
+                DefaultTransactionDefinition definition = new 
DefaultTransactionDefinition();
+                definition.setPropagationBehavior(PROPAGATION_REQUIRES_NEW);
+                if (timeout > 0) {
+                    definition.setTimeout(timeout);
+                }
+
+                // start the transaction
+                TransactionStatus transactionStatus = 
transactionManager.getTransaction(definition);
+
+                // TransactionStatus must be a DefaultTransactionStatus so we 
can implement isTransactionActive()
+                if (!(transactionManager instanceof DefaultTransactionStatus)) 
{
+                    transactionManager.rollback(transactionStatus);
+                    throw new 
IllegalArgumentException("SpringBeanTransactionPolicy only works with a 
PlatformTransactionManager that uses DefaultTransactionStatus");
+                }
+                beanTransaction = (DefaultTransactionStatus) transactionStatus;
+            } catch (TransactionException e) {
+                // check if exception is simply wrapping a JTA exception
+                Throwable cause = e.getCause();
+                if (cause instanceof NotSupportedException) {
+                    throw (NotSupportedException) cause;
+                } else if (cause instanceof javax.transaction.SystemException) 
{
+                    throw (javax.transaction.SystemException) cause;
+                }
+
+                // convert to JTA exception
+                if (e instanceof NestedTransactionNotSupportedException) {
+                    throw createJtaException(NotSupportedException.class, e);
+                }
+                throw 
createJtaException(javax.transaction.SystemException.class, e);
+            }
+        }
+
+        public void commit() throws HeuristicMixedException, 
HeuristicRollbackException, IllegalStateException, RollbackException, 
SecurityException, javax.transaction.SystemException {
+            if (getTransactionStatus().isCompleted()) {
+                throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+            }
+
+            if (beanTransaction == null) {
+                throw new IllegalStateException("Current thread is not 
associated with a transaction");
+            }
+
+            try {
+                transactionManager.commit(beanTransaction);
+            } catch (TransactionException e) {
+                // check if exception is simply wrapping a JTA exception
+                Throwable cause = e.getCause();
+                if (cause instanceof HeuristicMixedException) {
+                    throw (HeuristicMixedException) cause;
+                } else if (cause instanceof HeuristicRollbackException) {
+                    throw (HeuristicRollbackException) cause;
+                } else if (cause instanceof IllegalStateException) {
+                    throw (IllegalStateException) cause;
+                } else if (cause instanceof RollbackException) {
+                    throw (RollbackException) cause;
+                } else if (cause instanceof SecurityException) {
+                    throw (SecurityException) cause;
+                } else if (cause instanceof javax.transaction.SystemException) 
{
+                    throw (javax.transaction.SystemException) cause;
+                }
+
+                // convert to JTA exception
+                if (e instanceof HeuristicCompletionException) {
+                    HeuristicCompletionException heuristicCompletionException 
= (HeuristicCompletionException) e;
+                    if (heuristicCompletionException.getOutcomeState() == 
HeuristicCompletionException.STATE_MIXED) {
+                        throw 
createJtaException(HeuristicMixedException.class, e);
+                    } else if (heuristicCompletionException.getOutcomeState() 
== HeuristicCompletionException.STATE_ROLLED_BACK) {
+                        throw 
createJtaException(HeuristicRollbackException.class, e);
+                    }
+                } else if (e instanceof UnexpectedRollbackException) {
+                    throw createJtaException(RollbackException.class, e);
+                }
+                throw 
createJtaException(javax.transaction.SystemException.class, e);
+            }
+        }
+
+        public void rollback() throws IllegalStateException, 
javax.transaction.SystemException {
+            if (getTransactionStatus().isCompleted()) {
+                throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+            }
+
+            if (beanTransaction == null) {
+                throw new IllegalStateException("Current thread is not 
associated with a transaction");
+            }
+
+            try {
+                transactionManager.rollback(beanTransaction);
+            } catch (TransactionException e) {
+                // check if exception is simply wrapping a JTA exception
+                Throwable cause = e.getCause();
+                if (cause instanceof IllegalStateException) {
+                    throw (IllegalStateException) cause;
+                } else if (cause instanceof SecurityException) {
+                    throw (SecurityException) cause;
+                } else if (cause instanceof javax.transaction.SystemException) 
{
+                    throw (javax.transaction.SystemException) cause;
+                }
+
+                // convert to JTA exception
+                throw 
createJtaException(javax.transaction.SystemException.class, e);
+            }
+        }
+
+        public void setRollbackOnly() throws IllegalStateException, 
javax.transaction.SystemException {
+            if (getTransactionStatus().isCompleted()) {
+                throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+            }
+
+            if (beanTransaction == null) {
+                throw new IllegalStateException("Current thread is not 
associated with a transaction");
+            }
+
+            try {
+                beanTransaction.setRollbackOnly();
+            } catch (Exception e) {
+                // check if exception is simply wrapping a JTA exception
+                Throwable cause = e.getCause();
+                if (cause instanceof IllegalStateException) {
+                    throw (IllegalStateException) cause;
+                } else if (cause instanceof javax.transaction.SystemException) 
{
+                    throw (javax.transaction.SystemException) cause;
+                }
+
+                // convert to JTA exception
+                throw 
createJtaException(javax.transaction.SystemException.class, e);
+            }
+        }
+
+        public void setTransactionTimeout(int timeout) throws 
javax.transaction.SystemException {
+            if (getTransactionStatus().isCompleted()) {
+                throw new IllegalStateException("SpringBeanTransactionPolicy 
transaction has been completed");
+            }
+
+            if (timeout < 0) {
+                throw new javax.transaction.SystemException("timeout is 
negative");
+            }
+            SpringBeanTransactionPolicy.this.timeout = timeout;
+        }
+
+        private <T extends Exception> T createJtaException(Class<T> type, 
Throwable cause) throws javax.transaction.SystemException {
+            T exception;
+            try {
+                exception = 
type.getConstructor(String.class).newInstance("Spring 
PlatformTransactionManager threw an exception");
+            } catch (Exception e) {
+                javax.transaction.SystemException systemException = new 
javax.transaction.SystemException("Spring PlatformTransactionManager threw an 
exception");
+                systemException.initCause(cause);
+                throw systemException;
+            }
+            exception.initCause(cause);
+            return exception;
+        }
+    }
+}

Added: 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicy.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicy.java?rev=688602&view=auto
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicy.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicy.java
 Sun Aug 24 19:39:06 2008
@@ -0,0 +1,172 @@
+/**
+ *
+ * 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.spring;
+
+import javax.transaction.RollbackException;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.xa.XAResource;
+
+import org.apache.openejb.core.transaction.TransactionPolicy;
+import org.apache.openejb.core.transaction.TransactionType;
+import 
org.apache.openejb.core.transaction.TransactionPolicy.TransactionSynchronization.Status;
+import org.apache.openejb.ApplicationException;
+import org.apache.openejb.SystemException;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.HeuristicCompletionException;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import 
org.springframework.transaction.support.TransactionSynchronizationManager;
+import 
org.springframework.transaction.support.TransactionSynchronizationAdapter;
+
+public class SpringTransactionPolicy implements TransactionPolicy {
+    protected final PlatformTransactionManager transactionManager;
+    protected final TransactionType type;
+    private final DefaultTransactionStatus transactionStatus;
+
+    public SpringTransactionPolicy(PlatformTransactionManager 
transactionManager, TransactionType type) {
+        this.transactionManager = transactionManager;
+        this.type = type;
+
+        DefaultTransactionDefinition transactionDefinition = new 
DefaultTransactionDefinition();
+        switch (type) {
+            case BeanManaged:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+                break;
+            case Mandatory:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_MANDATORY);
+                break;
+            case Never:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_NEVER);
+                break;
+            case NotSupported:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+                break;
+            case Required:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED);
+                break;
+            case RequiresNew:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+                break;
+            case Supports:
+                
transactionDefinition.setPropagationBehavior(org.springframework.transaction.TransactionDefinition.PROPAGATION_SUPPORTS);
+                break;
+        }
+
+        TransactionStatus transactionStatus = 
transactionManager.getTransaction(transactionDefinition);
+        if (!(transactionManager instanceof DefaultTransactionStatus)) {
+            throw new IllegalArgumentException("SpringTransactionPolicy only 
works with a PlatformTransactionManager that uses DefaultTransactionStatus");
+        }
+        this.transactionStatus = (DefaultTransactionStatus) transactionStatus;
+    }
+
+    public TransactionType getTransactionType() {
+        return type;
+    }
+
+    public boolean isNewTransaction() {
+        return getTransactionStatus().isNewTransaction();
+    }
+
+    public boolean isTransactionActive() {
+        return !getTransactionStatus().isCompleted() && 
getTransactionStatus().hasTransaction();
+    }
+
+    public boolean isRollbackOnly() {
+        return getTransactionStatus().isRollbackOnly();
+    }
+
+    public void setRollbackOnly() {
+        getTransactionStatus().setRollbackOnly();
+    }
+
+    public void commit() throws ApplicationException, SystemException {
+        try {
+            transactionManager.commit(getTransactionStatus());
+        } catch (TransactionException e) {
+            // check if exception is simply wrapping a supported JTA exception
+            Throwable cause = e.getCause();
+            if (cause instanceof RollbackException) {
+                throw new ApplicationException(cause);
+            } else if (cause instanceof HeuristicMixedException) {
+                throw new ApplicationException(cause);
+            } else if (cause instanceof HeuristicRollbackException) {
+                throw new ApplicationException(cause);
+            } else if (cause instanceof IllegalStateException) {
+                throw new SystemException(cause);
+            } else if (cause instanceof SecurityException) {
+                throw new SystemException(cause);
+            } else if (cause instanceof javax.transaction.SystemException) {
+                throw new SystemException(cause);
+            }
+
+            // wrap with application or system exception based on type
+            if (e instanceof HeuristicCompletionException) {
+                throw new ApplicationException(e);
+            } else if (e instanceof UnexpectedRollbackException) {
+                throw new ApplicationException(e);
+            }
+            throw new SystemException(e);
+        }
+    }
+
+    public Object getResource(Object key) {
+        Object resource = TransactionSynchronizationManager.getResource(key);
+        return resource;
+    }
+
+    public void putResource(Object key, Object value) {
+        TransactionSynchronizationManager.bindResource(key, value);
+    }
+
+    public Object removeResource(Object key) {
+        Object resource = 
TransactionSynchronizationManager.unbindResource(key);
+        return resource;
+    }
+
+    public void registerSynchronization(final TransactionSynchronization 
synchronization) {
+        TransactionSynchronizationManager.registerSynchronization(new 
TransactionSynchronizationAdapter() {
+            public void beforeCompletion() {
+                synchronization.beforeCompletion();
+            }
+
+            public void afterCompletion(int status) {
+                Status s = null;
+                if (status == STATUS_COMMITTED) {
+                    s = Status.COMMITTED;
+                } else if (status == STATUS_ROLLED_BACK) {
+                    s = Status.ROLLEDBACK;
+                } else if (status == STATUS_UNKNOWN) {
+                    s = Status.UNKNOWN;
+                }
+                synchronization.afterCompletion(s);
+            }
+        });
+    }
+
+    public void enlistResource(XAResource xaResource) throws SystemException {
+        throw new SystemException(new 
UnsupportedOperationException("SpringTransactionPolicy does not support 
XAResource enlistment"));
+    }
+
+    protected DefaultTransactionStatus getTransactionStatus() {
+        return transactionStatus;
+    }
+}

Added: 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicyFactory.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicyFactory.java?rev=688602&view=auto
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicyFactory.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringTransactionPolicyFactory.java
 Sun Aug 24 19:39:06 2008
@@ -0,0 +1,44 @@
+/**
+ *
+ * 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.spring;
+
+import org.apache.openejb.core.transaction.TransactionPolicyFactory;
+import org.apache.openejb.core.transaction.TransactionPolicy;
+import org.apache.openejb.core.transaction.TransactionType;
+import org.apache.openejb.SystemException;
+import org.apache.openejb.ApplicationException;
+import org.springframework.transaction.PlatformTransactionManager;
+
+public class SpringTransactionPolicyFactory implements 
TransactionPolicyFactory {
+    private final PlatformTransactionManager transactionManager;
+
+    public SpringTransactionPolicyFactory(PlatformTransactionManager 
transactionManager) {
+        if (transactionManager == null) throw new 
NullPointerException("transactionManager is null");
+        this.transactionManager = transactionManager;
+    }
+
+    public TransactionPolicy createTransactionPolicy(TransactionType type) 
throws SystemException, ApplicationException {
+        SpringTransactionPolicy policy;
+        if (type == TransactionType.BeanManaged) {
+            policy = new SpringBeanTransactionPolicy(transactionManager);
+        } else {
+            policy = new SpringTransactionPolicy(transactionManager, type);
+        }
+        return policy;
+    }
+}


Reply via email to