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/11 01:33:15 UTC

svn commit: r495063 - in /incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb: assembler/classic/JndiEncBuilder.java core/CoreUserTransaction.java ri/sp/PseudoTransactionService.java

Author: dain
Date: Wed Jan 10 16:33:14 2007
New Revision: 495063

URL: http://svn.apache.org/viewvc?view=rev&rev=495063
Log:
OPENEJB-441 added support for TransactionSynchronizationRegistry

Modified:
    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/CoreUserTransaction.java
    incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoTransactionService.java

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=495063&r1=495062&r2=495063
==============================================================================
--- 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 Wed Jan 10 16:33:14 2007
@@ -32,6 +32,7 @@
 import javax.persistence.EntityManagerFactory;
 import javax.transaction.TransactionManager;
 import javax.transaction.UserTransaction;
+import javax.transaction.TransactionSynchronizationRegistry;
 import java.io.File;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -134,10 +135,21 @@
     public Context build() throws OpenEJBException {
         Map<String, Object> bindings = new HashMap<String, Object>();
 
-        if (beanManagedTransactions) {
-            Object obj = Assembler.getContext().get(TransactionManager.class.getName());
-            TransactionManager transactionManager = (TransactionManager) obj;
+        // bind TransactionManager
+        TransactionManager transactionManager = (TransactionManager) Assembler.getContext().get(TransactionManager.class.getName());
+        bindings.put("java:comp/TransactionManager", transactionManager);
 
+        // bind TransactionSynchronizationRegistry
+        TransactionSynchronizationRegistry synchronizationRegistry = (TransactionSynchronizationRegistry) Assembler.getContext().get(TransactionSynchronizationRegistry.class.getName());
+        if (synchronizationRegistry == null && transactionManager instanceof TransactionSynchronizationRegistry) {
+            synchronizationRegistry = (TransactionSynchronizationRegistry) transactionManager;
+        }
+        if (synchronizationRegistry != null) {
+            bindings.put("java:comp/TransactionSynchronizationRegistry", synchronizationRegistry);
+        }
+
+        // bind UserTransaction if bean managed transactions
+        if (beanManagedTransactions) {
             Object userTransaction = referenceWrapper.wrap(new CoreUserTransaction(transactionManager));
             bindings.put("java:comp/UserTransaction", userTransaction);
         }

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreUserTransaction.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreUserTransaction.java?view=diff&rev=495063&r1=495062&r2=495063
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreUserTransaction.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreUserTransaction.java Wed Jan 10 16:33:14 2007
@@ -40,11 +40,9 @@
     }
 
     private TransactionManager transactionManager() {
-        // DMB: taking this out is fine unless it is serialized as part of a stateful sessionbean passivation
-        // when the bean is activated
-//        if (transactionManager == null) {
-//            transactionManager = org.apache.openejb.OpenEJB.getTransactionManager();
-//        }
+        if (transactionManager == null) {
+            transactionManager = org.apache.openejb.OpenEJB.getTransactionManager();
+        }
         return transactionManager;
     }
 

Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoTransactionService.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoTransactionService.java?view=diff&rev=495063&r1=495062&r2=495063
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoTransactionService.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoTransactionService.java Wed Jan 10 16:33:14 2007
@@ -1,152 +1,192 @@
-/**
- * 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.
- */
+/**
+ * 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.ri.sp;
 
-import org.apache.openejb.spi.TransactionService;
-
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
 import javax.transaction.RollbackException;
 import javax.transaction.Status;
 import javax.transaction.Synchronization;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
-import javax.transaction.UserTransaction;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.xa.XAException;
 import javax.transaction.xa.XAResource;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
+
+import org.apache.openejb.spi.TransactionService;
+import org.apache.openejb.util.Logger;
 
 /**
  * @org.apache.xbean.XBean element="pseudoTransactionService"
  */
-public class PseudoTransactionService implements TransactionService, TransactionManager {
-    Hashtable map = new Hashtable();
+public class PseudoTransactionService implements TransactionService, TransactionManager, TransactionSynchronizationRegistry {
+    private static final Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.core.cmp");
+    private final ThreadLocal<MyTransaction> threadTransaction = new ThreadLocal<MyTransaction>();
 
-    public void init(java.util.Properties props) {
+    public void init(Properties props) {
     }
 
     public TransactionManager getTransactionManager() {
         return this;
     }
 
-    public UserTransaction getUserTransaction(Object txID) {
-        return new UserTransaction() {
-            public void begin() {
-                PseudoTransactionService.this.begin();
-            }
-
-            public void commit() throws RollbackException {
-                PseudoTransactionService.this.commit();
-            }
+    public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
+        return this;
+    }
 
-            public int getStatus() throws javax.transaction.SystemException {
-                return PseudoTransactionService.this.getStatus();
-            }
+    public int getStatus() {
+        MyTransaction tx = threadTransaction.get();
+        if (tx == null) {
+            return Status.STATUS_NO_TRANSACTION;
+        }
+        return tx.getStatus();
+    }
 
-            public void rollback() {
-                PseudoTransactionService.this.rollback();
-            }
+    public Transaction getTransaction() {
+        return threadTransaction.get();
+    }
 
-            public void setRollbackOnly() {
-                PseudoTransactionService.this.setRollbackOnly();
-            }
+    public boolean getRollbackOnly() {
+        MyTransaction tx = threadTransaction.get();
+        if (tx == null) {
+            throw new IllegalStateException("No transaction active");
+        }
+        return tx.getRollbackOnly();
+    }
 
-            public void setTransactionTimeout(int seconds) {
-                PseudoTransactionService.this.setTransactionTimeout(seconds);
-            }
-        };
+    public void setRollbackOnly() {
+        MyTransaction tx = threadTransaction.get();
+        if (tx == null) {
+            throw new IllegalStateException("No transaction active");
+        }
+        tx.setRollbackOnly();
     }
 
-    public void begin() {
-        Transaction tx = new MyTransaction();
-        map.put(Thread.currentThread(), tx);
+    public void begin() throws NotSupportedException {
+        if (threadTransaction.get() != null) {
+            throw new NotSupportedException("A transaction is already active");
+        }
+
+        MyTransaction tx = new MyTransaction();
+        threadTransaction.set(tx);
     }
 
     public void commit() throws RollbackException {
-        MyTransaction tx = (MyTransaction) map.remove(Thread.currentThread());
-        if (tx != null) {
+        MyTransaction tx = threadTransaction.get();
+        if (tx == null) {
+            throw new IllegalStateException("No transaction active");
+        }
+
+        try {
             tx.commit();
-        } else {
-            throw new IllegalStateException();
+        } finally {
+            threadTransaction.set(null);
         }
     }
 
-    public int getStatus() throws javax.transaction.SystemException {
-        Transaction tx = (Transaction) map.get(Thread.currentThread());
+
+    public void rollback() {
+        MyTransaction tx = threadTransaction.get();
         if (tx == null) {
-            return Status.STATUS_NO_TRANSACTION;
+            throw new IllegalStateException("No transaction active");
+        }
+
+        try {
+            tx.rollback();
+        } finally {
+            threadTransaction.set(null);
         }
-        return tx.getStatus();
     }
 
-    public Transaction getTransaction() {
-        return (Transaction) map.get(Thread.currentThread());
+    public Transaction suspend() {
+        return threadTransaction.get();
     }
 
-    public void resume(Transaction tx)
-            throws javax.transaction.SystemException, javax.transaction.InvalidTransactionException {
-        Transaction ctx = (Transaction) map.get(Thread.currentThread());
-        int status = tx.getStatus();
+    public void resume(Transaction tx) throws InvalidTransactionException {
+        if (tx == null) {
+            throw new InvalidTransactionException("Transaction is null");
+        }
+        if (!(tx instanceof MyTransaction)) {
+            throw new InvalidTransactionException("Unknown transaction type " + tx.getClass().getName());
+        }
+        MyTransaction myTransaction = (MyTransaction) tx;
+
+        if (threadTransaction.get() != null) {
+            throw new IllegalStateException("A transaction is already active");
+        }
 
-        if (ctx != null || tx == null || (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK)) {
-            throw new javax.transaction.InvalidTransactionException();
+        int status = myTransaction.getStatus();
+        if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) {
+            throw new InvalidTransactionException("Expected transaction to be STATUS_ACTIVE or STATUS_MARKED_ROLLBACK, but was " + status);
         }
-        map.put(Thread.currentThread(), tx);
+
+        threadTransaction.set(myTransaction);
     }
 
-    public Transaction suspend() {
-        return (Transaction) map.remove(Thread.currentThread());
+    public Object getTransactionKey() {
+        return getTransaction();
     }
 
-    public void rollback() {
-        MyTransaction tx = (MyTransaction) map.remove(Thread.currentThread());
+    public int getTransactionStatus() {
+        return getStatus();
+    }
+
+    public Object getResource(Object key) {
+        MyTransaction tx = threadTransaction.get();
         if (tx == null) {
-            throw new IllegalStateException();
+            throw new IllegalStateException("No transaction active");
         }
-        tx.rollback();
+
+        Object value = tx.getResource(key);
+        return value;
     }
 
-    public void setRollbackOnly() {
-        MyTransaction tx = (MyTransaction) map.get(Thread.currentThread());
+    public void putResource(Object key, Object value) {
+        MyTransaction tx = threadTransaction.get();
         if (tx == null) {
-            throw new IllegalStateException();
+            throw new IllegalStateException("No transaction active");
         }
-        tx.setRollbackOnly();
+
+        tx.putResource(key, value);
+    }
+
+    public void registerInterposedSynchronization(Synchronization synchronization) {
+        MyTransaction tx = threadTransaction.get();
+        if (tx == null) {
+            throw new IllegalStateException("No transaction active");
+        }
+
+        tx.registerInterposedSynchronization(synchronization);
     }
 
-    public void setTransactionTimeout(int x) {
+    public void setTransactionTimeout(int seconds) {
     }
 
     public class MyTransaction implements Transaction {
-        Vector registeredSynchronizations = new Vector();
-        Vector xaResources = new Vector();
-        int status = Status.STATUS_ACTIVE;
-
-        public void commit() throws RollbackException {
-            if (status == Status.STATUS_MARKED_ROLLBACK) {
-                rollback();
-                throw new RollbackException();
-            }
-            doBeforeCompletion();
-            doXAResources(Status.STATUS_COMMITTED);
-            status = Status.STATUS_COMMITTED;
-            doAfterCompletion(Status.STATUS_COMMITTED);
-            registeredSynchronizations = new Vector();
-            map.remove(Thread.currentThread());
-        }
+        private final List<Synchronization> registeredSynchronizations = Collections.synchronizedList(new ArrayList<Synchronization>());
+        private final List<XAResource> xaResources =  Collections.synchronizedList(new ArrayList<XAResource>());
+        private final Map<Object, Object> resources = new HashMap<Object,Object>();
+        private int status = Status.STATUS_ACTIVE;
 
         public boolean delistResource(XAResource xaRes, int flag) {
             xaResources.remove(xaRes);
@@ -154,7 +194,7 @@
         }
 
         public boolean enlistResource(XAResource xaRes) {
-            xaResources.addElement(xaRes);
+            xaResources.add(xaRes);
             return true;
         }
 
@@ -162,79 +202,110 @@
             return status;
         }
 
-        public void registerSynchronization(Synchronization sync) {
-            registeredSynchronizations.addElement(sync);
+        public void registerSynchronization(Synchronization synchronization) {
+            registeredSynchronizations.add(synchronization);
         }
 
-        public void rollback() {
-            doXAResources(Status.STATUS_ROLLEDBACK);
-            doAfterCompletion(Status.STATUS_ROLLEDBACK);
-            status = Status.STATUS_ROLLEDBACK;
-            registeredSynchronizations = new Vector();
-            map.remove(Thread.currentThread());
+        public void registerInterposedSynchronization(Synchronization synchronization) {
+            registeredSynchronizations.add(synchronization);
+        }
+
+        public boolean getRollbackOnly() {
+            return status == Status.STATUS_MARKED_ROLLBACK;
         }
 
         public void setRollbackOnly() {
             status = Status.STATUS_MARKED_ROLLBACK;
         }
 
+        public Object getResource(Object key) {
+            if (key == null) throw new NullPointerException("key is null");
+            return resources.get(key);
+        }
 
-        private void doBeforeCompletion() {
-            Enumeration enumeration = registeredSynchronizations.elements();
-            while (enumeration.hasMoreElements()) {
+        public void putResource(Object key, Object value) {
+            if (key == null) throw new NullPointerException("key is null");
+            if (value != null) {
+                resources.put(key, value);
+            } else {
+                resources.remove(key);
+            }
+        }
+
+        public void commit() throws RollbackException {
+            try {
+                if (status == Status.STATUS_MARKED_ROLLBACK) {
+                    rollback();
+                    throw new RollbackException();
+                }
                 try {
-                    Synchronization sync = (Synchronization) enumeration.nextElement();
-                    sync.beforeCompletion();
-                } catch (RuntimeException re) {
-                    re.printStackTrace();
+                    doBeforeCompletion();
+                } catch (Exception e) {
+                    rollback();
+                    throw (RollbackException) new RollbackException().initCause(e);
                 }
+                doXAResources(Status.STATUS_COMMITTED);
+                status = Status.STATUS_COMMITTED;
+                doAfterCompletion(Status.STATUS_COMMITTED);
+            } finally {
+                threadTransaction.set(null);
+            }
+        }
+
+        public void rollback() {
+            try {
+                doXAResources(Status.STATUS_ROLLEDBACK);
+                doAfterCompletion(Status.STATUS_ROLLEDBACK);
+                status = Status.STATUS_ROLLEDBACK;
+                registeredSynchronizations.clear();
+            } finally {
+                threadTransaction.set(null);
+            }
+        }
+
+        private void doBeforeCompletion() {
+            for (Synchronization sync : new ArrayList<Synchronization>(registeredSynchronizations)) {
+                sync.beforeCompletion();
             }
         }
 
         private void doAfterCompletion(int status) {
-            Enumeration enumeration = registeredSynchronizations.elements();
-            while (enumeration.hasMoreElements()) {
+            for (Synchronization sync : new ArrayList<Synchronization>(registeredSynchronizations)) {
                 try {
-                    Synchronization sync = (Synchronization) enumeration.nextElement();
                     sync.afterCompletion(status);
-                } catch (RuntimeException re) {
-                    re.printStackTrace();
+                } catch (RuntimeException e) {
+                    logger.warning("Synchronization afterCompletion threw a RuntimeException", e);
                 }
             }
         }
 
         private void doXAResources(int status) {
-            Object [] resources = xaResources.toArray();
-            for (int i = 0; i < resources.length; i++) {
-                XAResource xaRes = (XAResource) resources[i];
+            for (XAResource xaRes : new ArrayList<XAResource>(xaResources)) {
                 if (status == Status.STATUS_COMMITTED) {
                     try {
                         xaRes.commit(null, true);
-                    } catch (javax.transaction.xa.XAException xae) {
+                    } catch (XAException e) {
 
                     }
                     try {
                         xaRes.end(null, XAResource.TMSUCCESS);
-                    } catch (javax.transaction.xa.XAException xae) {
+                    } catch (XAException e) {
 
                     }
                 } else {
                     try {
                         xaRes.rollback(null);
-                    } catch (javax.transaction.xa.XAException xae) {
+                    } catch (XAException e) {
 
                     }
                     try {
                         xaRes.end(null, XAResource.TMFAIL);
-                    } catch (javax.transaction.xa.XAException xae) {
-
+                    } catch (XAException e) {
                     }
                 }
             }
-            xaResources = new Vector();
-
+            xaResources.clear();
         }
-
     }
 }