You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2005/02/26 00:10:29 UTC

svn commit: r155376 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/ connector/src/test/org/apache/geronimo/connector/outbound/ timer/src/java/org/apache/geronimo/timer/ timer/src/test/org/apache/geronimo/timer/ transaction/src/java/org/apache/geronimo/transaction/ transaction/src/java/org/apache/geronimo/transaction/context/

Author: dain
Date: Fri Feb 25 15:10:24 2005
New Revision: 155376

URL: http://svn.apache.org/viewcvs?view=rev&rev=155376
Log:
Fixed bugs in TransactionContext and handling of the contexts unturned by turning back on in-tx caching
Added support for entrancy tracking and killing InstanceContexts

Modified:
    geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java
    geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionEnlistingInterceptor.java
    geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/TransactionCachingInterceptorTest.java
    geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/NontransactionalExecutorTask.java
    geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ThreadPooledTimer.java
    geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/TransactionalExecutorTask.java
    geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java
    geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/DefaultInstanceContext.java
    geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/InstanceContext.java
    geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/InheritableTransactionContext.java
    geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/TransactionContext.java
    geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/UnspecifiedTransactionContext.java

Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java (original)
+++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionCachingInterceptor.java Fri Feb 25 15:10:24 2005
@@ -27,6 +27,7 @@
 import org.apache.geronimo.transaction.ConnectionReleaser;
 import org.apache.geronimo.transaction.context.TransactionContext;
 import org.apache.geronimo.transaction.context.TransactionContextManager;
+import org.apache.geronimo.transaction.context.InheritableTransactionContext;
 
 /**
  * TransactionCachingInterceptor.java
@@ -59,16 +60,15 @@
     }
 
     public void getConnection(ConnectionInfo connectionInfo) throws ResourceException {
-        TransactionContext transactionContext = transactionContextManager.getContext();
         //There can be an inactive transaction context when a connection is requested in
         //Synchronization.afterCompletion().
-        if (transactionContext == null || !transactionContext.isActive()) {
-            next.getConnection(connectionInfo);
-        } else {
-            ManagedConnectionInfos managedConnectionInfos = (ManagedConnectionInfos) transactionContext.getManagedConnectionInfo(this);
+        TransactionContext transactionContext = transactionContextManager.getContext();
+        if ((transactionContext instanceof InheritableTransactionContext) && ((InheritableTransactionContext) transactionContext).isActive()) {
+            InheritableTransactionContext inheritableTransactionContext = ((InheritableTransactionContext) transactionContext);
+            ManagedConnectionInfos managedConnectionInfos = (ManagedConnectionInfos) inheritableTransactionContext.getManagedConnectionInfo(this);
             if (managedConnectionInfos == null) {
                 managedConnectionInfos = new ManagedConnectionInfos();
-                transactionContext.setManagedConnectionInfo(this, managedConnectionInfos);
+                inheritableTransactionContext.setManagedConnectionInfo(this, managedConnectionInfos);
             }
             if (connectionInfo.isUnshareable()) {
                 if (!managedConnectionInfos.containsUnshared(connectionInfo.getManagedConnectionInfo())) {
@@ -85,6 +85,8 @@
                     managedConnectionInfos.setShared(connectionInfo.getManagedConnectionInfo());
                 }
             }
+        } else {
+            next.getConnection(connectionInfo);
         }
     }
 
@@ -96,7 +98,7 @@
         }
 
         TransactionContext transactionContext = transactionContextManager.getContext();
-        if (transactionContext != null && transactionContext.isActive()) {
+        if ((transactionContext instanceof InheritableTransactionContext) && ((InheritableTransactionContext) transactionContext).isActive()) {
             return;
         }
         internalReturn(connectionInfo, connectionReturnAction);

Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionEnlistingInterceptor.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionEnlistingInterceptor.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionEnlistingInterceptor.java (original)
+++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/TransactionEnlistingInterceptor.java Fri Feb 25 15:10:24 2005
@@ -24,6 +24,7 @@
 
 import org.apache.geronimo.transaction.context.TransactionContext;
 import org.apache.geronimo.transaction.context.TransactionContextManager;
+import org.apache.geronimo.transaction.context.InheritableTransactionContext;
 
 /**
  * TransactionEnlistingInterceptor.java
@@ -48,9 +49,12 @@
         try {
             ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo();
             TransactionContext transactionContext = transactionContextManager.getContext();
-            if (transactionContext != null && transactionContext.isActive()) {
-                XAResource xares = mci.getXAResource();
-                transactionContext.getTransaction().enlistResource(xares);
+            if ((transactionContext instanceof InheritableTransactionContext)) {
+                InheritableTransactionContext inheritableTransactionContext = ((InheritableTransactionContext) transactionContext);
+                if (inheritableTransactionContext.isActive()) {
+                    XAResource xares = mci.getXAResource();
+                    inheritableTransactionContext.getTransaction().enlistResource(xares);
+                }
             }
 
         } catch (SystemException e) {
@@ -76,9 +80,12 @@
         try {
             ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo();
             TransactionContext transactionContext = transactionContextManager.getContext();
-            if (transactionContext != null && transactionContext.isActive()) {
-                XAResource xares = mci.getXAResource();
-                transactionContext.getTransaction().delistResource(xares, XAResource.TMSUSPEND);
+            if ((transactionContext instanceof InheritableTransactionContext)) {
+                InheritableTransactionContext inheritableTransactionContext = ((InheritableTransactionContext) transactionContext);
+                if (inheritableTransactionContext.isActive()) {
+                    XAResource xares = mci.getXAResource();
+                    inheritableTransactionContext.getTransaction().delistResource(xares, XAResource.TMSUSPEND);
+                }
             }
 
         } catch (SystemException e) {

Modified: geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/TransactionCachingInterceptorTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/TransactionCachingInterceptorTest.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/TransactionCachingInterceptorTest.java (original)
+++ geronimo/trunk/modules/connector/src/test/org/apache/geronimo/connector/outbound/TransactionCachingInterceptorTest.java Fri Feb 25 15:10:24 2005
@@ -127,8 +127,6 @@
         transactionCachingInterceptor.getConnection(connectionInfo1);
         assertTrue("Expected to get an initial connection", obtainedConnectionInfo != null);
         assertTrue("Expected nothing returned yet", returnedConnectionInfo == null);
-        assertTrue("Expected no ManagedConnectionInfo in the TransactionContext",
-                null == transactionContextManager.getContext().getManagedConnectionInfo(transactionCachingInterceptor));
         obtainedConnectionInfo = null;
         ConnectionInfo connectionInfo2 = makeConnectionInfo();
         transactionCachingInterceptor.getConnection(connectionInfo2);
@@ -136,18 +134,12 @@
         assertTrue("Expected nothing returned yet", returnedConnectionInfo == null);
         assertTrue("Expected different ManagedConnectionInfo in both ConnectionInfos",
                 connectionInfo1.getManagedConnectionInfo() != connectionInfo2.getManagedConnectionInfo());
-        assertTrue("Expected no ManagedConnectionInfo in the TransactionContext",
-                null == transactionContextManager.getContext().getManagedConnectionInfo(transactionCachingInterceptor));
         //we didn't create any handles, so the "ManagedConnection" should be returned.
-        assertTrue("Expected TransactionContext to report inactive", !transactionContextManager.getContext().isActive());
         transactionCachingInterceptor.returnConnection(connectionInfo1, ConnectionReturnAction.RETURN_HANDLE);
         assertTrue("Expected connection to be returned", returnedConnectionInfo != null);
         returnedConnectionInfo = null;
         transactionCachingInterceptor.returnConnection(connectionInfo2, ConnectionReturnAction.RETURN_HANDLE);
         assertTrue("Expected connection to be returned", returnedConnectionInfo != null);
-
-        assertTrue("Expected TransactionContext to report inactive", !transactionContextManager.getContext().isActive());
-
     }
 
     public void testTransactionIndependence() throws Exception {

Modified: geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/NontransactionalExecutorTask.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/NontransactionalExecutorTask.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/NontransactionalExecutorTask.java (original)
+++ geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/NontransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
@@ -19,14 +19,12 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.geronimo.timer.ExecutorTask;
+import org.apache.geronimo.transaction.context.TransactionContext;
+import org.apache.geronimo.transaction.context.UnspecifiedTransactionContext;
 
 /**
- *
- *
  * @version $Rev$ $Date$
- *
- * */
+ */
 public class NontransactionalExecutorTask implements ExecutorTask {
 
     private static final Log log = LogFactory.getLog(NontransactionalExecutorTask.class);
@@ -42,18 +40,26 @@
     }
 
     public void run() {
+        UnspecifiedTransactionContext transactionContext = new UnspecifiedTransactionContext();
+        TransactionContext oldTransactionContext = TransactionContext.getContext();
+        TransactionContext.setContext(transactionContext);
         try {
-            userTask.run();
-        } catch (Exception e) {
-            log.info(e);
-        }
-        try {
-            threadPooledTimer.workPerformed(workInfo);
-        } catch (PersistenceException e) {
-            log.info(e);
-        }
-        if (workInfo.isOneTime()) {
-            threadPooledTimer.removeWorkInfo(workInfo);
+            try {
+                userTask.run();
+            } catch (Exception e) {
+                log.info(e);
+            }
+            try {
+                threadPooledTimer.workPerformed(workInfo);
+            } catch (PersistenceException e) {
+                log.info(e);
+            }
+            if (workInfo.isOneTime()) {
+                threadPooledTimer.removeWorkInfo(workInfo);
+            }
+        } finally {
+            transactionContext.commit();
+            TransactionContext.setContext(oldTransactionContext);
         }
     }
 

Modified: geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ThreadPooledTimer.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ThreadPooledTimer.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ThreadPooledTimer.java (original)
+++ geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ThreadPooledTimer.java Fri Feb 25 15:10:24 2005
@@ -37,6 +37,7 @@
 import org.apache.geronimo.gbean.GBeanLifecycle;
 import org.apache.geronimo.transaction.context.TransactionContext;
 import org.apache.geronimo.transaction.context.TransactionContextManager;
+import org.apache.geronimo.transaction.context.InheritableTransactionContext;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -243,13 +244,21 @@
 
     void registerSynchronization(Synchronization sync) throws RollbackException, SystemException {
         TransactionContext transactionContext = transactionContextManager.getContext();
+
         //TODO move the registerSynchronization to the TransactionContext
-        Transaction transaction = transactionContext == null? null: transactionContext.getTransaction();
+        Transaction transaction;
+        if (transactionContext instanceof InheritableTransactionContext) {
+            InheritableTransactionContext inheritableTransactionContext = ((InheritableTransactionContext) transactionContext);
+            transaction = inheritableTransactionContext.getTransaction();
+            assert transaction == null || inheritableTransactionContext.isActive(): "Trying to register a sync on an inactive transaction context";
+        } else {
+            transaction = null;
+        }
+
         if (transaction == null) {
             sync.beforeCompletion();
             sync.afterCompletion(Status.STATUS_COMMITTED);
         } else {
-            assert transactionContext.isActive(): "Trying to register a sync on an inactive transaction context";
             transaction.registerSynchronization(sync);
         }
     }

Modified: geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/TransactionalExecutorTask.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/TransactionalExecutorTask.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/TransactionalExecutorTask.java (original)
+++ geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/TransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
@@ -17,26 +17,14 @@
 
 package org.apache.geronimo.timer;
 
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.geronimo.transaction.context.ContainerTransactionContext;
 import org.apache.geronimo.transaction.context.TransactionContextManager;
-import org.apache.geronimo.timer.ExecutorTask;
-import org.apache.geronimo.timer.PersistenceException;
-import org.apache.geronimo.timer.ThreadPooledTimer;
 
 /**
- *
- *
  * @version $Rev$ $Date$
- *
- * */
+ */
 public class TransactionalExecutorTask implements ExecutorTask {
     private static final Log log = LogFactory.getLog(TransactionalExecutorTask.class);
 
@@ -54,49 +42,38 @@
         this.transactionContextManager = transactionContextManager;
         this.repeatCount = repeatCount;
     }
-
+    
     public void run() {
         ContainerTransactionContext transactionContext = null;
         for (int tries = 0; tries < repeatCount; tries++) {
             try {
                 transactionContext = transactionContextManager.newContainerTransactionContext();
-            } catch (NotSupportedException e) {
-                log.info(e);
-                break;
-            } catch (SystemException e) {
-                log.info(e);
+            } catch (Exception e) {
+                log.info("Exception occured while starting container transaction", e);
                 break;
             }
             try {
                 try {
                     userTask.run();
                 } catch (Exception e) {
-                    log.info(e);
+                    log.info("Exception occured while running user task", e);
                 }
                 try {
                     threadPooledTimer.workPerformed(workInfo);
                 } catch (PersistenceException e) {
-                    log.info(e);
+                    log.info("Exception occured while updating timer persistent state", e);
                 }
             } finally {
                 try {
-                    if (transactionContext.getRollbackOnly()) {
-                        transactionContext.rollback();
-                    } else {
-                        transactionContext.commit();
+                    if (transactionContext.commit()) {
                         if (workInfo.isOneTime()) {
                             threadPooledTimer.removeWorkInfo(workInfo);
                         }
+                        // todo this is a very weird code structure.... returning from a finally is very confusing
                         return;
                     }
-                } catch (SystemException e) {
-                    log.info(e);
-                } catch (HeuristicMixedException e) {
-                    log.info(e);
-                } catch (HeuristicRollbackException e) {
-                    log.info(e);
-                } catch (RollbackException e) {
-                    log.info(e);
+                } catch (Exception e) {
+                    log.info("Exception occured while completing container transaction", e);
                 }
             }
         }

Modified: geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java (original)
+++ geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java Fri Feb 25 15:10:24 2005
@@ -23,11 +23,6 @@
 import org.apache.geronimo.transaction.context.TransactionContext;
 import org.apache.geronimo.transaction.context.TransactionContextManager;
 import org.apache.geronimo.timer.vm.VMWorkerPersistence;
-import org.apache.geronimo.timer.ExecutorTaskFactory;
-import org.apache.geronimo.timer.ThreadPooledTimer;
-import org.apache.geronimo.timer.UserTaskFactory;
-import org.apache.geronimo.timer.WorkerPersistence;
-import org.apache.geronimo.timer.WorkInfo;
 
 /**
  *
@@ -73,7 +68,7 @@
         for (long i = 0; i < COUNT; i++) {
             timer.schedule(userTaskFactory, key, userId, userKey, i);
         }
-        Thread.currentThread().sleep(COUNT + SLOP);
+        Thread.sleep(COUNT + SLOP);
         assertEquals(COUNT, counter.get());
     }
 
@@ -85,7 +80,7 @@
         for (int i = 0; i < workInfos.length; i++) {
             workInfos[i].getExecutorFeedingTimerTask().cancel();
         }
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(0, counter.get());
     }
 
@@ -98,7 +93,7 @@
 
         timer.doStart();
         timer.playback(key, userTaskFactory);
-        Thread.currentThread().sleep(2 * SLOP + DELAY);
+        Thread.sleep(2 * SLOP + DELAY);
         assertEquals(COUNT, counter.get());
     }
 
@@ -134,48 +129,48 @@
         for (long i = 0; i < COUNT; i++) {
             timer.schedule(userTaskFactory, key, userId, userKey, i);
         }
-        Thread.currentThread().sleep(COUNT + SLOP);
+        Thread.sleep(COUNT + SLOP);
         assertEquals(0, counter.get());
         transactionContext.commit();
-        Thread.currentThread().sleep(COUNT + SLOP);
+        Thread.sleep(COUNT + SLOP);
         assertEquals(COUNT, counter.get());
     }
 
     public void testCancelInCommittedTransaction() throws Exception {
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         WorkInfo[] workInfos = new WorkInfo[COUNT];
         for (long i = 0; i < COUNT; i++) {
             workInfos[(int) i] = timer.scheduleAtFixedRate(key, userTaskFactory, userId, userKey, DELAY, DELAY);
         }
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(COUNT, counter.get());
         TransactionContext transactionContext = transactionContextManager.newContainerTransactionContext();
         for (int i = 0; i < workInfos.length; i++) {
             workInfos[i].getExecutorFeedingTimerTask().cancel();
         }
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(COUNT, counter.get());
         transactionContext.commit();
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(COUNT, counter.get());
     }
 
     public void testCancelInRolledBackTransaction() throws Exception {
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         WorkInfo[] workInfos = new WorkInfo[COUNT];
         for (long i = 0; i < COUNT; i++) {
             workInfos[(int) i] = timer.scheduleAtFixedRate(key, userTaskFactory, userId, userKey, DELAY, DELAY);
         }
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(COUNT, counter.get());
         TransactionContext transactionContext = transactionContextManager.newContainerTransactionContext();
         for (int i = 0; i < workInfos.length; i++) {
             workInfos[i].getExecutorFeedingTimerTask().cancel();
         }
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         assertEquals(COUNT, counter.get());
         transactionContext.rollback();
-        Thread.currentThread().sleep(SLOP + DELAY);
+        Thread.sleep(SLOP + DELAY);
         // Catches up with two periods.
         assertEquals(3 * COUNT, counter.get());
     }
@@ -183,13 +178,13 @@
     public void testRepeatCountFromPersisted() throws Exception {
         assert DELAY > 2 * SLOP;
         timer.scheduleAtFixedRate(key, userTaskFactory, userId, userKey, 0L, DELAY);
-        Thread.currentThread().sleep(4 * DELAY + SLOP);
+        Thread.sleep(4 * DELAY + SLOP);
         timer.doStop();
         assertEquals(5, counter.get());
 
         timer.doStart();
         timer.playback(key, userTaskFactory);
-        Thread.currentThread().sleep(5 * DELAY + SLOP);
+        Thread.sleep(5 * DELAY + SLOP);
         assertEquals(2 * 5, counter.get());
 
     }

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/DefaultInstanceContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/DefaultInstanceContext.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/DefaultInstanceContext.java (original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/DefaultInstanceContext.java Fri Feb 25 15:10:24 2005
@@ -29,10 +29,11 @@
  *
  * */
 public class DefaultInstanceContext implements InstanceContext {
-
     private final Map connectionManagerMap = new HashMap();
     private final Set unshareableResources;
     private final Set applicationManagedSecurityResources;
+    private int callDepth;
+    private boolean dead = false;
 
     public DefaultInstanceContext(Set unshareableResources, Set applicationManagedSecurityResources) {
         this.unshareableResources = unshareableResources;
@@ -43,9 +44,6 @@
         return null;
     }
 
-    public void setId(Object id) {
-    }
-
     public Object getContainerId() {
         return null;
     }
@@ -62,6 +60,9 @@
     public void afterCommit(boolean status) throws Exception {
     }
 
+    public void unassociate() throws Throwable {
+    }
+
     public Map getConnectionManagerMap() {
         return connectionManagerMap;
     }
@@ -74,4 +75,24 @@
         return applicationManagedSecurityResources;
     }
 
+    public boolean isInCall() {
+        return callDepth > 0;
+    }
+
+    public void enter() {
+        callDepth++;
+    }
+
+    public void exit() {
+        assert isInCall();
+        callDepth--;
+    }
+
+    public boolean isDead() {
+        return dead;
+    }
+
+    public void die() {
+        dead = true;
+    }
 }

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/InstanceContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/InstanceContext.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/InstanceContext.java (original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/InstanceContext.java Fri Feb 25 15:10:24 2005
@@ -29,8 +29,6 @@
 public interface InstanceContext {
     Object getId();
 
-    void setId(Object id);
-
     Object getContainerId();
 
     void associate() throws Throwable;
@@ -41,6 +39,8 @@
 
     void afterCommit(boolean status) throws Throwable;
 
+    void unassociate() throws Throwable;
+
     /**
      * IMPORTANT INVARIANT: this should always return a map, never null.
      * @return map of ConnectionManager to (list of ) managed connection info objects.
@@ -51,4 +51,13 @@
 
     Set getApplicationManagedSecurityResources();
 
+    boolean isInCall();
+
+    void enter();
+
+    void exit();
+
+    boolean isDead();
+
+    void die();
 }

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/InheritableTransactionContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/InheritableTransactionContext.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/InheritableTransactionContext.java (original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/InheritableTransactionContext.java Fri Feb 25 15:10:24 2005
@@ -17,6 +17,10 @@
 
 package org.apache.geronimo.transaction.context;
 
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
 import javax.transaction.SystemException;
 import javax.transaction.Status;
 import javax.transaction.Transaction;
@@ -27,16 +31,17 @@
 import javax.transaction.RollbackException;
 
 import org.apache.geronimo.transaction.ExtendedTransactionManager;
+import org.apache.geronimo.transaction.ConnectionReleaser;
+import org.apache.geronimo.transaction.InstanceContext;
 
 /**
- *
- *
  * @version $Rev$ $Date$
  */
 public abstract class InheritableTransactionContext extends TransactionContext {
     private final ExtendedTransactionManager txnManager;
     private Transaction transaction;
     private boolean threadAssociated = false;
+    private Map managedConnections;
 
     protected InheritableTransactionContext(ExtendedTransactionManager txnManager) {
         this.txnManager = txnManager;
@@ -55,9 +60,26 @@
         return transaction;
     }
 
+    public void setManagedConnectionInfo(ConnectionReleaser key, Object info) {
+        if (managedConnections == null) {
+            managedConnections = new HashMap();
+        }
+        managedConnections.put(key, info);
+    }
+
+    public Object getManagedConnectionInfo(ConnectionReleaser key) {
+        if (managedConnections == null) {
+            return null;
+        }
+        return managedConnections.get(key);
+    }
+
     public boolean isActive() {
+        if (transaction == null) {
+            return false;
+        }
         try {
-            int status = txnManager.getStatus();
+            int status = transaction.getStatus();
             return status == Status.STATUS_ACTIVE || status == Status.STATUS_MARKED_ROLLBACK;
         } catch (SystemException e) {
             return false;
@@ -65,7 +87,6 @@
     }
 
     public boolean getRollbackOnly() throws SystemException {
-        Transaction transaction = getTransaction();
         if (transaction == null) {
             throw new IllegalStateException("There is no transaction in progress.");
         }
@@ -77,7 +98,6 @@
     }
 
     public void setRollbackOnly() throws IllegalStateException, SystemException {
-        Transaction transaction = getTransaction();
         if (transaction == null) {
             throw new IllegalStateException("There is no transaction in progress.");
         }
@@ -85,13 +105,16 @@
     }
 
     public void begin(long transactionTimeoutMilliseconds) throws SystemException, NotSupportedException {
+        assert transaction == null:  "Already associated with a transaction";
         transaction = txnManager.begin(transactionTimeoutMilliseconds);
         threadAssociated = true;
     }
 
     public void suspend() throws SystemException {
         Transaction suspendedTransaction = txnManager.suspend();
-        assert (transaction == suspendedTransaction) : "suspend did not return our transaction. ours: " + transaction + ", suspended returned: " + suspendedTransaction;
+        if (transaction != suspendedTransaction) {
+            throw new SystemException("Suspend did not return our transaction: expectedTx=" + transaction + ", suspendedTx=" + suspendedTransaction);
+        }
         threadAssociated = false;
     }
 
@@ -101,6 +124,29 @@
     }
 
     public boolean commit() throws HeuristicMixedException, HeuristicRollbackException, SystemException, RollbackException {
+        return complete();
+    }
+
+    public void rollback() throws SystemException {
+        setRollbackOnly();
+        try {
+            complete();
+        } catch (SystemException e) {
+            throw e;
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Error e) {
+            throw e;
+        } catch (Exception e) {
+            throw (SystemException) new SystemException("After commit of container transaction failed").initCause(e);
+        }
+    }
+
+    private boolean complete() throws HeuristicMixedException, HeuristicRollbackException, SystemException, RollbackException {
+        if (transaction == null) {
+            throw new IllegalStateException("There is no transaction in progress.");
+        }
+
         boolean wasCommitted = false;
         try {
             if (isRolledback()) {
@@ -120,6 +166,14 @@
                 return false;
             }
 
+            // verify our tx is the current tx associated with the thread
+            // this is really only an error case and should never happen, but just to be sure double check
+            // immedately before committing using the transaction manager
+            Transaction currentTransaction = txnManager.getTransaction();
+            if (currentTransaction != transaction) {
+                throw new SystemException("An unknown transaction is currently associated with the thread: expectedTx=" + transaction + ", currentTx=" + currentTransaction);
+            }
+
             txnManager.commit();
             wasCommitted = true;
         } catch (Throwable t) {
@@ -130,23 +184,82 @@
             } catch (Throwable e) {
                 rollbackAndThrow("After commit of container transaction failed", e);
             } finally {
+                unassociateAll();
                 connectorAfterCommit();
                 transaction = null;
+                threadAssociated = false;
             }
         }
         return wasCommitted;
     }
 
+    private void beforeCommit() throws Throwable {
+        // @todo allow for enrollment during pre-commit
+        ArrayList toFlush = getAssociatedContexts();
+        for (Iterator i = toFlush.iterator(); i.hasNext();) {
+            InstanceContext context = (InstanceContext) i.next();
+            if (!context.isDead()) {
+                context.beforeCommit();
+            }
+        }
+    }
+
+    private void afterCommit(boolean status) throws Throwable {
+        Throwable firstThrowable = null;
+        ArrayList toFlush = getAssociatedContexts();
+        for (Iterator i = toFlush.iterator(); i.hasNext();) {
+            InstanceContext context = (InstanceContext) i.next();
+            if (!context.isDead()) {
+                try {
+                    context.afterCommit(status);
+                } catch (Throwable e) {
+                    if (firstThrowable == null) {
+                        firstThrowable = e;
+                    }
+                }
+            }
+        }
+
+        if (firstThrowable instanceof Error) {
+            throw (Error) firstThrowable;
+        } else if (firstThrowable instanceof Exception) {
+            throw (Exception) firstThrowable;
+        } else if (firstThrowable != null) {
+            throw (SystemException) new SystemException().initCause(firstThrowable);
+        }
+    }
+
+    private void connectorAfterCommit() {
+        if (managedConnections != null) {
+            for (Iterator entries = managedConnections.entrySet().iterator(); entries.hasNext();) {
+                Map.Entry entry = (Map.Entry) entries.next();
+                ConnectionReleaser key = (ConnectionReleaser) entry.getKey();
+                key.afterCompletion(entry.getValue());
+            }
+            //If BeanTransactionContext never reuses the same instance for sequential BMT, this
+            //clearing is unnecessary.
+            managedConnections.clear();
+        }
+    }
+
     private boolean isRolledback() throws SystemException {
         int status;
         try {
             status = transaction.getStatus();
         } catch (SystemException e) {
-            txnManager.rollback();
+            transaction.rollback();
             throw e;
         }
 
         if (status == Status.STATUS_MARKED_ROLLBACK) {
+            // verify our tx is the current tx associated with the thread
+            // this is really only an error case and should never happen, but just to be sure double check
+            // immedately before committing using the transaction manager
+            Transaction currentTransaction = txnManager.getTransaction();
+            if (currentTransaction != transaction) {
+                throw new SystemException("An unknown transaction is currently associated with the thread: expectedTx=" + transaction + ", currentTx=" + currentTransaction);
+            }
+
             // we need to rollback
             txnManager.rollback();
             return true;
@@ -160,7 +273,6 @@
 
     private void rollbackAndThrow(String message, Throwable throwable) throws HeuristicMixedException, HeuristicRollbackException, SystemException, RollbackException {
         try {
-            // just incase there is a junk transaction on the thread
             if (txnManager.getStatus() != Status.STATUS_NO_TRANSACTION) {
                 txnManager.rollback();
             }
@@ -168,6 +280,18 @@
             log.error("Unable to roll back transaction", t);
         }
 
+        try {
+            // make doubly sure our transaction was rolled back
+            // this can happen when there was a junk transaction on the thread
+            int status = transaction.getStatus();
+            if (status != Status.STATUS_ROLLEDBACK &&
+                    status != Status.STATUS_ROLLING_BACK) {
+                transaction.rollback();
+            }
+        } catch (Throwable t) {
+            log.error("Unable to roll back transaction", t);
+        }
+
         if (throwable instanceof HeuristicMixedException) {
             throw (HeuristicMixedException) throwable;
         } else if (throwable instanceof HeuristicRollbackException) {
@@ -182,41 +306,6 @@
             throw (RuntimeException) throwable;
         } else {
             throw (SystemException) new SystemException(message).initCause(throwable);
-        }
-    }
-
-    public void rollback() throws SystemException {
-        try {
-            try {
-                if (txnManager.getStatus() != Status.STATUS_NO_TRANSACTION) {
-                    txnManager.rollback();
-                }
-            } finally {
-                try {
-                    afterCommit(false);
-                } catch (Throwable e) {
-                    try {
-                        // just incase there is a junk transaction on the thread
-                        if (txnManager.getStatus() != Status.STATUS_NO_TRANSACTION) {
-                            txnManager.rollback();
-                        }
-                    } catch (Throwable t1) {
-                        log.error("Unable to roll back transaction", t1);
-                    }
-
-                    if (e instanceof SystemException) {
-                        throw (SystemException) e;
-                    } else if (e instanceof Error) {
-                        throw (Error) e;
-                    } else if (e instanceof RuntimeException) {
-                        throw (RuntimeException) e;
-                    }
-                    throw (SystemException) new SystemException("After commit of container transaction failed").initCause(e);
-                }
-            }
-        } finally {
-            connectorAfterCommit();
-            transaction = null;
         }
     }
 }

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/TransactionContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/TransactionContext.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/TransactionContext.java (original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/TransactionContext.java Fri Feb 25 15:10:24 2005
@@ -18,27 +18,21 @@
 package org.apache.geronimo.transaction.context;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
 import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
 import javax.transaction.InvalidTransactionException;
 import javax.transaction.RollbackException;
 import javax.transaction.SystemException;
-import javax.transaction.Transaction;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.geronimo.transaction.ConnectionReleaser;
 import org.apache.geronimo.transaction.DoubleKeyedHashMap;
 import org.apache.geronimo.transaction.InstanceContext;
 import org.tranql.cache.InTxCache;
 
 
 /**
- *
- *
  * @version $Rev$ $Date$
  */
 public abstract class TransactionContext {
@@ -56,9 +50,12 @@
     private InstanceContext currentContext;
     private final DoubleKeyedHashMap associatedContexts = new DoubleKeyedHashMap();
     private final DoubleKeyedHashMap dirtyContexts = new DoubleKeyedHashMap();
-    private Map managedConnections;
     private InTxCache inTxCache;
 
+    public abstract boolean getRollbackOnly() throws SystemException;
+
+    public abstract void setRollbackOnly() throws SystemException;
+
     public abstract void suspend() throws SystemException;
 
     public abstract void resume() throws SystemException, InvalidTransactionException;
@@ -73,21 +70,51 @@
         }
     }
 
-    public final void unassociate(Object containerId, Object id) throws Exception {
-        associatedContexts.remove(containerId, id);
-        dirtyContexts.remove(containerId, id);
+    public final void unassociate(InstanceContext context) throws Throwable {
+        associatedContexts.remove(context.getContainerId(), context.getId());
+        context.unassociate();
+    }
+
+    public final void unassociate(Object containerId, Object id) throws Throwable {
+        InstanceContext context = (InstanceContext) associatedContexts.remove(containerId, id);
+        if (context != null) {
+            context.unassociate();
+        }
+    }
+
+    public final InstanceContext getContext(Object containerId, Object id) {
+        return (InstanceContext) associatedContexts.get(containerId, id);
+    }
+
+    protected final ArrayList getAssociatedContexts() {
+        return new ArrayList(associatedContexts.values());
+    }
+
+    protected final void unassociateAll() {
+        ArrayList toFlush = getAssociatedContexts();
+        for (Iterator i = toFlush.iterator(); i.hasNext();) {
+            InstanceContext context = (InstanceContext) i.next();
+            try {
+                context.unassociate();
+            } catch (Throwable throwable) {
+                log.warn("Error while unassociating instance from transaction context: " + context, throwable);
+            }
+        }
     }
 
-    public final InstanceContext beginInvocation(InstanceContext context) {
+    public final InstanceContext beginInvocation(InstanceContext context) throws Throwable {
         if (context.getId() != null) {
+            associate(context);
             dirtyContexts.put(context.getContainerId(), context.getId(), context);
         }
+        context.enter();
         InstanceContext caller = currentContext;
         currentContext = context;
         return caller;
     }
 
     public final void endInvocation(InstanceContext caller) {
+        currentContext.exit();
         currentContext = caller;
     }
 
@@ -97,7 +124,9 @@
             dirtyContexts.clear();
             for (Iterator i = toFlush.iterator(); i.hasNext();) {
                 InstanceContext context = (InstanceContext) i.next();
-                context.flush();
+                if (!context.isDead()) {
+                    context.flush();
+                }
             }
         }
         if (currentContext != null && currentContext.getId() != null) {
@@ -108,42 +137,6 @@
         }
     }
 
-    protected void beforeCommit() throws Throwable {
-        // @todo allow for enrollment during pre-commit
-        ArrayList toFlush = new ArrayList(associatedContexts.values());
-        for (Iterator i = toFlush.iterator(); i.hasNext();) {
-            InstanceContext context = (InstanceContext) i.next();
-            context.beforeCommit();
-        }
-    }
-
-    protected void afterCommit(boolean status) throws Throwable {
-        Throwable firstThrowable = null;
-        ArrayList toFlush = new ArrayList(associatedContexts.values());
-        for (Iterator i = toFlush.iterator(); i.hasNext();) {
-            InstanceContext context = (InstanceContext) i.next();
-            try {
-                context.afterCommit(status);
-            } catch (Throwable e) {
-                if (firstThrowable == null) {
-                    firstThrowable = e;
-                }
-            }
-        }
-
-        if (firstThrowable instanceof Error) {
-            throw (Error) firstThrowable;
-        } else if (firstThrowable instanceof Exception) {
-            throw (Exception) firstThrowable;
-        } else if (firstThrowable != null) {
-            throw (SystemException) new SystemException().initCause(firstThrowable);
-        }
-    }
-
-    public final InstanceContext getContext(Object containerId, Object id) {
-        return (InstanceContext) associatedContexts.get(containerId, id);
-    }
-
     public final void setInTxCache(InTxCache inTxCache) {
         this.inTxCache = inTxCache;
     }
@@ -151,42 +144,4 @@
     public final InTxCache getInTxCache() {
         return inTxCache;
     }
-
-    //Geronimo connector framework support
-    public void setManagedConnectionInfo(ConnectionReleaser key, Object info) {
-        if (managedConnections == null) {
-            managedConnections = new HashMap();
-        }
-        managedConnections.put(key, info);
-    }
-
-    public Object getManagedConnectionInfo(ConnectionReleaser key) {
-        if (managedConnections == null) {
-            return null;
-        }
-        return managedConnections.get(key);
-    }
-
-    /**
-     * determines if the transaction is in a pre-prepared state
-     * of STATUS_ACTIVE or STATUS_MARKED_ROLLBACK.
-     * @return true if more work can be done in the transaction (although it might be forced to roll back)
-     */
-    public abstract boolean isActive();
-
-    public abstract Transaction getTransaction();
-
-    protected void connectorAfterCommit() {
-        if (managedConnections != null) {
-            for (Iterator entries = managedConnections.entrySet().iterator(); entries.hasNext();) {
-                Map.Entry entry = (Map.Entry) entries.next();
-                ConnectionReleaser key = (ConnectionReleaser) entry.getKey();
-                key.afterCompletion(entry.getValue());
-            }
-            //If BeanTransactionContext never reuses the same instance for sequential BMT, this
-            //clearing is unnecessary.
-            managedConnections.clear();
-        }
-    }
-
 }

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/UnspecifiedTransactionContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/UnspecifiedTransactionContext.java?view=diff&r1=155375&r2=155376
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/UnspecifiedTransactionContext.java (original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/context/UnspecifiedTransactionContext.java Fri Feb 25 15:10:24 2005
@@ -17,16 +17,18 @@
 
 package org.apache.geronimo.transaction.context;
 
-import javax.transaction.Transaction;
-
-import org.apache.geronimo.transaction.ConnectionReleaser;
-
-
 /**
  * @version $Rev$ $Date$
  */
 public class UnspecifiedTransactionContext extends TransactionContext {
-    public void begin() {
+    private boolean failed = false;
+
+    public boolean getRollbackOnly() {
+        return failed;
+    }
+
+    public void setRollbackOnly() {
+        this.failed = true;
     }
 
     public void suspend() {
@@ -36,33 +38,28 @@
     }
 
     public boolean commit() {
+        complete();
+        return true;
+    }
+
+    public void rollback() {
+        setRollbackOnly();
+        complete();
+    }
+
+    private void complete() {
         try {
-            flushState();
+            if (!failed) {
+                flushState();
+            }
         } catch (Error e) {
             throw e;
         } catch (RuntimeException re) {
             throw re;
         } catch (Throwable e) {
             log.error("Unable to flush state, continuing", e);
+        } finally {
+            unassociateAll();
         }
-        return true;
-    }
-
-    public void rollback() {
-    }
-
-    public void setManagedConnectionInfo(ConnectionReleaser key, Object info) {
-    }
-
-    public Object getManagedConnectionInfo(ConnectionReleaser key) {
-        return null;
-    }
-
-    public boolean isActive() {
-        return false;
-    }
-
-    public Transaction getTransaction() {
-        return null;
     }
 }



Re: svn commit: r155376 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/ connector/src/test/org/apache/geronimo/connector/outbound/ timer/src/java/org/apache/geronimo/timer/ timer/src/test/org/apache/geronimo/timer/ transaction/src/java/org/apache/geronimo/transaction/ transaction/src/java/org/apache/geronimo/transaction/context/

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Saturday 26 February 2005 09:14, David Jencks wrote:
> On Feb 25, 2005, at 4:45 PM, Dain Sundstrom wrote:


Are you guys really so busy that you can't snip large message out of replies??
Not everyone sits on broadband, and I am sure infrastructure are not too happy 
about 50MB of unnecessary mail bandwidth, either...

Thanks!
Niclas

Re: svn commit: r155376 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/ connector/src/test/org/apache/geronimo/connector/outbound/ timer/src/java/org/apache/geronimo/timer/ timer/src/test/org/apache/geronimo/timer/ transaction/src/java/org/apache/geronimo/transaction/ transaction/src/java/org/apache/geronimo/transaction/context/

Posted by David Jencks <da...@yahoo.com>.
On Feb 25, 2005, at 4:45 PM, Dain Sundstrom wrote:

> There are very few uses of isAcive and getManagerconnectionInfos in  
> the code, and most of those cases already use  
> InheritableTransactionalContext (or ContainerTransactionContext).   
> Also isActive and getManagedconnectionInfos don't make sense for a  
> non-tx based context.

Sure they do.  isActive is false, and getManagedConnectionInfos returns  
an empty object or null.  That way the connection management code  
doesn't need to know about the inheritance hierarchy of   
TransactionContext, something it really doesn't care or need to know  
about.
>   I used the rule of thumb that the methods on the TxContext should  
> make since for all since for tx and non-tx based contexts.  If they  
> don't make since, you should make sure you are dealing with the  
> correct subclass.

Why do you think isActive doesn't make sense?  Is there some  
circumstance in which an UnspecifiedTransactionContext might be partly  
associated with an active transaction?

david jencks
>
> -dain
>
> On Feb 25, 2005, at 4:12 PM, David Jencks wrote:
>
>> what is the point of removing the isActive() and  
>> getManagedConnectionInfos() methods from TransactionContext and  
>> forcing all the clients to do a lot of type testing and casting?
>>
>> david jencks
>>
>> On Feb 25, 2005, at 3:10 PM, dain@apache.org wrote:
>>
>>> Author: dain
>>> Date: Fri Feb 25 15:10:24 2005
>>> New Revision: 155376
>>>
>>> URL: http://svn.apache.org/viewcvs?view=rev&rev=155376
>>> Log:
>>> Fixed bugs in TransactionContext and handling of the contexts  
>>> unturned by turning back on in-tx caching
>>> Added support for entrancy tracking and killing InstanceContexts
>>>
>>> Modified:
>>>      
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptor.java
>>>      
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionEnlistingInterceptor.java
>>>      
>>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptorTest.java
>>>      
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> NontransactionalExecutorTask.java
>>>      
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> ThreadPooledTimer.java
>>>      
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> TransactionalExecutorTask.java
>>>      
>>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>>> AbstractThreadPooledTimerTest.java
>>>      
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/DefaultInstanceContext.java
>>>      
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/InstanceContext.java
>>>      
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/InheritableTransactionContext.java
>>>      
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/TransactionContext.java
>>>      
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/UnspecifiedTransactionContext.java
>>>
>>> Modified:  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptor.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>>> java/org/apache/geronimo/connector/outbound/ 
>>> TransactionCachingInterceptor.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptor.java (original)
>>> +++  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptor.java Fri Feb 25  
>>> 15:10:24 2005
>>> @@ -27,6 +27,7 @@
>>>  import org.apache.geronimo.transaction.ConnectionReleaser;
>>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>>  import  
>>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>> +import  
>>> org.apache.geronimo.transaction.context.InheritableTransactionContext 
>>> ;
>>>
>>>  /**
>>>   * TransactionCachingInterceptor.java
>>> @@ -59,16 +60,15 @@
>>>      }
>>>
>>>      public void getConnection(ConnectionInfo connectionInfo) throws  
>>> ResourceException {
>>> -        TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>>          //There can be an inactive transaction context when a  
>>> connection is requested in
>>>          //Synchronization.afterCompletion().
>>> -        if (transactionContext == null ||  
>>> !transactionContext.isActive()) {
>>> -            next.getConnection(connectionInfo);
>>> -        } else {
>>> -            ManagedConnectionInfos managedConnectionInfos =  
>>> (ManagedConnectionInfos)  
>>> transactionContext.getManagedConnectionInfo(this);
>>> +        TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>> +        if ((transactionContext instanceof  
>>> InheritableTransactionContext) && ((InheritableTransactionContext)  
>>> transactionContext).isActive()) {
>>> +            InheritableTransactionContext  
>>> inheritableTransactionContext = ((InheritableTransactionContext)  
>>> transactionContext);
>>> +            ManagedConnectionInfos managedConnectionInfos =  
>>> (ManagedConnectionInfos)  
>>> inheritableTransactionContext.getManagedConnectionInfo(this);
>>>              if (managedConnectionInfos == null) {
>>>                  managedConnectionInfos = new  
>>> ManagedConnectionInfos();
>>> -                transactionContext.setManagedConnectionInfo(this,  
>>> managedConnectionInfos);
>>> +                 
>>> inheritableTransactionContext.setManagedConnectionInfo(this,  
>>> managedConnectionInfos);
>>>              }
>>>              if (connectionInfo.isUnshareable()) {
>>>                  if  
>>> (! 
>>> managedConnectionInfos.containsUnshared(connectionInfo.getManagedConn 
>>> ectionInfo())) {
>>> @@ -85,6 +85,8 @@
>>>                       
>>> managedConnectionInfos.setShared(connectionInfo.getManagedConnectionI 
>>> nfo());
>>>                  }
>>>              }
>>> +        } else {
>>> +            next.getConnection(connectionInfo);
>>>          }
>>>      }
>>>
>>> @@ -96,7 +98,7 @@
>>>          }
>>>
>>>          TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>> -        if (transactionContext != null &&  
>>> transactionContext.isActive()) {
>>> +        if ((transactionContext instanceof  
>>> InheritableTransactionContext) && ((InheritableTransactionContext)  
>>> transactionContext).isActive()) {
>>>              return;
>>>          }
>>>          internalReturn(connectionInfo, connectionReturnAction);
>>>
>>> Modified:  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionEnlistingInterceptor.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>>> java/org/apache/geronimo/connector/outbound/ 
>>> TransactionEnlistingInterceptor.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionEnlistingInterceptor.java (original)
>>> +++  
>>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>>> connector/outbound/TransactionEnlistingInterceptor.java Fri Feb 25  
>>> 15:10:24 2005
>>> @@ -24,6 +24,7 @@
>>>
>>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>>  import  
>>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>> +import  
>>> org.apache.geronimo.transaction.context.InheritableTransactionContext 
>>> ;
>>>
>>>  /**
>>>   * TransactionEnlistingInterceptor.java
>>> @@ -48,9 +49,12 @@
>>>          try {
>>>              ManagedConnectionInfo mci =  
>>> connectionInfo.getManagedConnectionInfo();
>>>              TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>> -            if (transactionContext != null &&  
>>> transactionContext.isActive()) {
>>> -                XAResource xares = mci.getXAResource();
>>> -                 
>>> transactionContext.getTransaction().enlistResource(xares);
>>> +            if ((transactionContext instanceof  
>>> InheritableTransactionContext)) {
>>> +                InheritableTransactionContext  
>>> inheritableTransactionContext = ((InheritableTransactionContext)  
>>> transactionContext);
>>> +                if (inheritableTransactionContext.isActive()) {
>>> +                    XAResource xares = mci.getXAResource();
>>> +                     
>>> inheritableTransactionContext.getTransaction().enlistResource(xares);
>>> +                }
>>>              }
>>>
>>>          } catch (SystemException e) {
>>> @@ -76,9 +80,12 @@
>>>          try {
>>>              ManagedConnectionInfo mci =  
>>> connectionInfo.getManagedConnectionInfo();
>>>              TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>> -            if (transactionContext != null &&  
>>> transactionContext.isActive()) {
>>> -                XAResource xares = mci.getXAResource();
>>> -                 
>>> transactionContext.getTransaction().delistResource(xares,  
>>> XAResource.TMSUSPEND);
>>> +            if ((transactionContext instanceof  
>>> InheritableTransactionContext)) {
>>> +                InheritableTransactionContext  
>>> inheritableTransactionContext = ((InheritableTransactionContext)  
>>> transactionContext);
>>> +                if (inheritableTransactionContext.isActive()) {
>>> +                    XAResource xares = mci.getXAResource();
>>> +                     
>>> inheritableTransactionContext.getTransaction().delistResource(xares,  
>>> XAResource.TMSUSPEND);
>>> +                }
>>>              }
>>>
>>>          } catch (SystemException e) {
>>>
>>> Modified:  
>>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptorTest.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>>> test/org/apache/geronimo/connector/outbound/ 
>>> TransactionCachingInterceptorTest.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptorTest.java (original)
>>> +++  
>>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>>> connector/outbound/TransactionCachingInterceptorTest.java Fri Feb 25  
>>> 15:10:24 2005
>>> @@ -127,8 +127,6 @@
>>>           
>>> transactionCachingInterceptor.getConnection(connectionInfo1);
>>>          assertTrue("Expected to get an initial connection",  
>>> obtainedConnectionInfo != null);
>>>          assertTrue("Expected nothing returned yet",  
>>> returnedConnectionInfo == null);
>>> -        assertTrue("Expected no ManagedConnectionInfo in the  
>>> TransactionContext",
>>> -                null ==  
>>> transactionContextManager.getContext().getManagedConnectionInfo(trans 
>>> actionCachingInterceptor));
>>>          obtainedConnectionInfo = null;
>>>          ConnectionInfo connectionInfo2 = makeConnectionInfo();
>>>           
>>> transactionCachingInterceptor.getConnection(connectionInfo2);
>>> @@ -136,18 +134,12 @@
>>>          assertTrue("Expected nothing returned yet",  
>>> returnedConnectionInfo == null);
>>>          assertTrue("Expected different ManagedConnectionInfo in  
>>> both ConnectionInfos",
>>>                  connectionInfo1.getManagedConnectionInfo() !=  
>>> connectionInfo2.getManagedConnectionInfo());
>>> -        assertTrue("Expected no ManagedConnectionInfo in the  
>>> TransactionContext",
>>> -                null ==  
>>> transactionContextManager.getContext().getManagedConnectionInfo(trans 
>>> actionCachingInterceptor));
>>>          //we didn't create any handles, so the "ManagedConnection"  
>>> should be returned.
>>> -        assertTrue("Expected TransactionContext to report  
>>> inactive", !transactionContextManager.getContext().isActive());
>>>           
>>> transactionCachingInterceptor.returnConnection(connectionInfo1,  
>>> ConnectionReturnAction.RETURN_HANDLE);
>>>          assertTrue("Expected connection to be returned",  
>>> returnedConnectionInfo != null);
>>>          returnedConnectionInfo = null;
>>>           
>>> transactionCachingInterceptor.returnConnection(connectionInfo2,  
>>> ConnectionReturnAction.RETURN_HANDLE);
>>>          assertTrue("Expected connection to be returned",  
>>> returnedConnectionInfo != null);
>>> -
>>> -        assertTrue("Expected TransactionContext to report  
>>> inactive", !transactionContextManager.getContext().isActive());
>>> -
>>>      }
>>>
>>>      public void testTransactionIndependence() throws Exception {
>>>
>>> Modified:  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> NontransactionalExecutorTask.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>>> org/apache/geronimo/timer/NontransactionalExecutorTask.java? 
>>> view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> NontransactionalExecutorTask.java (original)
>>> +++  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> NontransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
>>> @@ -19,14 +19,12 @@
>>>
>>>  import org.apache.commons.logging.Log;
>>>  import org.apache.commons.logging.LogFactory;
>>> -import org.apache.geronimo.timer.ExecutorTask;
>>> +import org.apache.geronimo.transaction.context.TransactionContext;
>>> +import  
>>> org.apache.geronimo.transaction.context.UnspecifiedTransactionContext 
>>> ;
>>>
>>>  /**
>>> - *
>>> - *
>>>   * @version $Rev$ $Date$
>>> - *
>>> - * */
>>> + */
>>>  public class NontransactionalExecutorTask implements ExecutorTask {
>>>
>>>      private static final Log log =  
>>> LogFactory.getLog(NontransactionalExecutorTask.class);
>>> @@ -42,18 +40,26 @@
>>>      }
>>>
>>>      public void run() {
>>> +        UnspecifiedTransactionContext transactionContext = new  
>>> UnspecifiedTransactionContext();
>>> +        TransactionContext oldTransactionContext =  
>>> TransactionContext.getContext();
>>> +        TransactionContext.setContext(transactionContext);
>>>          try {
>>> -            userTask.run();
>>> -        } catch (Exception e) {
>>> -            log.info(e);
>>> -        }
>>> -        try {
>>> -            threadPooledTimer.workPerformed(workInfo);
>>> -        } catch (PersistenceException e) {
>>> -            log.info(e);
>>> -        }
>>> -        if (workInfo.isOneTime()) {
>>> -            threadPooledTimer.removeWorkInfo(workInfo);
>>> +            try {
>>> +                userTask.run();
>>> +            } catch (Exception e) {
>>> +                log.info(e);
>>> +            }
>>> +            try {
>>> +                threadPooledTimer.workPerformed(workInfo);
>>> +            } catch (PersistenceException e) {
>>> +                log.info(e);
>>> +            }
>>> +            if (workInfo.isOneTime()) {
>>> +                threadPooledTimer.removeWorkInfo(workInfo);
>>> +            }
>>> +        } finally {
>>> +            transactionContext.commit();
>>> +            TransactionContext.setContext(oldTransactionContext);
>>>          }
>>>      }
>>>
>>>
>>> Modified:  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> ThreadPooledTimer.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>>> org/apache/geronimo/timer/ThreadPooledTimer.java? 
>>> view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> ThreadPooledTimer.java (original)
>>> +++  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> ThreadPooledTimer.java Fri Feb 25 15:10:24 2005
>>> @@ -37,6 +37,7 @@
>>>  import org.apache.geronimo.gbean.GBeanLifecycle;
>>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>>  import  
>>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>> +import  
>>> org.apache.geronimo.transaction.context.InheritableTransactionContext 
>>> ;
>>>  import org.apache.commons.logging.Log;
>>>  import org.apache.commons.logging.LogFactory;
>>>
>>> @@ -243,13 +244,21 @@
>>>
>>>      void registerSynchronization(Synchronization sync) throws  
>>> RollbackException, SystemException {
>>>          TransactionContext transactionContext =  
>>> transactionContextManager.getContext();
>>> +
>>>          //TODO move the registerSynchronization to the  
>>> TransactionContext
>>> -        Transaction transaction = transactionContext == null? null:  
>>> transactionContext.getTransaction();
>>> +        Transaction transaction;
>>> +        if (transactionContext instanceof  
>>> InheritableTransactionContext) {
>>> +            InheritableTransactionContext  
>>> inheritableTransactionContext = ((InheritableTransactionContext)  
>>> transactionContext);
>>> +            transaction =  
>>> inheritableTransactionContext.getTransaction();
>>> +            assert transaction == null ||  
>>> inheritableTransactionContext.isActive(): "Trying to register a sync  
>>> on an inactive transaction context";
>>> +        } else {
>>> +            transaction = null;
>>> +        }
>>> +
>>>          if (transaction == null) {
>>>              sync.beforeCompletion();
>>>              sync.afterCompletion(Status.STATUS_COMMITTED);
>>>          } else {
>>> -            assert transactionContext.isActive(): "Trying to  
>>> register a sync on an inactive transaction context";
>>>              transaction.registerSynchronization(sync);
>>>          }
>>>      }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> TransactionalExecutorTask.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>>> org/apache/geronimo/timer/TransactionalExecutorTask.java? 
>>> view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> TransactionalExecutorTask.java (original)
>>> +++  
>>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>>> TransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
>>> @@ -17,26 +17,14 @@
>>>
>>>  package org.apache.geronimo.timer;
>>>
>>> -import javax.transaction.HeuristicMixedException;
>>> -import javax.transaction.HeuristicRollbackException;
>>> -import javax.transaction.NotSupportedException;
>>> -import javax.transaction.RollbackException;
>>> -import javax.transaction.SystemException;
>>> -
>>>  import org.apache.commons.logging.Log;
>>>  import org.apache.commons.logging.LogFactory;
>>>  import  
>>> org.apache.geronimo.transaction.context.ContainerTransactionContext;
>>>  import  
>>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>> -import org.apache.geronimo.timer.ExecutorTask;
>>> -import org.apache.geronimo.timer.PersistenceException;
>>> -import org.apache.geronimo.timer.ThreadPooledTimer;
>>>
>>>  /**
>>> - *
>>> - *
>>>   * @version $Rev$ $Date$
>>> - *
>>> - * */
>>> + */
>>>  public class TransactionalExecutorTask implements ExecutorTask {
>>>      private static final Log log =  
>>> LogFactory.getLog(TransactionalExecutorTask.class);
>>>
>>> @@ -54,49 +42,38 @@
>>>          this.transactionContextManager = transactionContextManager;
>>>          this.repeatCount = repeatCount;
>>>      }
>>> -
>>> +
>>>      public void run() {
>>>          ContainerTransactionContext transactionContext = null;
>>>          for (int tries = 0; tries < repeatCount; tries++) {
>>>              try {
>>>                  transactionContext =  
>>> transactionContextManager.newContainerTransactionContext();
>>> -            } catch (NotSupportedException e) {
>>> -                log.info(e);
>>> -                break;
>>> -            } catch (SystemException e) {
>>> -                log.info(e);
>>> +            } catch (Exception e) {
>>> +                log.info("Exception occured while starting  
>>> container transaction", e);
>>>                  break;
>>>              }
>>>              try {
>>>                  try {
>>>                      userTask.run();
>>>                  } catch (Exception e) {
>>> -                    log.info(e);
>>> +                    log.info("Exception occured while running user  
>>> task", e);
>>>                  }
>>>                  try {
>>>                      threadPooledTimer.workPerformed(workInfo);
>>>                  } catch (PersistenceException e) {
>>> -                    log.info(e);
>>> +                    log.info("Exception occured while updating  
>>> timer persistent state", e);
>>>                  }
>>>              } finally {
>>>                  try {
>>> -                    if (transactionContext.getRollbackOnly()) {
>>> -                        transactionContext.rollback();
>>> -                    } else {
>>> -                        transactionContext.commit();
>>> +                    if (transactionContext.commit()) {
>>>                          if (workInfo.isOneTime()) {
>>>                               
>>> threadPooledTimer.removeWorkInfo(workInfo);
>>>                          }
>>> +                        // todo this is a very weird code  
>>> structure.... returning from a finally is very confusing
>>>                          return;
>>>                      }
>>> -                } catch (SystemException e) {
>>> -                    log.info(e);
>>> -                } catch (HeuristicMixedException e) {
>>> -                    log.info(e);
>>> -                } catch (HeuristicRollbackException e) {
>>> -                    log.info(e);
>>> -                } catch (RollbackException e) {
>>> -                    log.info(e);
>>> +                } catch (Exception e) {
>>> +                    log.info("Exception occured while completing  
>>> container transaction", e);
>>>                  }
>>>              }
>>>          }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>>> AbstractThreadPooledTimerTest.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/test/ 
>>> org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java? 
>>> view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>>> AbstractThreadPooledTimerTest.java (original)
>>> +++  
>>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>>> AbstractThreadPooledTimerTest.java Fri Feb 25 15:10:24 2005
>>> @@ -23,11 +23,6 @@
>>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>>  import  
>>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>>  import org.apache.geronimo.timer.vm.VMWorkerPersistence;
>>> -import org.apache.geronimo.timer.ExecutorTaskFactory;
>>> -import org.apache.geronimo.timer.ThreadPooledTimer;
>>> -import org.apache.geronimo.timer.UserTaskFactory;
>>> -import org.apache.geronimo.timer.WorkerPersistence;
>>> -import org.apache.geronimo.timer.WorkInfo;
>>>
>>>  /**
>>>   *
>>> @@ -73,7 +68,7 @@
>>>          for (long i = 0; i < COUNT; i++) {
>>>              timer.schedule(userTaskFactory, key, userId, userKey,  
>>> i);
>>>          }
>>> -        Thread.currentThread().sleep(COUNT + SLOP);
>>> +        Thread.sleep(COUNT + SLOP);
>>>          assertEquals(COUNT, counter.get());
>>>      }
>>>
>>> @@ -85,7 +80,7 @@
>>>          for (int i = 0; i < workInfos.length; i++) {
>>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>>          }
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(0, counter.get());
>>>      }
>>>
>>> @@ -98,7 +93,7 @@
>>>
>>>          timer.doStart();
>>>          timer.playback(key, userTaskFactory);
>>> -        Thread.currentThread().sleep(2 * SLOP + DELAY);
>>> +        Thread.sleep(2 * SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>      }
>>>
>>> @@ -134,48 +129,48 @@
>>>          for (long i = 0; i < COUNT; i++) {
>>>              timer.schedule(userTaskFactory, key, userId, userKey,  
>>> i);
>>>          }
>>> -        Thread.currentThread().sleep(COUNT + SLOP);
>>> +        Thread.sleep(COUNT + SLOP);
>>>          assertEquals(0, counter.get());
>>>          transactionContext.commit();
>>> -        Thread.currentThread().sleep(COUNT + SLOP);
>>> +        Thread.sleep(COUNT + SLOP);
>>>          assertEquals(COUNT, counter.get());
>>>      }
>>>
>>>      public void testCancelInCommittedTransaction() throws Exception  
>>> {
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>>>          for (long i = 0; i < COUNT; i++) {
>>>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
>>> userTaskFactory, userId, userKey, DELAY, DELAY);
>>>          }
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>          TransactionContext transactionContext =  
>>> transactionContextManager.newContainerTransactionContext();
>>>          for (int i = 0; i < workInfos.length; i++) {
>>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>>          }
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>          transactionContext.commit();
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>      }
>>>
>>>      public void testCancelInRolledBackTransaction() throws  
>>> Exception {
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>>>          for (long i = 0; i < COUNT; i++) {
>>>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
>>> userTaskFactory, userId, userKey, DELAY, DELAY);
>>>          }
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>          TransactionContext transactionContext =  
>>> transactionContextManager.newContainerTransactionContext();
>>>          for (int i = 0; i < workInfos.length; i++) {
>>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>>          }
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          assertEquals(COUNT, counter.get());
>>>          transactionContext.rollback();
>>> -        Thread.currentThread().sleep(SLOP + DELAY);
>>> +        Thread.sleep(SLOP + DELAY);
>>>          // Catches up with two periods.
>>>          assertEquals(3 * COUNT, counter.get());
>>>      }
>>> @@ -183,13 +178,13 @@
>>>      public void testRepeatCountFromPersisted() throws Exception {
>>>          assert DELAY > 2 * SLOP;
>>>          timer.scheduleAtFixedRate(key, userTaskFactory, userId,  
>>> userKey, 0L, DELAY);
>>> -        Thread.currentThread().sleep(4 * DELAY + SLOP);
>>> +        Thread.sleep(4 * DELAY + SLOP);
>>>          timer.doStop();
>>>          assertEquals(5, counter.get());
>>>
>>>          timer.doStart();
>>>          timer.playback(key, userTaskFactory);
>>> -        Thread.currentThread().sleep(5 * DELAY + SLOP);
>>> +        Thread.sleep(5 * DELAY + SLOP);
>>>          assertEquals(2 * 5, counter.get());
>>>
>>>      }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/DefaultInstanceContext.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/ 
>>> src/java/org/apache/geronimo/transaction/ 
>>> DefaultInstanceContext.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/DefaultInstanceContext.java (original)
>>> +++  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/DefaultInstanceContext.java Fri Feb 25 15:10:24 2005
>>> @@ -29,10 +29,11 @@
>>>   *
>>>   * */
>>>  public class DefaultInstanceContext implements InstanceContext {
>>> -
>>>      private final Map connectionManagerMap = new HashMap();
>>>      private final Set unshareableResources;
>>>      private final Set applicationManagedSecurityResources;
>>> +    private int callDepth;
>>> +    private boolean dead = false;
>>>
>>>      public DefaultInstanceContext(Set unshareableResources, Set  
>>> applicationManagedSecurityResources) {
>>>          this.unshareableResources = unshareableResources;
>>> @@ -43,9 +44,6 @@
>>>          return null;
>>>      }
>>>
>>> -    public void setId(Object id) {
>>> -    }
>>> -
>>>      public Object getContainerId() {
>>>          return null;
>>>      }
>>> @@ -62,6 +60,9 @@
>>>      public void afterCommit(boolean status) throws Exception {
>>>      }
>>>
>>> +    public void unassociate() throws Throwable {
>>> +    }
>>> +
>>>      public Map getConnectionManagerMap() {
>>>          return connectionManagerMap;
>>>      }
>>> @@ -74,4 +75,24 @@
>>>          return applicationManagedSecurityResources;
>>>      }
>>>
>>> +    public boolean isInCall() {
>>> +        return callDepth > 0;
>>> +    }
>>> +
>>> +    public void enter() {
>>> +        callDepth++;
>>> +    }
>>> +
>>> +    public void exit() {
>>> +        assert isInCall();
>>> +        callDepth--;
>>> +    }
>>> +
>>> +    public boolean isDead() {
>>> +        return dead;
>>> +    }
>>> +
>>> +    public void die() {
>>> +        dead = true;
>>> +    }
>>>  }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/InstanceContext.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/ 
>>> src/java/org/apache/geronimo/transaction/InstanceContext.java? 
>>> view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/InstanceContext.java (original)
>>> +++  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/InstanceContext.java Fri Feb 25 15:10:24 2005
>>> @@ -29,8 +29,6 @@
>>>  public interface InstanceContext {
>>>      Object getId();
>>>
>>> -    void setId(Object id);
>>> -
>>>      Object getContainerId();
>>>
>>>      void associate() throws Throwable;
>>> @@ -41,6 +39,8 @@
>>>
>>>      void afterCommit(boolean status) throws Throwable;
>>>
>>> +    void unassociate() throws Throwable;
>>> +
>>>      /**
>>>       * IMPORTANT INVARIANT: this should always return a map, never  
>>> null.
>>>       * @return map of ConnectionManager to (list of ) managed  
>>> connection info objects.
>>> @@ -51,4 +51,13 @@
>>>
>>>      Set getApplicationManagedSecurityResources();
>>>
>>> +    boolean isInCall();
>>> +
>>> +    void enter();
>>> +
>>> +    void exit();
>>> +
>>> +    boolean isDead();
>>> +
>>> +    void die();
>>>  }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/InheritableTransactionContext.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/ 
>>> src/java/org/apache/geronimo/transaction/context/ 
>>> InheritableTransactionContext.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/InheritableTransactionContext.java (original)
>>> +++  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/InheritableTransactionContext.java Fri Feb 25  
>>> 15:10:24 2005
>>> @@ -17,6 +17,10 @@
>>>
>>>  package org.apache.geronimo.transaction.context;
>>>
>>> +import java.util.Iterator;
>>> +import java.util.Map;
>>> +import java.util.HashMap;
>>> +import java.util.ArrayList;
>>>  import javax.transaction.SystemException;
>>>  import javax.transaction.Status;
>>>  import javax.transaction.Transaction;
>>> @@ -27,16 +31,17 @@
>>>  import javax.transaction.RollbackException;
>>>
>>>  import org.apache.geronimo.transaction.ExtendedTransactionManager;
>>> +import org.apache.geronimo.transaction.ConnectionReleaser;
>>> +import org.apache.geronimo.transaction.InstanceContext;
>>>
>>>  /**
>>> - *
>>> - *
>>>   * @version $Rev$ $Date$
>>>   */
>>>  public abstract class InheritableTransactionContext extends  
>>> TransactionContext {
>>>      private final ExtendedTransactionManager txnManager;
>>>      private Transaction transaction;
>>>      private boolean threadAssociated = false;
>>> +    private Map managedConnections;
>>>
>>>      protected  
>>> InheritableTransactionContext(ExtendedTransactionManager txnManager)  
>>> {
>>>          this.txnManager = txnManager;
>>> @@ -55,9 +60,26 @@
>>>          return transaction;
>>>      }
>>>
>>> +    public void setManagedConnectionInfo(ConnectionReleaser key,  
>>> Object info) {
>>> +        if (managedConnections == null) {
>>> +            managedConnections = new HashMap();
>>> +        }
>>> +        managedConnections.put(key, info);
>>> +    }
>>> +
>>> +    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>>> +        if (managedConnections == null) {
>>> +            return null;
>>> +        }
>>> +        return managedConnections.get(key);
>>> +    }
>>> +
>>>      public boolean isActive() {
>>> +        if (transaction == null) {
>>> +            return false;
>>> +        }
>>>          try {
>>> -            int status = txnManager.getStatus();
>>> +            int status = transaction.getStatus();
>>>              return status == Status.STATUS_ACTIVE || status ==  
>>> Status.STATUS_MARKED_ROLLBACK;
>>>          } catch (SystemException e) {
>>>              return false;
>>> @@ -65,7 +87,6 @@
>>>      }
>>>
>>>      public boolean getRollbackOnly() throws SystemException {
>>> -        Transaction transaction = getTransaction();
>>>          if (transaction == null) {
>>>              throw new IllegalStateException("There is no  
>>> transaction in progress.");
>>>          }
>>> @@ -77,7 +98,6 @@
>>>      }
>>>
>>>      public void setRollbackOnly() throws IllegalStateException,  
>>> SystemException {
>>> -        Transaction transaction = getTransaction();
>>>          if (transaction == null) {
>>>              throw new IllegalStateException("There is no  
>>> transaction in progress.");
>>>          }
>>> @@ -85,13 +105,16 @@
>>>      }
>>>
>>>      public void begin(long transactionTimeoutMilliseconds) throws  
>>> SystemException, NotSupportedException {
>>> +        assert transaction == null:  "Already associated with a  
>>> transaction";
>>>          transaction =  
>>> txnManager.begin(transactionTimeoutMilliseconds);
>>>          threadAssociated = true;
>>>      }
>>>
>>>      public void suspend() throws SystemException {
>>>          Transaction suspendedTransaction = txnManager.suspend();
>>> -        assert (transaction == suspendedTransaction) : "suspend did  
>>> not return our transaction. ours: " + transaction + ", suspended  
>>> returned: " + suspendedTransaction;
>>> +        if (transaction != suspendedTransaction) {
>>> +            throw new SystemException("Suspend did not return our  
>>> transaction: expectedTx=" + transaction + ", suspendedTx=" +  
>>> suspendedTransaction);
>>> +        }
>>>          threadAssociated = false;
>>>      }
>>>
>>> @@ -101,6 +124,29 @@
>>>      }
>>>
>>>      public boolean commit() throws HeuristicMixedException,  
>>> HeuristicRollbackException, SystemException, RollbackException {
>>> +        return complete();
>>> +    }
>>> +
>>> +    public void rollback() throws SystemException {
>>> +        setRollbackOnly();
>>> +        try {
>>> +            complete();
>>> +        } catch (SystemException e) {
>>> +            throw e;
>>> +        } catch (RuntimeException e) {
>>> +            throw e;
>>> +        } catch (Error e) {
>>> +            throw e;
>>> +        } catch (Exception e) {
>>> +            throw (SystemException) new SystemException("After  
>>> commit of container transaction failed").initCause(e);
>>> +        }
>>> +    }
>>> +
>>> +    private boolean complete() throws HeuristicMixedException,  
>>> HeuristicRollbackException, SystemException, RollbackException {
>>> +        if (transaction == null) {
>>> +            throw new IllegalStateException("There is no  
>>> transaction in progress.");
>>> +        }
>>> +
>>>          boolean wasCommitted = false;
>>>          try {
>>>              if (isRolledback()) {
>>> @@ -120,6 +166,14 @@
>>>                  return false;
>>>              }
>>>
>>> +            // verify our tx is the current tx associated with the  
>>> thread
>>> +            // this is really only an error case and should never  
>>> happen, but just to be sure double check
>>> +            // immedately before committing using the transaction  
>>> manager
>>> +            Transaction currentTransaction =  
>>> txnManager.getTransaction();
>>> +            if (currentTransaction != transaction) {
>>> +                throw new SystemException("An unknown transaction  
>>> is currently associated with the thread: expectedTx=" + transaction  
>>> + ", currentTx=" + currentTransaction);
>>> +            }
>>> +
>>>              txnManager.commit();
>>>              wasCommitted = true;
>>>          } catch (Throwable t) {
>>> @@ -130,23 +184,82 @@
>>>              } catch (Throwable e) {
>>>                  rollbackAndThrow("After commit of container  
>>> transaction failed", e);
>>>              } finally {
>>> +                unassociateAll();
>>>                  connectorAfterCommit();
>>>                  transaction = null;
>>> +                threadAssociated = false;
>>>              }
>>>          }
>>>          return wasCommitted;
>>>      }
>>>
>>> +    private void beforeCommit() throws Throwable {
>>> +        // @todo allow for enrollment during pre-commit
>>> +        ArrayList toFlush = getAssociatedContexts();
>>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>> +            InstanceContext context = (InstanceContext) i.next();
>>> +            if (!context.isDead()) {
>>> +                context.beforeCommit();
>>> +            }
>>> +        }
>>> +    }
>>> +
>>> +    private void afterCommit(boolean status) throws Throwable {
>>> +        Throwable firstThrowable = null;
>>> +        ArrayList toFlush = getAssociatedContexts();
>>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>> +            InstanceContext context = (InstanceContext) i.next();
>>> +            if (!context.isDead()) {
>>> +                try {
>>> +                    context.afterCommit(status);
>>> +                } catch (Throwable e) {
>>> +                    if (firstThrowable == null) {
>>> +                        firstThrowable = e;
>>> +                    }
>>> +                }
>>> +            }
>>> +        }
>>> +
>>> +        if (firstThrowable instanceof Error) {
>>> +            throw (Error) firstThrowable;
>>> +        } else if (firstThrowable instanceof Exception) {
>>> +            throw (Exception) firstThrowable;
>>> +        } else if (firstThrowable != null) {
>>> +            throw (SystemException) new  
>>> SystemException().initCause(firstThrowable);
>>> +        }
>>> +    }
>>> +
>>> +    private void connectorAfterCommit() {
>>> +        if (managedConnections != null) {
>>> +            for (Iterator entries =  
>>> managedConnections.entrySet().iterator(); entries.hasNext();) {
>>> +                Map.Entry entry = (Map.Entry) entries.next();
>>> +                ConnectionReleaser key = (ConnectionReleaser)  
>>> entry.getKey();
>>> +                key.afterCompletion(entry.getValue());
>>> +            }
>>> +            //If BeanTransactionContext never reuses the same  
>>> instance for sequential BMT, this
>>> +            //clearing is unnecessary.
>>> +            managedConnections.clear();
>>> +        }
>>> +    }
>>> +
>>>      private boolean isRolledback() throws SystemException {
>>>          int status;
>>>          try {
>>>              status = transaction.getStatus();
>>>          } catch (SystemException e) {
>>> -            txnManager.rollback();
>>> +            transaction.rollback();
>>>              throw e;
>>>          }
>>>
>>>          if (status == Status.STATUS_MARKED_ROLLBACK) {
>>> +            // verify our tx is the current tx associated with the  
>>> thread
>>> +            // this is really only an error case and should never  
>>> happen, but just to be sure double check
>>> +            // immedately before committing using the transaction  
>>> manager
>>> +            Transaction currentTransaction =  
>>> txnManager.getTransaction();
>>> +            if (currentTransaction != transaction) {
>>> +                throw new SystemException("An unknown transaction  
>>> is currently associated with the thread: expectedTx=" + transaction  
>>> + ", currentTx=" + currentTransaction);
>>> +            }
>>> +
>>>              // we need to rollback
>>>              txnManager.rollback();
>>>              return true;
>>> @@ -160,7 +273,6 @@
>>>
>>>      private void rollbackAndThrow(String message, Throwable  
>>> throwable) throws HeuristicMixedException,  
>>> HeuristicRollbackException, SystemException, RollbackException {
>>>          try {
>>> -            // just incase there is a junk transaction on the thread
>>>              if (txnManager.getStatus() !=  
>>> Status.STATUS_NO_TRANSACTION) {
>>>                  txnManager.rollback();
>>>              }
>>> @@ -168,6 +280,18 @@
>>>              log.error("Unable to roll back transaction", t);
>>>          }
>>>
>>> +        try {
>>> +            // make doubly sure our transaction was rolled back
>>> +            // this can happen when there was a junk transaction on  
>>> the thread
>>> +            int status = transaction.getStatus();
>>> +            if (status != Status.STATUS_ROLLEDBACK &&
>>> +                    status != Status.STATUS_ROLLING_BACK) {
>>> +                transaction.rollback();
>>> +            }
>>> +        } catch (Throwable t) {
>>> +            log.error("Unable to roll back transaction", t);
>>> +        }
>>> +
>>>          if (throwable instanceof HeuristicMixedException) {
>>>              throw (HeuristicMixedException) throwable;
>>>          } else if (throwable instanceof HeuristicRollbackException)  
>>> {
>>> @@ -182,41 +306,6 @@
>>>              throw (RuntimeException) throwable;
>>>          } else {
>>>              throw (SystemException) new  
>>> SystemException(message).initCause(throwable);
>>> -        }
>>> -    }
>>> -
>>> -    public void rollback() throws SystemException {
>>> -        try {
>>> -            try {
>>> -                if (txnManager.getStatus() !=  
>>> Status.STATUS_NO_TRANSACTION) {
>>> -                    txnManager.rollback();
>>> -                }
>>> -            } finally {
>>> -                try {
>>> -                    afterCommit(false);
>>> -                } catch (Throwable e) {
>>> -                    try {
>>> -                        // just incase there is a junk transaction  
>>> on the thread
>>> -                        if (txnManager.getStatus() !=  
>>> Status.STATUS_NO_TRANSACTION) {
>>> -                            txnManager.rollback();
>>> -                        }
>>> -                    } catch (Throwable t1) {
>>> -                        log.error("Unable to roll back  
>>> transaction", t1);
>>> -                    }
>>> -
>>> -                    if (e instanceof SystemException) {
>>> -                        throw (SystemException) e;
>>> -                    } else if (e instanceof Error) {
>>> -                        throw (Error) e;
>>> -                    } else if (e instanceof RuntimeException) {
>>> -                        throw (RuntimeException) e;
>>> -                    }
>>> -                    throw (SystemException) new  
>>> SystemException("After commit of container transaction  
>>> failed").initCause(e);
>>> -                }
>>> -            }
>>> -        } finally {
>>> -            connectorAfterCommit();
>>> -            transaction = null;
>>>          }
>>>      }
>>>  }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/TransactionContext.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/ 
>>> src/java/org/apache/geronimo/transaction/context/ 
>>> TransactionContext.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/TransactionContext.java (original)
>>> +++  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/TransactionContext.java Fri Feb 25 15:10:24 2005
>>> @@ -18,27 +18,21 @@
>>>  package org.apache.geronimo.transaction.context;
>>>
>>>  import java.util.ArrayList;
>>> -import java.util.HashMap;
>>>  import java.util.Iterator;
>>> -import java.util.Map;
>>>  import javax.transaction.HeuristicMixedException;
>>>  import javax.transaction.HeuristicRollbackException;
>>>  import javax.transaction.InvalidTransactionException;
>>>  import javax.transaction.RollbackException;
>>>  import javax.transaction.SystemException;
>>> -import javax.transaction.Transaction;
>>>
>>>  import org.apache.commons.logging.Log;
>>>  import org.apache.commons.logging.LogFactory;
>>> -import org.apache.geronimo.transaction.ConnectionReleaser;
>>>  import org.apache.geronimo.transaction.DoubleKeyedHashMap;
>>>  import org.apache.geronimo.transaction.InstanceContext;
>>>  import org.tranql.cache.InTxCache;
>>>
>>>
>>>  /**
>>> - *
>>> - *
>>>   * @version $Rev$ $Date$
>>>   */
>>>  public abstract class TransactionContext {
>>> @@ -56,9 +50,12 @@
>>>      private InstanceContext currentContext;
>>>      private final DoubleKeyedHashMap associatedContexts = new  
>>> DoubleKeyedHashMap();
>>>      private final DoubleKeyedHashMap dirtyContexts = new  
>>> DoubleKeyedHashMap();
>>> -    private Map managedConnections;
>>>      private InTxCache inTxCache;
>>>
>>> +    public abstract boolean getRollbackOnly() throws  
>>> SystemException;
>>> +
>>> +    public abstract void setRollbackOnly() throws SystemException;
>>> +
>>>      public abstract void suspend() throws SystemException;
>>>
>>>      public abstract void resume() throws SystemException,  
>>> InvalidTransactionException;
>>> @@ -73,21 +70,51 @@
>>>          }
>>>      }
>>>
>>> -    public final void unassociate(Object containerId, Object id)  
>>> throws Exception {
>>> -        associatedContexts.remove(containerId, id);
>>> -        dirtyContexts.remove(containerId, id);
>>> +    public final void unassociate(InstanceContext context) throws  
>>> Throwable {
>>> +        associatedContexts.remove(context.getContainerId(),  
>>> context.getId());
>>> +        context.unassociate();
>>> +    }
>>> +
>>> +    public final void unassociate(Object containerId, Object id)  
>>> throws Throwable {
>>> +        InstanceContext context = (InstanceContext)  
>>> associatedContexts.remove(containerId, id);
>>> +        if (context != null) {
>>> +            context.unassociate();
>>> +        }
>>> +    }
>>> +
>>> +    public final InstanceContext getContext(Object containerId,  
>>> Object id) {
>>> +        return (InstanceContext)  
>>> associatedContexts.get(containerId, id);
>>> +    }
>>> +
>>> +    protected final ArrayList getAssociatedContexts() {
>>> +        return new ArrayList(associatedContexts.values());
>>> +    }
>>> +
>>> +    protected final void unassociateAll() {
>>> +        ArrayList toFlush = getAssociatedContexts();
>>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>> +            InstanceContext context = (InstanceContext) i.next();
>>> +            try {
>>> +                context.unassociate();
>>> +            } catch (Throwable throwable) {
>>> +                log.warn("Error while unassociating instance from  
>>> transaction context: " + context, throwable);
>>> +            }
>>> +        }
>>>      }
>>>
>>> -    public final InstanceContext beginInvocation(InstanceContext  
>>> context) {
>>> +    public final InstanceContext beginInvocation(InstanceContext  
>>> context) throws Throwable {
>>>          if (context.getId() != null) {
>>> +            associate(context);
>>>              dirtyContexts.put(context.getContainerId(),  
>>> context.getId(), context);
>>>          }
>>> +        context.enter();
>>>          InstanceContext caller = currentContext;
>>>          currentContext = context;
>>>          return caller;
>>>      }
>>>
>>>      public final void endInvocation(InstanceContext caller) {
>>> +        currentContext.exit();
>>>          currentContext = caller;
>>>      }
>>>
>>> @@ -97,7 +124,9 @@
>>>              dirtyContexts.clear();
>>>              for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>>                  InstanceContext context = (InstanceContext)  
>>> i.next();
>>> -                context.flush();
>>> +                if (!context.isDead()) {
>>> +                    context.flush();
>>> +                }
>>>              }
>>>          }
>>>          if (currentContext != null && currentContext.getId() !=  
>>> null) {
>>> @@ -108,42 +137,6 @@
>>>          }
>>>      }
>>>
>>> -    protected void beforeCommit() throws Throwable {
>>> -        // @todo allow for enrollment during pre-commit
>>> -        ArrayList toFlush = new  
>>> ArrayList(associatedContexts.values());
>>> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>> -            InstanceContext context = (InstanceContext) i.next();
>>> -            context.beforeCommit();
>>> -        }
>>> -    }
>>> -
>>> -    protected void afterCommit(boolean status) throws Throwable {
>>> -        Throwable firstThrowable = null;
>>> -        ArrayList toFlush = new  
>>> ArrayList(associatedContexts.values());
>>> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>> -            InstanceContext context = (InstanceContext) i.next();
>>> -            try {
>>> -                context.afterCommit(status);
>>> -            } catch (Throwable e) {
>>> -                if (firstThrowable == null) {
>>> -                    firstThrowable = e;
>>> -                }
>>> -            }
>>> -        }
>>> -
>>> -        if (firstThrowable instanceof Error) {
>>> -            throw (Error) firstThrowable;
>>> -        } else if (firstThrowable instanceof Exception) {
>>> -            throw (Exception) firstThrowable;
>>> -        } else if (firstThrowable != null) {
>>> -            throw (SystemException) new  
>>> SystemException().initCause(firstThrowable);
>>> -        }
>>> -    }
>>> -
>>> -    public final InstanceContext getContext(Object containerId,  
>>> Object id) {
>>> -        return (InstanceContext)  
>>> associatedContexts.get(containerId, id);
>>> -    }
>>> -
>>>      public final void setInTxCache(InTxCache inTxCache) {
>>>          this.inTxCache = inTxCache;
>>>      }
>>> @@ -151,42 +144,4 @@
>>>      public final InTxCache getInTxCache() {
>>>          return inTxCache;
>>>      }
>>> -
>>> -    //Geronimo connector framework support
>>> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
>>> Object info) {
>>> -        if (managedConnections == null) {
>>> -            managedConnections = new HashMap();
>>> -        }
>>> -        managedConnections.put(key, info);
>>> -    }
>>> -
>>> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>>> -        if (managedConnections == null) {
>>> -            return null;
>>> -        }
>>> -        return managedConnections.get(key);
>>> -    }
>>> -
>>> -    /**
>>> -     * determines if the transaction is in a pre-prepared state
>>> -     * of STATUS_ACTIVE or STATUS_MARKED_ROLLBACK.
>>> -     * @return true if more work can be done in the transaction  
>>> (although it might be forced to roll back)
>>> -     */
>>> -    public abstract boolean isActive();
>>> -
>>> -    public abstract Transaction getTransaction();
>>> -
>>> -    protected void connectorAfterCommit() {
>>> -        if (managedConnections != null) {
>>> -            for (Iterator entries =  
>>> managedConnections.entrySet().iterator(); entries.hasNext();) {
>>> -                Map.Entry entry = (Map.Entry) entries.next();
>>> -                ConnectionReleaser key = (ConnectionReleaser)  
>>> entry.getKey();
>>> -                key.afterCompletion(entry.getValue());
>>> -            }
>>> -            //If BeanTransactionContext never reuses the same  
>>> instance for sequential BMT, this
>>> -            //clearing is unnecessary.
>>> -            managedConnections.clear();
>>> -        }
>>> -    }
>>> -
>>>  }
>>>
>>> Modified:  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/UnspecifiedTransactionContext.java
>>> URL:  
>>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/ 
>>> src/java/org/apache/geronimo/transaction/context/ 
>>> UnspecifiedTransactionContext.java?view=diff&r1=155375&r2=155376
>>> ===================================================================== 
>>> =========
>>> ---  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/UnspecifiedTransactionContext.java (original)
>>> +++  
>>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>>> transaction/context/UnspecifiedTransactionContext.java Fri Feb 25  
>>> 15:10:24 2005
>>> @@ -17,16 +17,18 @@
>>>
>>>  package org.apache.geronimo.transaction.context;
>>>
>>> -import javax.transaction.Transaction;
>>> -
>>> -import org.apache.geronimo.transaction.ConnectionReleaser;
>>> -
>>> -
>>>  /**
>>>   * @version $Rev$ $Date$
>>>   */
>>>  public class UnspecifiedTransactionContext extends  
>>> TransactionContext {
>>> -    public void begin() {
>>> +    private boolean failed = false;
>>> +
>>> +    public boolean getRollbackOnly() {
>>> +        return failed;
>>> +    }
>>> +
>>> +    public void setRollbackOnly() {
>>> +        this.failed = true;
>>>      }
>>>
>>>      public void suspend() {
>>> @@ -36,33 +38,28 @@
>>>      }
>>>
>>>      public boolean commit() {
>>> +        complete();
>>> +        return true;
>>> +    }
>>> +
>>> +    public void rollback() {
>>> +        setRollbackOnly();
>>> +        complete();
>>> +    }
>>> +
>>> +    private void complete() {
>>>          try {
>>> -            flushState();
>>> +            if (!failed) {
>>> +                flushState();
>>> +            }
>>>          } catch (Error e) {
>>>              throw e;
>>>          } catch (RuntimeException re) {
>>>              throw re;
>>>          } catch (Throwable e) {
>>>              log.error("Unable to flush state, continuing", e);
>>> +        } finally {
>>> +            unassociateAll();
>>>          }
>>> -        return true;
>>> -    }
>>> -
>>> -    public void rollback() {
>>> -    }
>>> -
>>> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
>>> Object info) {
>>> -    }
>>> -
>>> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>>> -        return null;
>>> -    }
>>> -
>>> -    public boolean isActive() {
>>> -        return false;
>>> -    }
>>> -
>>> -    public Transaction getTransaction() {
>>> -        return null;
>>>      }
>>>  }
>>>
>>>
>


Re: svn commit: r155376 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/ connector/src/test/org/apache/geronimo/connector/outbound/ timer/src/java/org/apache/geronimo/timer/ timer/src/test/org/apache/geronimo/timer/ transaction/src/java/org/apache/geronimo/transaction/ transaction/src/java/org/apache/geronimo/transaction/context/

Posted by Dain Sundstrom <ds...@gluecode.com>.
There are very few uses of isAcive and getManagerconnectionInfos in the  
code, and most of those cases already use  
InheritableTransactionalContext (or ContainerTransactionContext).  Also  
isActive and getManagedconnectionInfos don't make sense for a non-tx  
based context.  I used the rule of thumb that the methods on the  
TxContext should make since for all since for tx and non-tx based  
contexts.  If they don't make since, you should make sure you are  
dealing with the correct subclass.

-dain

On Feb 25, 2005, at 4:12 PM, David Jencks wrote:

> what is the point of removing the isActive() and  
> getManagedConnectionInfos() methods from TransactionContext and  
> forcing all the clients to do a lot of type testing and casting?
>
> david jencks
>
> On Feb 25, 2005, at 3:10 PM, dain@apache.org wrote:
>
>> Author: dain
>> Date: Fri Feb 25 15:10:24 2005
>> New Revision: 155376
>>
>> URL: http://svn.apache.org/viewcvs?view=rev&rev=155376
>> Log:
>> Fixed bugs in TransactionContext and handling of the contexts  
>> unturned by turning back on in-tx caching
>> Added support for entrancy tracking and killing InstanceContexts
>>
>> Modified:
>>      
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptor.java
>>      
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionEnlistingInterceptor.java
>>      
>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptorTest.java
>>      
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> NontransactionalExecutorTask.java
>>      
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> ThreadPooledTimer.java
>>      
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> TransactionalExecutorTask.java
>>      
>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>> AbstractThreadPooledTimerTest.java
>>      
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/DefaultInstanceContext.java
>>      
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/InstanceContext.java
>>      
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/InheritableTransactionContext.java
>>      
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/TransactionContext.java
>>      
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/UnspecifiedTransactionContext.java
>>
>> Modified:  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptor.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>> java/org/apache/geronimo/connector/outbound/ 
>> TransactionCachingInterceptor.java?view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptor.java (original)
>> +++  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptor.java Fri Feb 25  
>> 15:10:24 2005
>> @@ -27,6 +27,7 @@
>>  import org.apache.geronimo.transaction.ConnectionReleaser;
>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>  import  
>> org.apache.geronimo.transaction.context.TransactionContextManager;
>> +import  
>> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>>
>>  /**
>>   * TransactionCachingInterceptor.java
>> @@ -59,16 +60,15 @@
>>      }
>>
>>      public void getConnection(ConnectionInfo connectionInfo) throws  
>> ResourceException {
>> -        TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>>          //There can be an inactive transaction context when a  
>> connection is requested in
>>          //Synchronization.afterCompletion().
>> -        if (transactionContext == null ||  
>> !transactionContext.isActive()) {
>> -            next.getConnection(connectionInfo);
>> -        } else {
>> -            ManagedConnectionInfos managedConnectionInfos =  
>> (ManagedConnectionInfos)  
>> transactionContext.getManagedConnectionInfo(this);
>> +        TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>> +        if ((transactionContext instanceof  
>> InheritableTransactionContext) && ((InheritableTransactionContext)  
>> transactionContext).isActive()) {
>> +            InheritableTransactionContext  
>> inheritableTransactionContext = ((InheritableTransactionContext)  
>> transactionContext);
>> +            ManagedConnectionInfos managedConnectionInfos =  
>> (ManagedConnectionInfos)  
>> inheritableTransactionContext.getManagedConnectionInfo(this);
>>              if (managedConnectionInfos == null) {
>>                  managedConnectionInfos = new  
>> ManagedConnectionInfos();
>> -                transactionContext.setManagedConnectionInfo(this,  
>> managedConnectionInfos);
>> +                 
>> inheritableTransactionContext.setManagedConnectionInfo(this,  
>> managedConnectionInfos);
>>              }
>>              if (connectionInfo.isUnshareable()) {
>>                  if  
>> (! 
>> managedConnectionInfos.containsUnshared(connectionInfo.getManagedConne 
>> ctionInfo())) {
>> @@ -85,6 +85,8 @@
>>                       
>> managedConnectionInfos.setShared(connectionInfo.getManagedConnectionIn 
>> fo());
>>                  }
>>              }
>> +        } else {
>> +            next.getConnection(connectionInfo);
>>          }
>>      }
>>
>> @@ -96,7 +98,7 @@
>>          }
>>
>>          TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>> -        if (transactionContext != null &&  
>> transactionContext.isActive()) {
>> +        if ((transactionContext instanceof  
>> InheritableTransactionContext) && ((InheritableTransactionContext)  
>> transactionContext).isActive()) {
>>              return;
>>          }
>>          internalReturn(connectionInfo, connectionReturnAction);
>>
>> Modified:  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionEnlistingInterceptor.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>> java/org/apache/geronimo/connector/outbound/ 
>> TransactionEnlistingInterceptor.java?view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionEnlistingInterceptor.java (original)
>> +++  
>> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
>> connector/outbound/TransactionEnlistingInterceptor.java Fri Feb 25  
>> 15:10:24 2005
>> @@ -24,6 +24,7 @@
>>
>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>  import  
>> org.apache.geronimo.transaction.context.TransactionContextManager;
>> +import  
>> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>>
>>  /**
>>   * TransactionEnlistingInterceptor.java
>> @@ -48,9 +49,12 @@
>>          try {
>>              ManagedConnectionInfo mci =  
>> connectionInfo.getManagedConnectionInfo();
>>              TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>> -            if (transactionContext != null &&  
>> transactionContext.isActive()) {
>> -                XAResource xares = mci.getXAResource();
>> -                 
>> transactionContext.getTransaction().enlistResource(xares);
>> +            if ((transactionContext instanceof  
>> InheritableTransactionContext)) {
>> +                InheritableTransactionContext  
>> inheritableTransactionContext = ((InheritableTransactionContext)  
>> transactionContext);
>> +                if (inheritableTransactionContext.isActive()) {
>> +                    XAResource xares = mci.getXAResource();
>> +                     
>> inheritableTransactionContext.getTransaction().enlistResource(xares);
>> +                }
>>              }
>>
>>          } catch (SystemException e) {
>> @@ -76,9 +80,12 @@
>>          try {
>>              ManagedConnectionInfo mci =  
>> connectionInfo.getManagedConnectionInfo();
>>              TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>> -            if (transactionContext != null &&  
>> transactionContext.isActive()) {
>> -                XAResource xares = mci.getXAResource();
>> -                 
>> transactionContext.getTransaction().delistResource(xares,  
>> XAResource.TMSUSPEND);
>> +            if ((transactionContext instanceof  
>> InheritableTransactionContext)) {
>> +                InheritableTransactionContext  
>> inheritableTransactionContext = ((InheritableTransactionContext)  
>> transactionContext);
>> +                if (inheritableTransactionContext.isActive()) {
>> +                    XAResource xares = mci.getXAResource();
>> +                     
>> inheritableTransactionContext.getTransaction().delistResource(xares,  
>> XAResource.TMSUSPEND);
>> +                }
>>              }
>>
>>          } catch (SystemException e) {
>>
>> Modified:  
>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptorTest.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
>> test/org/apache/geronimo/connector/outbound/ 
>> TransactionCachingInterceptorTest.java?view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptorTest.java (original)
>> +++  
>> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
>> connector/outbound/TransactionCachingInterceptorTest.java Fri Feb 25  
>> 15:10:24 2005
>> @@ -127,8 +127,6 @@
>>          transactionCachingInterceptor.getConnection(connectionInfo1);
>>          assertTrue("Expected to get an initial connection",  
>> obtainedConnectionInfo != null);
>>          assertTrue("Expected nothing returned yet",  
>> returnedConnectionInfo == null);
>> -        assertTrue("Expected no ManagedConnectionInfo in the  
>> TransactionContext",
>> -                null ==  
>> transactionContextManager.getContext().getManagedConnectionInfo(transa 
>> ctionCachingInterceptor));
>>          obtainedConnectionInfo = null;
>>          ConnectionInfo connectionInfo2 = makeConnectionInfo();
>>          transactionCachingInterceptor.getConnection(connectionInfo2);
>> @@ -136,18 +134,12 @@
>>          assertTrue("Expected nothing returned yet",  
>> returnedConnectionInfo == null);
>>          assertTrue("Expected different ManagedConnectionInfo in both  
>> ConnectionInfos",
>>                  connectionInfo1.getManagedConnectionInfo() !=  
>> connectionInfo2.getManagedConnectionInfo());
>> -        assertTrue("Expected no ManagedConnectionInfo in the  
>> TransactionContext",
>> -                null ==  
>> transactionContextManager.getContext().getManagedConnectionInfo(transa 
>> ctionCachingInterceptor));
>>          //we didn't create any handles, so the "ManagedConnection"  
>> should be returned.
>> -        assertTrue("Expected TransactionContext to report inactive",  
>> !transactionContextManager.getContext().isActive());
>>           
>> transactionCachingInterceptor.returnConnection(connectionInfo1,  
>> ConnectionReturnAction.RETURN_HANDLE);
>>          assertTrue("Expected connection to be returned",  
>> returnedConnectionInfo != null);
>>          returnedConnectionInfo = null;
>>           
>> transactionCachingInterceptor.returnConnection(connectionInfo2,  
>> ConnectionReturnAction.RETURN_HANDLE);
>>          assertTrue("Expected connection to be returned",  
>> returnedConnectionInfo != null);
>> -
>> -        assertTrue("Expected TransactionContext to report inactive",  
>> !transactionContextManager.getContext().isActive());
>> -
>>      }
>>
>>      public void testTransactionIndependence() throws Exception {
>>
>> Modified:  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> NontransactionalExecutorTask.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>> org/apache/geronimo/timer/NontransactionalExecutorTask.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> NontransactionalExecutorTask.java (original)
>> +++  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> NontransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
>> @@ -19,14 +19,12 @@
>>
>>  import org.apache.commons.logging.Log;
>>  import org.apache.commons.logging.LogFactory;
>> -import org.apache.geronimo.timer.ExecutorTask;
>> +import org.apache.geronimo.transaction.context.TransactionContext;
>> +import  
>> org.apache.geronimo.transaction.context.UnspecifiedTransactionContext;
>>
>>  /**
>> - *
>> - *
>>   * @version $Rev$ $Date$
>> - *
>> - * */
>> + */
>>  public class NontransactionalExecutorTask implements ExecutorTask {
>>
>>      private static final Log log =  
>> LogFactory.getLog(NontransactionalExecutorTask.class);
>> @@ -42,18 +40,26 @@
>>      }
>>
>>      public void run() {
>> +        UnspecifiedTransactionContext transactionContext = new  
>> UnspecifiedTransactionContext();
>> +        TransactionContext oldTransactionContext =  
>> TransactionContext.getContext();
>> +        TransactionContext.setContext(transactionContext);
>>          try {
>> -            userTask.run();
>> -        } catch (Exception e) {
>> -            log.info(e);
>> -        }
>> -        try {
>> -            threadPooledTimer.workPerformed(workInfo);
>> -        } catch (PersistenceException e) {
>> -            log.info(e);
>> -        }
>> -        if (workInfo.isOneTime()) {
>> -            threadPooledTimer.removeWorkInfo(workInfo);
>> +            try {
>> +                userTask.run();
>> +            } catch (Exception e) {
>> +                log.info(e);
>> +            }
>> +            try {
>> +                threadPooledTimer.workPerformed(workInfo);
>> +            } catch (PersistenceException e) {
>> +                log.info(e);
>> +            }
>> +            if (workInfo.isOneTime()) {
>> +                threadPooledTimer.removeWorkInfo(workInfo);
>> +            }
>> +        } finally {
>> +            transactionContext.commit();
>> +            TransactionContext.setContext(oldTransactionContext);
>>          }
>>      }
>>
>>
>> Modified:  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> ThreadPooledTimer.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>> org/apache/geronimo/timer/ThreadPooledTimer.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> ThreadPooledTimer.java (original)
>> +++  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> ThreadPooledTimer.java Fri Feb 25 15:10:24 2005
>> @@ -37,6 +37,7 @@
>>  import org.apache.geronimo.gbean.GBeanLifecycle;
>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>  import  
>> org.apache.geronimo.transaction.context.TransactionContextManager;
>> +import  
>> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>>  import org.apache.commons.logging.Log;
>>  import org.apache.commons.logging.LogFactory;
>>
>> @@ -243,13 +244,21 @@
>>
>>      void registerSynchronization(Synchronization sync) throws  
>> RollbackException, SystemException {
>>          TransactionContext transactionContext =  
>> transactionContextManager.getContext();
>> +
>>          //TODO move the registerSynchronization to the  
>> TransactionContext
>> -        Transaction transaction = transactionContext == null? null:  
>> transactionContext.getTransaction();
>> +        Transaction transaction;
>> +        if (transactionContext instanceof  
>> InheritableTransactionContext) {
>> +            InheritableTransactionContext  
>> inheritableTransactionContext = ((InheritableTransactionContext)  
>> transactionContext);
>> +            transaction =  
>> inheritableTransactionContext.getTransaction();
>> +            assert transaction == null ||  
>> inheritableTransactionContext.isActive(): "Trying to register a sync  
>> on an inactive transaction context";
>> +        } else {
>> +            transaction = null;
>> +        }
>> +
>>          if (transaction == null) {
>>              sync.beforeCompletion();
>>              sync.afterCompletion(Status.STATUS_COMMITTED);
>>          } else {
>> -            assert transactionContext.isActive(): "Trying to  
>> register a sync on an inactive transaction context";
>>              transaction.registerSynchronization(sync);
>>          }
>>      }
>>
>> Modified:  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> TransactionalExecutorTask.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
>> org/apache/geronimo/timer/TransactionalExecutorTask.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> TransactionalExecutorTask.java (original)
>> +++  
>> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
>> TransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
>> @@ -17,26 +17,14 @@
>>
>>  package org.apache.geronimo.timer;
>>
>> -import javax.transaction.HeuristicMixedException;
>> -import javax.transaction.HeuristicRollbackException;
>> -import javax.transaction.NotSupportedException;
>> -import javax.transaction.RollbackException;
>> -import javax.transaction.SystemException;
>> -
>>  import org.apache.commons.logging.Log;
>>  import org.apache.commons.logging.LogFactory;
>>  import  
>> org.apache.geronimo.transaction.context.ContainerTransactionContext;
>>  import  
>> org.apache.geronimo.transaction.context.TransactionContextManager;
>> -import org.apache.geronimo.timer.ExecutorTask;
>> -import org.apache.geronimo.timer.PersistenceException;
>> -import org.apache.geronimo.timer.ThreadPooledTimer;
>>
>>  /**
>> - *
>> - *
>>   * @version $Rev$ $Date$
>> - *
>> - * */
>> + */
>>  public class TransactionalExecutorTask implements ExecutorTask {
>>      private static final Log log =  
>> LogFactory.getLog(TransactionalExecutorTask.class);
>>
>> @@ -54,49 +42,38 @@
>>          this.transactionContextManager = transactionContextManager;
>>          this.repeatCount = repeatCount;
>>      }
>> -
>> +
>>      public void run() {
>>          ContainerTransactionContext transactionContext = null;
>>          for (int tries = 0; tries < repeatCount; tries++) {
>>              try {
>>                  transactionContext =  
>> transactionContextManager.newContainerTransactionContext();
>> -            } catch (NotSupportedException e) {
>> -                log.info(e);
>> -                break;
>> -            } catch (SystemException e) {
>> -                log.info(e);
>> +            } catch (Exception e) {
>> +                log.info("Exception occured while starting container  
>> transaction", e);
>>                  break;
>>              }
>>              try {
>>                  try {
>>                      userTask.run();
>>                  } catch (Exception e) {
>> -                    log.info(e);
>> +                    log.info("Exception occured while running user  
>> task", e);
>>                  }
>>                  try {
>>                      threadPooledTimer.workPerformed(workInfo);
>>                  } catch (PersistenceException e) {
>> -                    log.info(e);
>> +                    log.info("Exception occured while updating timer  
>> persistent state", e);
>>                  }
>>              } finally {
>>                  try {
>> -                    if (transactionContext.getRollbackOnly()) {
>> -                        transactionContext.rollback();
>> -                    } else {
>> -                        transactionContext.commit();
>> +                    if (transactionContext.commit()) {
>>                          if (workInfo.isOneTime()) {
>>                               
>> threadPooledTimer.removeWorkInfo(workInfo);
>>                          }
>> +                        // todo this is a very weird code  
>> structure.... returning from a finally is very confusing
>>                          return;
>>                      }
>> -                } catch (SystemException e) {
>> -                    log.info(e);
>> -                } catch (HeuristicMixedException e) {
>> -                    log.info(e);
>> -                } catch (HeuristicRollbackException e) {
>> -                    log.info(e);
>> -                } catch (RollbackException e) {
>> -                    log.info(e);
>> +                } catch (Exception e) {
>> +                    log.info("Exception occured while completing  
>> container transaction", e);
>>                  }
>>              }
>>          }
>>
>> Modified:  
>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>> AbstractThreadPooledTimerTest.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/test/ 
>> org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>> AbstractThreadPooledTimerTest.java (original)
>> +++  
>> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
>> AbstractThreadPooledTimerTest.java Fri Feb 25 15:10:24 2005
>> @@ -23,11 +23,6 @@
>>  import org.apache.geronimo.transaction.context.TransactionContext;
>>  import  
>> org.apache.geronimo.transaction.context.TransactionContextManager;
>>  import org.apache.geronimo.timer.vm.VMWorkerPersistence;
>> -import org.apache.geronimo.timer.ExecutorTaskFactory;
>> -import org.apache.geronimo.timer.ThreadPooledTimer;
>> -import org.apache.geronimo.timer.UserTaskFactory;
>> -import org.apache.geronimo.timer.WorkerPersistence;
>> -import org.apache.geronimo.timer.WorkInfo;
>>
>>  /**
>>   *
>> @@ -73,7 +68,7 @@
>>          for (long i = 0; i < COUNT; i++) {
>>              timer.schedule(userTaskFactory, key, userId, userKey, i);
>>          }
>> -        Thread.currentThread().sleep(COUNT + SLOP);
>> +        Thread.sleep(COUNT + SLOP);
>>          assertEquals(COUNT, counter.get());
>>      }
>>
>> @@ -85,7 +80,7 @@
>>          for (int i = 0; i < workInfos.length; i++) {
>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>          }
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(0, counter.get());
>>      }
>>
>> @@ -98,7 +93,7 @@
>>
>>          timer.doStart();
>>          timer.playback(key, userTaskFactory);
>> -        Thread.currentThread().sleep(2 * SLOP + DELAY);
>> +        Thread.sleep(2 * SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>      }
>>
>> @@ -134,48 +129,48 @@
>>          for (long i = 0; i < COUNT; i++) {
>>              timer.schedule(userTaskFactory, key, userId, userKey, i);
>>          }
>> -        Thread.currentThread().sleep(COUNT + SLOP);
>> +        Thread.sleep(COUNT + SLOP);
>>          assertEquals(0, counter.get());
>>          transactionContext.commit();
>> -        Thread.currentThread().sleep(COUNT + SLOP);
>> +        Thread.sleep(COUNT + SLOP);
>>          assertEquals(COUNT, counter.get());
>>      }
>>
>>      public void testCancelInCommittedTransaction() throws Exception {
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>>          for (long i = 0; i < COUNT; i++) {
>>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
>> userTaskFactory, userId, userKey, DELAY, DELAY);
>>          }
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>          TransactionContext transactionContext =  
>> transactionContextManager.newContainerTransactionContext();
>>          for (int i = 0; i < workInfos.length; i++) {
>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>          }
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>          transactionContext.commit();
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>      }
>>
>>      public void testCancelInRolledBackTransaction() throws Exception  
>> {
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>>          for (long i = 0; i < COUNT; i++) {
>>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
>> userTaskFactory, userId, userKey, DELAY, DELAY);
>>          }
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>          TransactionContext transactionContext =  
>> transactionContextManager.newContainerTransactionContext();
>>          for (int i = 0; i < workInfos.length; i++) {
>>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>>          }
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          assertEquals(COUNT, counter.get());
>>          transactionContext.rollback();
>> -        Thread.currentThread().sleep(SLOP + DELAY);
>> +        Thread.sleep(SLOP + DELAY);
>>          // Catches up with two periods.
>>          assertEquals(3 * COUNT, counter.get());
>>      }
>> @@ -183,13 +178,13 @@
>>      public void testRepeatCountFromPersisted() throws Exception {
>>          assert DELAY > 2 * SLOP;
>>          timer.scheduleAtFixedRate(key, userTaskFactory, userId,  
>> userKey, 0L, DELAY);
>> -        Thread.currentThread().sleep(4 * DELAY + SLOP);
>> +        Thread.sleep(4 * DELAY + SLOP);
>>          timer.doStop();
>>          assertEquals(5, counter.get());
>>
>>          timer.doStart();
>>          timer.playback(key, userTaskFactory);
>> -        Thread.currentThread().sleep(5 * DELAY + SLOP);
>> +        Thread.sleep(5 * DELAY + SLOP);
>>          assertEquals(2 * 5, counter.get());
>>
>>      }
>>
>> Modified:  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/DefaultInstanceContext.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
>> java/org/apache/geronimo/transaction/DefaultInstanceContext.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/DefaultInstanceContext.java (original)
>> +++  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/DefaultInstanceContext.java Fri Feb 25 15:10:24 2005
>> @@ -29,10 +29,11 @@
>>   *
>>   * */
>>  public class DefaultInstanceContext implements InstanceContext {
>> -
>>      private final Map connectionManagerMap = new HashMap();
>>      private final Set unshareableResources;
>>      private final Set applicationManagedSecurityResources;
>> +    private int callDepth;
>> +    private boolean dead = false;
>>
>>      public DefaultInstanceContext(Set unshareableResources, Set  
>> applicationManagedSecurityResources) {
>>          this.unshareableResources = unshareableResources;
>> @@ -43,9 +44,6 @@
>>          return null;
>>      }
>>
>> -    public void setId(Object id) {
>> -    }
>> -
>>      public Object getContainerId() {
>>          return null;
>>      }
>> @@ -62,6 +60,9 @@
>>      public void afterCommit(boolean status) throws Exception {
>>      }
>>
>> +    public void unassociate() throws Throwable {
>> +    }
>> +
>>      public Map getConnectionManagerMap() {
>>          return connectionManagerMap;
>>      }
>> @@ -74,4 +75,24 @@
>>          return applicationManagedSecurityResources;
>>      }
>>
>> +    public boolean isInCall() {
>> +        return callDepth > 0;
>> +    }
>> +
>> +    public void enter() {
>> +        callDepth++;
>> +    }
>> +
>> +    public void exit() {
>> +        assert isInCall();
>> +        callDepth--;
>> +    }
>> +
>> +    public boolean isDead() {
>> +        return dead;
>> +    }
>> +
>> +    public void die() {
>> +        dead = true;
>> +    }
>>  }
>>
>> Modified:  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/InstanceContext.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
>> java/org/apache/geronimo/transaction/InstanceContext.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/InstanceContext.java (original)
>> +++  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/InstanceContext.java Fri Feb 25 15:10:24 2005
>> @@ -29,8 +29,6 @@
>>  public interface InstanceContext {
>>      Object getId();
>>
>> -    void setId(Object id);
>> -
>>      Object getContainerId();
>>
>>      void associate() throws Throwable;
>> @@ -41,6 +39,8 @@
>>
>>      void afterCommit(boolean status) throws Throwable;
>>
>> +    void unassociate() throws Throwable;
>> +
>>      /**
>>       * IMPORTANT INVARIANT: this should always return a map, never  
>> null.
>>       * @return map of ConnectionManager to (list of ) managed  
>> connection info objects.
>> @@ -51,4 +51,13 @@
>>
>>      Set getApplicationManagedSecurityResources();
>>
>> +    boolean isInCall();
>> +
>> +    void enter();
>> +
>> +    void exit();
>> +
>> +    boolean isDead();
>> +
>> +    void die();
>>  }
>>
>> Modified:  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/InheritableTransactionContext.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
>> java/org/apache/geronimo/transaction/context/ 
>> InheritableTransactionContext.java?view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/InheritableTransactionContext.java (original)
>> +++  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/InheritableTransactionContext.java Fri Feb 25  
>> 15:10:24 2005
>> @@ -17,6 +17,10 @@
>>
>>  package org.apache.geronimo.transaction.context;
>>
>> +import java.util.Iterator;
>> +import java.util.Map;
>> +import java.util.HashMap;
>> +import java.util.ArrayList;
>>  import javax.transaction.SystemException;
>>  import javax.transaction.Status;
>>  import javax.transaction.Transaction;
>> @@ -27,16 +31,17 @@
>>  import javax.transaction.RollbackException;
>>
>>  import org.apache.geronimo.transaction.ExtendedTransactionManager;
>> +import org.apache.geronimo.transaction.ConnectionReleaser;
>> +import org.apache.geronimo.transaction.InstanceContext;
>>
>>  /**
>> - *
>> - *
>>   * @version $Rev$ $Date$
>>   */
>>  public abstract class InheritableTransactionContext extends  
>> TransactionContext {
>>      private final ExtendedTransactionManager txnManager;
>>      private Transaction transaction;
>>      private boolean threadAssociated = false;
>> +    private Map managedConnections;
>>
>>      protected  
>> InheritableTransactionContext(ExtendedTransactionManager txnManager)  
>> {
>>          this.txnManager = txnManager;
>> @@ -55,9 +60,26 @@
>>          return transaction;
>>      }
>>
>> +    public void setManagedConnectionInfo(ConnectionReleaser key,  
>> Object info) {
>> +        if (managedConnections == null) {
>> +            managedConnections = new HashMap();
>> +        }
>> +        managedConnections.put(key, info);
>> +    }
>> +
>> +    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>> +        if (managedConnections == null) {
>> +            return null;
>> +        }
>> +        return managedConnections.get(key);
>> +    }
>> +
>>      public boolean isActive() {
>> +        if (transaction == null) {
>> +            return false;
>> +        }
>>          try {
>> -            int status = txnManager.getStatus();
>> +            int status = transaction.getStatus();
>>              return status == Status.STATUS_ACTIVE || status ==  
>> Status.STATUS_MARKED_ROLLBACK;
>>          } catch (SystemException e) {
>>              return false;
>> @@ -65,7 +87,6 @@
>>      }
>>
>>      public boolean getRollbackOnly() throws SystemException {
>> -        Transaction transaction = getTransaction();
>>          if (transaction == null) {
>>              throw new IllegalStateException("There is no transaction  
>> in progress.");
>>          }
>> @@ -77,7 +98,6 @@
>>      }
>>
>>      public void setRollbackOnly() throws IllegalStateException,  
>> SystemException {
>> -        Transaction transaction = getTransaction();
>>          if (transaction == null) {
>>              throw new IllegalStateException("There is no transaction  
>> in progress.");
>>          }
>> @@ -85,13 +105,16 @@
>>      }
>>
>>      public void begin(long transactionTimeoutMilliseconds) throws  
>> SystemException, NotSupportedException {
>> +        assert transaction == null:  "Already associated with a  
>> transaction";
>>          transaction =  
>> txnManager.begin(transactionTimeoutMilliseconds);
>>          threadAssociated = true;
>>      }
>>
>>      public void suspend() throws SystemException {
>>          Transaction suspendedTransaction = txnManager.suspend();
>> -        assert (transaction == suspendedTransaction) : "suspend did  
>> not return our transaction. ours: " + transaction + ", suspended  
>> returned: " + suspendedTransaction;
>> +        if (transaction != suspendedTransaction) {
>> +            throw new SystemException("Suspend did not return our  
>> transaction: expectedTx=" + transaction + ", suspendedTx=" +  
>> suspendedTransaction);
>> +        }
>>          threadAssociated = false;
>>      }
>>
>> @@ -101,6 +124,29 @@
>>      }
>>
>>      public boolean commit() throws HeuristicMixedException,  
>> HeuristicRollbackException, SystemException, RollbackException {
>> +        return complete();
>> +    }
>> +
>> +    public void rollback() throws SystemException {
>> +        setRollbackOnly();
>> +        try {
>> +            complete();
>> +        } catch (SystemException e) {
>> +            throw e;
>> +        } catch (RuntimeException e) {
>> +            throw e;
>> +        } catch (Error e) {
>> +            throw e;
>> +        } catch (Exception e) {
>> +            throw (SystemException) new SystemException("After  
>> commit of container transaction failed").initCause(e);
>> +        }
>> +    }
>> +
>> +    private boolean complete() throws HeuristicMixedException,  
>> HeuristicRollbackException, SystemException, RollbackException {
>> +        if (transaction == null) {
>> +            throw new IllegalStateException("There is no transaction  
>> in progress.");
>> +        }
>> +
>>          boolean wasCommitted = false;
>>          try {
>>              if (isRolledback()) {
>> @@ -120,6 +166,14 @@
>>                  return false;
>>              }
>>
>> +            // verify our tx is the current tx associated with the  
>> thread
>> +            // this is really only an error case and should never  
>> happen, but just to be sure double check
>> +            // immedately before committing using the transaction  
>> manager
>> +            Transaction currentTransaction =  
>> txnManager.getTransaction();
>> +            if (currentTransaction != transaction) {
>> +                throw new SystemException("An unknown transaction is  
>> currently associated with the thread: expectedTx=" + transaction + ",  
>> currentTx=" + currentTransaction);
>> +            }
>> +
>>              txnManager.commit();
>>              wasCommitted = true;
>>          } catch (Throwable t) {
>> @@ -130,23 +184,82 @@
>>              } catch (Throwable e) {
>>                  rollbackAndThrow("After commit of container  
>> transaction failed", e);
>>              } finally {
>> +                unassociateAll();
>>                  connectorAfterCommit();
>>                  transaction = null;
>> +                threadAssociated = false;
>>              }
>>          }
>>          return wasCommitted;
>>      }
>>
>> +    private void beforeCommit() throws Throwable {
>> +        // @todo allow for enrollment during pre-commit
>> +        ArrayList toFlush = getAssociatedContexts();
>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>> +            InstanceContext context = (InstanceContext) i.next();
>> +            if (!context.isDead()) {
>> +                context.beforeCommit();
>> +            }
>> +        }
>> +    }
>> +
>> +    private void afterCommit(boolean status) throws Throwable {
>> +        Throwable firstThrowable = null;
>> +        ArrayList toFlush = getAssociatedContexts();
>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>> +            InstanceContext context = (InstanceContext) i.next();
>> +            if (!context.isDead()) {
>> +                try {
>> +                    context.afterCommit(status);
>> +                } catch (Throwable e) {
>> +                    if (firstThrowable == null) {
>> +                        firstThrowable = e;
>> +                    }
>> +                }
>> +            }
>> +        }
>> +
>> +        if (firstThrowable instanceof Error) {
>> +            throw (Error) firstThrowable;
>> +        } else if (firstThrowable instanceof Exception) {
>> +            throw (Exception) firstThrowable;
>> +        } else if (firstThrowable != null) {
>> +            throw (SystemException) new  
>> SystemException().initCause(firstThrowable);
>> +        }
>> +    }
>> +
>> +    private void connectorAfterCommit() {
>> +        if (managedConnections != null) {
>> +            for (Iterator entries =  
>> managedConnections.entrySet().iterator(); entries.hasNext();) {
>> +                Map.Entry entry = (Map.Entry) entries.next();
>> +                ConnectionReleaser key = (ConnectionReleaser)  
>> entry.getKey();
>> +                key.afterCompletion(entry.getValue());
>> +            }
>> +            //If BeanTransactionContext never reuses the same  
>> instance for sequential BMT, this
>> +            //clearing is unnecessary.
>> +            managedConnections.clear();
>> +        }
>> +    }
>> +
>>      private boolean isRolledback() throws SystemException {
>>          int status;
>>          try {
>>              status = transaction.getStatus();
>>          } catch (SystemException e) {
>> -            txnManager.rollback();
>> +            transaction.rollback();
>>              throw e;
>>          }
>>
>>          if (status == Status.STATUS_MARKED_ROLLBACK) {
>> +            // verify our tx is the current tx associated with the  
>> thread
>> +            // this is really only an error case and should never  
>> happen, but just to be sure double check
>> +            // immedately before committing using the transaction  
>> manager
>> +            Transaction currentTransaction =  
>> txnManager.getTransaction();
>> +            if (currentTransaction != transaction) {
>> +                throw new SystemException("An unknown transaction is  
>> currently associated with the thread: expectedTx=" + transaction + ",  
>> currentTx=" + currentTransaction);
>> +            }
>> +
>>              // we need to rollback
>>              txnManager.rollback();
>>              return true;
>> @@ -160,7 +273,6 @@
>>
>>      private void rollbackAndThrow(String message, Throwable  
>> throwable) throws HeuristicMixedException,  
>> HeuristicRollbackException, SystemException, RollbackException {
>>          try {
>> -            // just incase there is a junk transaction on the thread
>>              if (txnManager.getStatus() !=  
>> Status.STATUS_NO_TRANSACTION) {
>>                  txnManager.rollback();
>>              }
>> @@ -168,6 +280,18 @@
>>              log.error("Unable to roll back transaction", t);
>>          }
>>
>> +        try {
>> +            // make doubly sure our transaction was rolled back
>> +            // this can happen when there was a junk transaction on  
>> the thread
>> +            int status = transaction.getStatus();
>> +            if (status != Status.STATUS_ROLLEDBACK &&
>> +                    status != Status.STATUS_ROLLING_BACK) {
>> +                transaction.rollback();
>> +            }
>> +        } catch (Throwable t) {
>> +            log.error("Unable to roll back transaction", t);
>> +        }
>> +
>>          if (throwable instanceof HeuristicMixedException) {
>>              throw (HeuristicMixedException) throwable;
>>          } else if (throwable instanceof HeuristicRollbackException) {
>> @@ -182,41 +306,6 @@
>>              throw (RuntimeException) throwable;
>>          } else {
>>              throw (SystemException) new  
>> SystemException(message).initCause(throwable);
>> -        }
>> -    }
>> -
>> -    public void rollback() throws SystemException {
>> -        try {
>> -            try {
>> -                if (txnManager.getStatus() !=  
>> Status.STATUS_NO_TRANSACTION) {
>> -                    txnManager.rollback();
>> -                }
>> -            } finally {
>> -                try {
>> -                    afterCommit(false);
>> -                } catch (Throwable e) {
>> -                    try {
>> -                        // just incase there is a junk transaction  
>> on the thread
>> -                        if (txnManager.getStatus() !=  
>> Status.STATUS_NO_TRANSACTION) {
>> -                            txnManager.rollback();
>> -                        }
>> -                    } catch (Throwable t1) {
>> -                        log.error("Unable to roll back transaction",  
>> t1);
>> -                    }
>> -
>> -                    if (e instanceof SystemException) {
>> -                        throw (SystemException) e;
>> -                    } else if (e instanceof Error) {
>> -                        throw (Error) e;
>> -                    } else if (e instanceof RuntimeException) {
>> -                        throw (RuntimeException) e;
>> -                    }
>> -                    throw (SystemException) new  
>> SystemException("After commit of container transaction  
>> failed").initCause(e);
>> -                }
>> -            }
>> -        } finally {
>> -            connectorAfterCommit();
>> -            transaction = null;
>>          }
>>      }
>>  }
>>
>> Modified:  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/TransactionContext.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
>> java/org/apache/geronimo/transaction/context/TransactionContext.java? 
>> view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/TransactionContext.java (original)
>> +++  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/TransactionContext.java Fri Feb 25 15:10:24 2005
>> @@ -18,27 +18,21 @@
>>  package org.apache.geronimo.transaction.context;
>>
>>  import java.util.ArrayList;
>> -import java.util.HashMap;
>>  import java.util.Iterator;
>> -import java.util.Map;
>>  import javax.transaction.HeuristicMixedException;
>>  import javax.transaction.HeuristicRollbackException;
>>  import javax.transaction.InvalidTransactionException;
>>  import javax.transaction.RollbackException;
>>  import javax.transaction.SystemException;
>> -import javax.transaction.Transaction;
>>
>>  import org.apache.commons.logging.Log;
>>  import org.apache.commons.logging.LogFactory;
>> -import org.apache.geronimo.transaction.ConnectionReleaser;
>>  import org.apache.geronimo.transaction.DoubleKeyedHashMap;
>>  import org.apache.geronimo.transaction.InstanceContext;
>>  import org.tranql.cache.InTxCache;
>>
>>
>>  /**
>> - *
>> - *
>>   * @version $Rev$ $Date$
>>   */
>>  public abstract class TransactionContext {
>> @@ -56,9 +50,12 @@
>>      private InstanceContext currentContext;
>>      private final DoubleKeyedHashMap associatedContexts = new  
>> DoubleKeyedHashMap();
>>      private final DoubleKeyedHashMap dirtyContexts = new  
>> DoubleKeyedHashMap();
>> -    private Map managedConnections;
>>      private InTxCache inTxCache;
>>
>> +    public abstract boolean getRollbackOnly() throws SystemException;
>> +
>> +    public abstract void setRollbackOnly() throws SystemException;
>> +
>>      public abstract void suspend() throws SystemException;
>>
>>      public abstract void resume() throws SystemException,  
>> InvalidTransactionException;
>> @@ -73,21 +70,51 @@
>>          }
>>      }
>>
>> -    public final void unassociate(Object containerId, Object id)  
>> throws Exception {
>> -        associatedContexts.remove(containerId, id);
>> -        dirtyContexts.remove(containerId, id);
>> +    public final void unassociate(InstanceContext context) throws  
>> Throwable {
>> +        associatedContexts.remove(context.getContainerId(),  
>> context.getId());
>> +        context.unassociate();
>> +    }
>> +
>> +    public final void unassociate(Object containerId, Object id)  
>> throws Throwable {
>> +        InstanceContext context = (InstanceContext)  
>> associatedContexts.remove(containerId, id);
>> +        if (context != null) {
>> +            context.unassociate();
>> +        }
>> +    }
>> +
>> +    public final InstanceContext getContext(Object containerId,  
>> Object id) {
>> +        return (InstanceContext) associatedContexts.get(containerId,  
>> id);
>> +    }
>> +
>> +    protected final ArrayList getAssociatedContexts() {
>> +        return new ArrayList(associatedContexts.values());
>> +    }
>> +
>> +    protected final void unassociateAll() {
>> +        ArrayList toFlush = getAssociatedContexts();
>> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>> +            InstanceContext context = (InstanceContext) i.next();
>> +            try {
>> +                context.unassociate();
>> +            } catch (Throwable throwable) {
>> +                log.warn("Error while unassociating instance from  
>> transaction context: " + context, throwable);
>> +            }
>> +        }
>>      }
>>
>> -    public final InstanceContext beginInvocation(InstanceContext  
>> context) {
>> +    public final InstanceContext beginInvocation(InstanceContext  
>> context) throws Throwable {
>>          if (context.getId() != null) {
>> +            associate(context);
>>              dirtyContexts.put(context.getContainerId(),  
>> context.getId(), context);
>>          }
>> +        context.enter();
>>          InstanceContext caller = currentContext;
>>          currentContext = context;
>>          return caller;
>>      }
>>
>>      public final void endInvocation(InstanceContext caller) {
>> +        currentContext.exit();
>>          currentContext = caller;
>>      }
>>
>> @@ -97,7 +124,9 @@
>>              dirtyContexts.clear();
>>              for (Iterator i = toFlush.iterator(); i.hasNext();) {
>>                  InstanceContext context = (InstanceContext) i.next();
>> -                context.flush();
>> +                if (!context.isDead()) {
>> +                    context.flush();
>> +                }
>>              }
>>          }
>>          if (currentContext != null && currentContext.getId() !=  
>> null) {
>> @@ -108,42 +137,6 @@
>>          }
>>      }
>>
>> -    protected void beforeCommit() throws Throwable {
>> -        // @todo allow for enrollment during pre-commit
>> -        ArrayList toFlush = new  
>> ArrayList(associatedContexts.values());
>> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>> -            InstanceContext context = (InstanceContext) i.next();
>> -            context.beforeCommit();
>> -        }
>> -    }
>> -
>> -    protected void afterCommit(boolean status) throws Throwable {
>> -        Throwable firstThrowable = null;
>> -        ArrayList toFlush = new  
>> ArrayList(associatedContexts.values());
>> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
>> -            InstanceContext context = (InstanceContext) i.next();
>> -            try {
>> -                context.afterCommit(status);
>> -            } catch (Throwable e) {
>> -                if (firstThrowable == null) {
>> -                    firstThrowable = e;
>> -                }
>> -            }
>> -        }
>> -
>> -        if (firstThrowable instanceof Error) {
>> -            throw (Error) firstThrowable;
>> -        } else if (firstThrowable instanceof Exception) {
>> -            throw (Exception) firstThrowable;
>> -        } else if (firstThrowable != null) {
>> -            throw (SystemException) new  
>> SystemException().initCause(firstThrowable);
>> -        }
>> -    }
>> -
>> -    public final InstanceContext getContext(Object containerId,  
>> Object id) {
>> -        return (InstanceContext) associatedContexts.get(containerId,  
>> id);
>> -    }
>> -
>>      public final void setInTxCache(InTxCache inTxCache) {
>>          this.inTxCache = inTxCache;
>>      }
>> @@ -151,42 +144,4 @@
>>      public final InTxCache getInTxCache() {
>>          return inTxCache;
>>      }
>> -
>> -    //Geronimo connector framework support
>> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
>> Object info) {
>> -        if (managedConnections == null) {
>> -            managedConnections = new HashMap();
>> -        }
>> -        managedConnections.put(key, info);
>> -    }
>> -
>> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>> -        if (managedConnections == null) {
>> -            return null;
>> -        }
>> -        return managedConnections.get(key);
>> -    }
>> -
>> -    /**
>> -     * determines if the transaction is in a pre-prepared state
>> -     * of STATUS_ACTIVE or STATUS_MARKED_ROLLBACK.
>> -     * @return true if more work can be done in the transaction  
>> (although it might be forced to roll back)
>> -     */
>> -    public abstract boolean isActive();
>> -
>> -    public abstract Transaction getTransaction();
>> -
>> -    protected void connectorAfterCommit() {
>> -        if (managedConnections != null) {
>> -            for (Iterator entries =  
>> managedConnections.entrySet().iterator(); entries.hasNext();) {
>> -                Map.Entry entry = (Map.Entry) entries.next();
>> -                ConnectionReleaser key = (ConnectionReleaser)  
>> entry.getKey();
>> -                key.afterCompletion(entry.getValue());
>> -            }
>> -            //If BeanTransactionContext never reuses the same  
>> instance for sequential BMT, this
>> -            //clearing is unnecessary.
>> -            managedConnections.clear();
>> -        }
>> -    }
>> -
>>  }
>>
>> Modified:  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/UnspecifiedTransactionContext.java
>> URL:  
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
>> java/org/apache/geronimo/transaction/context/ 
>> UnspecifiedTransactionContext.java?view=diff&r1=155375&r2=155376
>> ====================================================================== 
>> ========
>> ---  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/UnspecifiedTransactionContext.java (original)
>> +++  
>> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
>> transaction/context/UnspecifiedTransactionContext.java Fri Feb 25  
>> 15:10:24 2005
>> @@ -17,16 +17,18 @@
>>
>>  package org.apache.geronimo.transaction.context;
>>
>> -import javax.transaction.Transaction;
>> -
>> -import org.apache.geronimo.transaction.ConnectionReleaser;
>> -
>> -
>>  /**
>>   * @version $Rev$ $Date$
>>   */
>>  public class UnspecifiedTransactionContext extends  
>> TransactionContext {
>> -    public void begin() {
>> +    private boolean failed = false;
>> +
>> +    public boolean getRollbackOnly() {
>> +        return failed;
>> +    }
>> +
>> +    public void setRollbackOnly() {
>> +        this.failed = true;
>>      }
>>
>>      public void suspend() {
>> @@ -36,33 +38,28 @@
>>      }
>>
>>      public boolean commit() {
>> +        complete();
>> +        return true;
>> +    }
>> +
>> +    public void rollback() {
>> +        setRollbackOnly();
>> +        complete();
>> +    }
>> +
>> +    private void complete() {
>>          try {
>> -            flushState();
>> +            if (!failed) {
>> +                flushState();
>> +            }
>>          } catch (Error e) {
>>              throw e;
>>          } catch (RuntimeException re) {
>>              throw re;
>>          } catch (Throwable e) {
>>              log.error("Unable to flush state, continuing", e);
>> +        } finally {
>> +            unassociateAll();
>>          }
>> -        return true;
>> -    }
>> -
>> -    public void rollback() {
>> -    }
>> -
>> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
>> Object info) {
>> -    }
>> -
>> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
>> -        return null;
>> -    }
>> -
>> -    public boolean isActive() {
>> -        return false;
>> -    }
>> -
>> -    public Transaction getTransaction() {
>> -        return null;
>>      }
>>  }
>>
>>


Re: svn commit: r155376 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/ connector/src/test/org/apache/geronimo/connector/outbound/ timer/src/java/org/apache/geronimo/timer/ timer/src/test/org/apache/geronimo/timer/ transaction/src/java/org/apache/geronimo/transaction/ transaction/src/java/org/apache/geronimo/transaction/context/

Posted by David Jencks <da...@yahoo.com>.
what is the point of removing the isActive() and  
getManagedConnectionInfos() methods from TransactionContext and forcing  
all the clients to do a lot of type testing and casting?

david jencks

On Feb 25, 2005, at 3:10 PM, dain@apache.org wrote:

> Author: dain
> Date: Fri Feb 25 15:10:24 2005
> New Revision: 155376
>
> URL: http://svn.apache.org/viewcvs?view=rev&rev=155376
> Log:
> Fixed bugs in TransactionContext and handling of the contexts unturned  
> by turning back on in-tx caching
> Added support for entrancy tracking and killing InstanceContexts
>
> Modified:
>      
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptor.java
>      
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionEnlistingInterceptor.java
>      
> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptorTest.java
>      
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> NontransactionalExecutorTask.java
>      
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> ThreadPooledTimer.java
>      
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> TransactionalExecutorTask.java
>      
> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
> AbstractThreadPooledTimerTest.java
>      
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/DefaultInstanceContext.java
>      
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/InstanceContext.java
>      
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/InheritableTransactionContext.java
>      
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/TransactionContext.java
>      
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/UnspecifiedTransactionContext.java
>
> Modified:  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptor.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
> java/org/apache/geronimo/connector/outbound/ 
> TransactionCachingInterceptor.java?view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptor.java (original)
> +++  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptor.java Fri Feb 25  
> 15:10:24 2005
> @@ -27,6 +27,7 @@
>  import org.apache.geronimo.transaction.ConnectionReleaser;
>  import org.apache.geronimo.transaction.context.TransactionContext;
>  import  
> org.apache.geronimo.transaction.context.TransactionContextManager;
> +import  
> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>
>  /**
>   * TransactionCachingInterceptor.java
> @@ -59,16 +60,15 @@
>      }
>
>      public void getConnection(ConnectionInfo connectionInfo) throws  
> ResourceException {
> -        TransactionContext transactionContext =  
> transactionContextManager.getContext();
>          //There can be an inactive transaction context when a  
> connection is requested in
>          //Synchronization.afterCompletion().
> -        if (transactionContext == null ||  
> !transactionContext.isActive()) {
> -            next.getConnection(connectionInfo);
> -        } else {
> -            ManagedConnectionInfos managedConnectionInfos =  
> (ManagedConnectionInfos)  
> transactionContext.getManagedConnectionInfo(this);
> +        TransactionContext transactionContext =  
> transactionContextManager.getContext();
> +        if ((transactionContext instanceof  
> InheritableTransactionContext) && ((InheritableTransactionContext)  
> transactionContext).isActive()) {
> +            InheritableTransactionContext  
> inheritableTransactionContext = ((InheritableTransactionContext)  
> transactionContext);
> +            ManagedConnectionInfos managedConnectionInfos =  
> (ManagedConnectionInfos)  
> inheritableTransactionContext.getManagedConnectionInfo(this);
>              if (managedConnectionInfos == null) {
>                  managedConnectionInfos = new ManagedConnectionInfos();
> -                transactionContext.setManagedConnectionInfo(this,  
> managedConnectionInfos);
> +                 
> inheritableTransactionContext.setManagedConnectionInfo(this,  
> managedConnectionInfos);
>              }
>              if (connectionInfo.isUnshareable()) {
>                  if  
> (! 
> managedConnectionInfos.containsUnshared(connectionInfo.getManagedConnec 
> tionInfo())) {
> @@ -85,6 +85,8 @@
>                       
> managedConnectionInfos.setShared(connectionInfo.getManagedConnectionInf 
> o());
>                  }
>              }
> +        } else {
> +            next.getConnection(connectionInfo);
>          }
>      }
>
> @@ -96,7 +98,7 @@
>          }
>
>          TransactionContext transactionContext =  
> transactionContextManager.getContext();
> -        if (transactionContext != null &&  
> transactionContext.isActive()) {
> +        if ((transactionContext instanceof  
> InheritableTransactionContext) && ((InheritableTransactionContext)  
> transactionContext).isActive()) {
>              return;
>          }
>          internalReturn(connectionInfo, connectionReturnAction);
>
> Modified:  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionEnlistingInterceptor.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
> java/org/apache/geronimo/connector/outbound/ 
> TransactionEnlistingInterceptor.java?view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionEnlistingInterceptor.java (original)
> +++  
> geronimo/trunk/modules/connector/src/java/org/apache/geronimo/ 
> connector/outbound/TransactionEnlistingInterceptor.java Fri Feb 25  
> 15:10:24 2005
> @@ -24,6 +24,7 @@
>
>  import org.apache.geronimo.transaction.context.TransactionContext;
>  import  
> org.apache.geronimo.transaction.context.TransactionContextManager;
> +import  
> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>
>  /**
>   * TransactionEnlistingInterceptor.java
> @@ -48,9 +49,12 @@
>          try {
>              ManagedConnectionInfo mci =  
> connectionInfo.getManagedConnectionInfo();
>              TransactionContext transactionContext =  
> transactionContextManager.getContext();
> -            if (transactionContext != null &&  
> transactionContext.isActive()) {
> -                XAResource xares = mci.getXAResource();
> -                 
> transactionContext.getTransaction().enlistResource(xares);
> +            if ((transactionContext instanceof  
> InheritableTransactionContext)) {
> +                InheritableTransactionContext  
> inheritableTransactionContext = ((InheritableTransactionContext)  
> transactionContext);
> +                if (inheritableTransactionContext.isActive()) {
> +                    XAResource xares = mci.getXAResource();
> +                     
> inheritableTransactionContext.getTransaction().enlistResource(xares);
> +                }
>              }
>
>          } catch (SystemException e) {
> @@ -76,9 +80,12 @@
>          try {
>              ManagedConnectionInfo mci =  
> connectionInfo.getManagedConnectionInfo();
>              TransactionContext transactionContext =  
> transactionContextManager.getContext();
> -            if (transactionContext != null &&  
> transactionContext.isActive()) {
> -                XAResource xares = mci.getXAResource();
> -                 
> transactionContext.getTransaction().delistResource(xares,  
> XAResource.TMSUSPEND);
> +            if ((transactionContext instanceof  
> InheritableTransactionContext)) {
> +                InheritableTransactionContext  
> inheritableTransactionContext = ((InheritableTransactionContext)  
> transactionContext);
> +                if (inheritableTransactionContext.isActive()) {
> +                    XAResource xares = mci.getXAResource();
> +                     
> inheritableTransactionContext.getTransaction().delistResource(xares,  
> XAResource.TMSUSPEND);
> +                }
>              }
>
>          } catch (SystemException e) {
>
> Modified:  
> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptorTest.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/connector/src/ 
> test/org/apache/geronimo/connector/outbound/ 
> TransactionCachingInterceptorTest.java?view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptorTest.java (original)
> +++  
> geronimo/trunk/modules/connector/src/test/org/apache/geronimo/ 
> connector/outbound/TransactionCachingInterceptorTest.java Fri Feb 25  
> 15:10:24 2005
> @@ -127,8 +127,6 @@
>          transactionCachingInterceptor.getConnection(connectionInfo1);
>          assertTrue("Expected to get an initial connection",  
> obtainedConnectionInfo != null);
>          assertTrue("Expected nothing returned yet",  
> returnedConnectionInfo == null);
> -        assertTrue("Expected no ManagedConnectionInfo in the  
> TransactionContext",
> -                null ==  
> transactionContextManager.getContext().getManagedConnectionInfo(transac 
> tionCachingInterceptor));
>          obtainedConnectionInfo = null;
>          ConnectionInfo connectionInfo2 = makeConnectionInfo();
>          transactionCachingInterceptor.getConnection(connectionInfo2);
> @@ -136,18 +134,12 @@
>          assertTrue("Expected nothing returned yet",  
> returnedConnectionInfo == null);
>          assertTrue("Expected different ManagedConnectionInfo in both  
> ConnectionInfos",
>                  connectionInfo1.getManagedConnectionInfo() !=  
> connectionInfo2.getManagedConnectionInfo());
> -        assertTrue("Expected no ManagedConnectionInfo in the  
> TransactionContext",
> -                null ==  
> transactionContextManager.getContext().getManagedConnectionInfo(transac 
> tionCachingInterceptor));
>          //we didn't create any handles, so the "ManagedConnection"  
> should be returned.
> -        assertTrue("Expected TransactionContext to report inactive",  
> !transactionContextManager.getContext().isActive());
>           
> transactionCachingInterceptor.returnConnection(connectionInfo1,  
> ConnectionReturnAction.RETURN_HANDLE);
>          assertTrue("Expected connection to be returned",  
> returnedConnectionInfo != null);
>          returnedConnectionInfo = null;
>           
> transactionCachingInterceptor.returnConnection(connectionInfo2,  
> ConnectionReturnAction.RETURN_HANDLE);
>          assertTrue("Expected connection to be returned",  
> returnedConnectionInfo != null);
> -
> -        assertTrue("Expected TransactionContext to report inactive",  
> !transactionContextManager.getContext().isActive());
> -
>      }
>
>      public void testTransactionIndependence() throws Exception {
>
> Modified:  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> NontransactionalExecutorTask.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
> org/apache/geronimo/timer/NontransactionalExecutorTask.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> NontransactionalExecutorTask.java (original)
> +++  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> NontransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
> @@ -19,14 +19,12 @@
>
>  import org.apache.commons.logging.Log;
>  import org.apache.commons.logging.LogFactory;
> -import org.apache.geronimo.timer.ExecutorTask;
> +import org.apache.geronimo.transaction.context.TransactionContext;
> +import  
> org.apache.geronimo.transaction.context.UnspecifiedTransactionContext;
>
>  /**
> - *
> - *
>   * @version $Rev$ $Date$
> - *
> - * */
> + */
>  public class NontransactionalExecutorTask implements ExecutorTask {
>
>      private static final Log log =  
> LogFactory.getLog(NontransactionalExecutorTask.class);
> @@ -42,18 +40,26 @@
>      }
>
>      public void run() {
> +        UnspecifiedTransactionContext transactionContext = new  
> UnspecifiedTransactionContext();
> +        TransactionContext oldTransactionContext =  
> TransactionContext.getContext();
> +        TransactionContext.setContext(transactionContext);
>          try {
> -            userTask.run();
> -        } catch (Exception e) {
> -            log.info(e);
> -        }
> -        try {
> -            threadPooledTimer.workPerformed(workInfo);
> -        } catch (PersistenceException e) {
> -            log.info(e);
> -        }
> -        if (workInfo.isOneTime()) {
> -            threadPooledTimer.removeWorkInfo(workInfo);
> +            try {
> +                userTask.run();
> +            } catch (Exception e) {
> +                log.info(e);
> +            }
> +            try {
> +                threadPooledTimer.workPerformed(workInfo);
> +            } catch (PersistenceException e) {
> +                log.info(e);
> +            }
> +            if (workInfo.isOneTime()) {
> +                threadPooledTimer.removeWorkInfo(workInfo);
> +            }
> +        } finally {
> +            transactionContext.commit();
> +            TransactionContext.setContext(oldTransactionContext);
>          }
>      }
>
>
> Modified:  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> ThreadPooledTimer.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
> org/apache/geronimo/timer/ThreadPooledTimer.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> ThreadPooledTimer.java (original)
> +++  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> ThreadPooledTimer.java Fri Feb 25 15:10:24 2005
> @@ -37,6 +37,7 @@
>  import org.apache.geronimo.gbean.GBeanLifecycle;
>  import org.apache.geronimo.transaction.context.TransactionContext;
>  import  
> org.apache.geronimo.transaction.context.TransactionContextManager;
> +import  
> org.apache.geronimo.transaction.context.InheritableTransactionContext;
>  import org.apache.commons.logging.Log;
>  import org.apache.commons.logging.LogFactory;
>
> @@ -243,13 +244,21 @@
>
>      void registerSynchronization(Synchronization sync) throws  
> RollbackException, SystemException {
>          TransactionContext transactionContext =  
> transactionContextManager.getContext();
> +
>          //TODO move the registerSynchronization to the  
> TransactionContext
> -        Transaction transaction = transactionContext == null? null:  
> transactionContext.getTransaction();
> +        Transaction transaction;
> +        if (transactionContext instanceof  
> InheritableTransactionContext) {
> +            InheritableTransactionContext  
> inheritableTransactionContext = ((InheritableTransactionContext)  
> transactionContext);
> +            transaction =  
> inheritableTransactionContext.getTransaction();
> +            assert transaction == null ||  
> inheritableTransactionContext.isActive(): "Trying to register a sync  
> on an inactive transaction context";
> +        } else {
> +            transaction = null;
> +        }
> +
>          if (transaction == null) {
>              sync.beforeCompletion();
>              sync.afterCompletion(Status.STATUS_COMMITTED);
>          } else {
> -            assert transactionContext.isActive(): "Trying to register  
> a sync on an inactive transaction context";
>              transaction.registerSynchronization(sync);
>          }
>      }
>
> Modified:  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> TransactionalExecutorTask.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/java/ 
> org/apache/geronimo/timer/TransactionalExecutorTask.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> TransactionalExecutorTask.java (original)
> +++  
> geronimo/trunk/modules/timer/src/java/org/apache/geronimo/timer/ 
> TransactionalExecutorTask.java Fri Feb 25 15:10:24 2005
> @@ -17,26 +17,14 @@
>
>  package org.apache.geronimo.timer;
>
> -import javax.transaction.HeuristicMixedException;
> -import javax.transaction.HeuristicRollbackException;
> -import javax.transaction.NotSupportedException;
> -import javax.transaction.RollbackException;
> -import javax.transaction.SystemException;
> -
>  import org.apache.commons.logging.Log;
>  import org.apache.commons.logging.LogFactory;
>  import  
> org.apache.geronimo.transaction.context.ContainerTransactionContext;
>  import  
> org.apache.geronimo.transaction.context.TransactionContextManager;
> -import org.apache.geronimo.timer.ExecutorTask;
> -import org.apache.geronimo.timer.PersistenceException;
> -import org.apache.geronimo.timer.ThreadPooledTimer;
>
>  /**
> - *
> - *
>   * @version $Rev$ $Date$
> - *
> - * */
> + */
>  public class TransactionalExecutorTask implements ExecutorTask {
>      private static final Log log =  
> LogFactory.getLog(TransactionalExecutorTask.class);
>
> @@ -54,49 +42,38 @@
>          this.transactionContextManager = transactionContextManager;
>          this.repeatCount = repeatCount;
>      }
> -
> +
>      public void run() {
>          ContainerTransactionContext transactionContext = null;
>          for (int tries = 0; tries < repeatCount; tries++) {
>              try {
>                  transactionContext =  
> transactionContextManager.newContainerTransactionContext();
> -            } catch (NotSupportedException e) {
> -                log.info(e);
> -                break;
> -            } catch (SystemException e) {
> -                log.info(e);
> +            } catch (Exception e) {
> +                log.info("Exception occured while starting container  
> transaction", e);
>                  break;
>              }
>              try {
>                  try {
>                      userTask.run();
>                  } catch (Exception e) {
> -                    log.info(e);
> +                    log.info("Exception occured while running user  
> task", e);
>                  }
>                  try {
>                      threadPooledTimer.workPerformed(workInfo);
>                  } catch (PersistenceException e) {
> -                    log.info(e);
> +                    log.info("Exception occured while updating timer  
> persistent state", e);
>                  }
>              } finally {
>                  try {
> -                    if (transactionContext.getRollbackOnly()) {
> -                        transactionContext.rollback();
> -                    } else {
> -                        transactionContext.commit();
> +                    if (transactionContext.commit()) {
>                          if (workInfo.isOneTime()) {
>                               
> threadPooledTimer.removeWorkInfo(workInfo);
>                          }
> +                        // todo this is a very weird code  
> structure.... returning from a finally is very confusing
>                          return;
>                      }
> -                } catch (SystemException e) {
> -                    log.info(e);
> -                } catch (HeuristicMixedException e) {
> -                    log.info(e);
> -                } catch (HeuristicRollbackException e) {
> -                    log.info(e);
> -                } catch (RollbackException e) {
> -                    log.info(e);
> +                } catch (Exception e) {
> +                    log.info("Exception occured while completing  
> container transaction", e);
>                  }
>              }
>          }
>
> Modified:  
> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
> AbstractThreadPooledTimerTest.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/timer/src/test/ 
> org/apache/geronimo/timer/AbstractThreadPooledTimerTest.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
> AbstractThreadPooledTimerTest.java (original)
> +++  
> geronimo/trunk/modules/timer/src/test/org/apache/geronimo/timer/ 
> AbstractThreadPooledTimerTest.java Fri Feb 25 15:10:24 2005
> @@ -23,11 +23,6 @@
>  import org.apache.geronimo.transaction.context.TransactionContext;
>  import  
> org.apache.geronimo.transaction.context.TransactionContextManager;
>  import org.apache.geronimo.timer.vm.VMWorkerPersistence;
> -import org.apache.geronimo.timer.ExecutorTaskFactory;
> -import org.apache.geronimo.timer.ThreadPooledTimer;
> -import org.apache.geronimo.timer.UserTaskFactory;
> -import org.apache.geronimo.timer.WorkerPersistence;
> -import org.apache.geronimo.timer.WorkInfo;
>
>  /**
>   *
> @@ -73,7 +68,7 @@
>          for (long i = 0; i < COUNT; i++) {
>              timer.schedule(userTaskFactory, key, userId, userKey, i);
>          }
> -        Thread.currentThread().sleep(COUNT + SLOP);
> +        Thread.sleep(COUNT + SLOP);
>          assertEquals(COUNT, counter.get());
>      }
>
> @@ -85,7 +80,7 @@
>          for (int i = 0; i < workInfos.length; i++) {
>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>          }
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(0, counter.get());
>      }
>
> @@ -98,7 +93,7 @@
>
>          timer.doStart();
>          timer.playback(key, userTaskFactory);
> -        Thread.currentThread().sleep(2 * SLOP + DELAY);
> +        Thread.sleep(2 * SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>      }
>
> @@ -134,48 +129,48 @@
>          for (long i = 0; i < COUNT; i++) {
>              timer.schedule(userTaskFactory, key, userId, userKey, i);
>          }
> -        Thread.currentThread().sleep(COUNT + SLOP);
> +        Thread.sleep(COUNT + SLOP);
>          assertEquals(0, counter.get());
>          transactionContext.commit();
> -        Thread.currentThread().sleep(COUNT + SLOP);
> +        Thread.sleep(COUNT + SLOP);
>          assertEquals(COUNT, counter.get());
>      }
>
>      public void testCancelInCommittedTransaction() throws Exception {
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>          for (long i = 0; i < COUNT; i++) {
>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
> userTaskFactory, userId, userKey, DELAY, DELAY);
>          }
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>          TransactionContext transactionContext =  
> transactionContextManager.newContainerTransactionContext();
>          for (int i = 0; i < workInfos.length; i++) {
>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>          }
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>          transactionContext.commit();
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>      }
>
>      public void testCancelInRolledBackTransaction() throws Exception {
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          WorkInfo[] workInfos = new WorkInfo[COUNT];
>          for (long i = 0; i < COUNT; i++) {
>              workInfos[(int) i] = timer.scheduleAtFixedRate(key,  
> userTaskFactory, userId, userKey, DELAY, DELAY);
>          }
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>          TransactionContext transactionContext =  
> transactionContextManager.newContainerTransactionContext();
>          for (int i = 0; i < workInfos.length; i++) {
>              workInfos[i].getExecutorFeedingTimerTask().cancel();
>          }
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          assertEquals(COUNT, counter.get());
>          transactionContext.rollback();
> -        Thread.currentThread().sleep(SLOP + DELAY);
> +        Thread.sleep(SLOP + DELAY);
>          // Catches up with two periods.
>          assertEquals(3 * COUNT, counter.get());
>      }
> @@ -183,13 +178,13 @@
>      public void testRepeatCountFromPersisted() throws Exception {
>          assert DELAY > 2 * SLOP;
>          timer.scheduleAtFixedRate(key, userTaskFactory, userId,  
> userKey, 0L, DELAY);
> -        Thread.currentThread().sleep(4 * DELAY + SLOP);
> +        Thread.sleep(4 * DELAY + SLOP);
>          timer.doStop();
>          assertEquals(5, counter.get());
>
>          timer.doStart();
>          timer.playback(key, userTaskFactory);
> -        Thread.currentThread().sleep(5 * DELAY + SLOP);
> +        Thread.sleep(5 * DELAY + SLOP);
>          assertEquals(2 * 5, counter.get());
>
>      }
>
> Modified:  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/DefaultInstanceContext.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
> java/org/apache/geronimo/transaction/DefaultInstanceContext.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/DefaultInstanceContext.java (original)
> +++  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/DefaultInstanceContext.java Fri Feb 25 15:10:24 2005
> @@ -29,10 +29,11 @@
>   *
>   * */
>  public class DefaultInstanceContext implements InstanceContext {
> -
>      private final Map connectionManagerMap = new HashMap();
>      private final Set unshareableResources;
>      private final Set applicationManagedSecurityResources;
> +    private int callDepth;
> +    private boolean dead = false;
>
>      public DefaultInstanceContext(Set unshareableResources, Set  
> applicationManagedSecurityResources) {
>          this.unshareableResources = unshareableResources;
> @@ -43,9 +44,6 @@
>          return null;
>      }
>
> -    public void setId(Object id) {
> -    }
> -
>      public Object getContainerId() {
>          return null;
>      }
> @@ -62,6 +60,9 @@
>      public void afterCommit(boolean status) throws Exception {
>      }
>
> +    public void unassociate() throws Throwable {
> +    }
> +
>      public Map getConnectionManagerMap() {
>          return connectionManagerMap;
>      }
> @@ -74,4 +75,24 @@
>          return applicationManagedSecurityResources;
>      }
>
> +    public boolean isInCall() {
> +        return callDepth > 0;
> +    }
> +
> +    public void enter() {
> +        callDepth++;
> +    }
> +
> +    public void exit() {
> +        assert isInCall();
> +        callDepth--;
> +    }
> +
> +    public boolean isDead() {
> +        return dead;
> +    }
> +
> +    public void die() {
> +        dead = true;
> +    }
>  }
>
> Modified:  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/InstanceContext.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
> java/org/apache/geronimo/transaction/InstanceContext.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/InstanceContext.java (original)
> +++  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/InstanceContext.java Fri Feb 25 15:10:24 2005
> @@ -29,8 +29,6 @@
>  public interface InstanceContext {
>      Object getId();
>
> -    void setId(Object id);
> -
>      Object getContainerId();
>
>      void associate() throws Throwable;
> @@ -41,6 +39,8 @@
>
>      void afterCommit(boolean status) throws Throwable;
>
> +    void unassociate() throws Throwable;
> +
>      /**
>       * IMPORTANT INVARIANT: this should always return a map, never  
> null.
>       * @return map of ConnectionManager to (list of ) managed  
> connection info objects.
> @@ -51,4 +51,13 @@
>
>      Set getApplicationManagedSecurityResources();
>
> +    boolean isInCall();
> +
> +    void enter();
> +
> +    void exit();
> +
> +    boolean isDead();
> +
> +    void die();
>  }
>
> Modified:  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/InheritableTransactionContext.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
> java/org/apache/geronimo/transaction/context/ 
> InheritableTransactionContext.java?view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/InheritableTransactionContext.java (original)
> +++  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/InheritableTransactionContext.java Fri Feb 25  
> 15:10:24 2005
> @@ -17,6 +17,10 @@
>
>  package org.apache.geronimo.transaction.context;
>
> +import java.util.Iterator;
> +import java.util.Map;
> +import java.util.HashMap;
> +import java.util.ArrayList;
>  import javax.transaction.SystemException;
>  import javax.transaction.Status;
>  import javax.transaction.Transaction;
> @@ -27,16 +31,17 @@
>  import javax.transaction.RollbackException;
>
>  import org.apache.geronimo.transaction.ExtendedTransactionManager;
> +import org.apache.geronimo.transaction.ConnectionReleaser;
> +import org.apache.geronimo.transaction.InstanceContext;
>
>  /**
> - *
> - *
>   * @version $Rev$ $Date$
>   */
>  public abstract class InheritableTransactionContext extends  
> TransactionContext {
>      private final ExtendedTransactionManager txnManager;
>      private Transaction transaction;
>      private boolean threadAssociated = false;
> +    private Map managedConnections;
>
>      protected  
> InheritableTransactionContext(ExtendedTransactionManager txnManager) {
>          this.txnManager = txnManager;
> @@ -55,9 +60,26 @@
>          return transaction;
>      }
>
> +    public void setManagedConnectionInfo(ConnectionReleaser key,  
> Object info) {
> +        if (managedConnections == null) {
> +            managedConnections = new HashMap();
> +        }
> +        managedConnections.put(key, info);
> +    }
> +
> +    public Object getManagedConnectionInfo(ConnectionReleaser key) {
> +        if (managedConnections == null) {
> +            return null;
> +        }
> +        return managedConnections.get(key);
> +    }
> +
>      public boolean isActive() {
> +        if (transaction == null) {
> +            return false;
> +        }
>          try {
> -            int status = txnManager.getStatus();
> +            int status = transaction.getStatus();
>              return status == Status.STATUS_ACTIVE || status ==  
> Status.STATUS_MARKED_ROLLBACK;
>          } catch (SystemException e) {
>              return false;
> @@ -65,7 +87,6 @@
>      }
>
>      public boolean getRollbackOnly() throws SystemException {
> -        Transaction transaction = getTransaction();
>          if (transaction == null) {
>              throw new IllegalStateException("There is no transaction  
> in progress.");
>          }
> @@ -77,7 +98,6 @@
>      }
>
>      public void setRollbackOnly() throws IllegalStateException,  
> SystemException {
> -        Transaction transaction = getTransaction();
>          if (transaction == null) {
>              throw new IllegalStateException("There is no transaction  
> in progress.");
>          }
> @@ -85,13 +105,16 @@
>      }
>
>      public void begin(long transactionTimeoutMilliseconds) throws  
> SystemException, NotSupportedException {
> +        assert transaction == null:  "Already associated with a  
> transaction";
>          transaction =  
> txnManager.begin(transactionTimeoutMilliseconds);
>          threadAssociated = true;
>      }
>
>      public void suspend() throws SystemException {
>          Transaction suspendedTransaction = txnManager.suspend();
> -        assert (transaction == suspendedTransaction) : "suspend did  
> not return our transaction. ours: " + transaction + ", suspended  
> returned: " + suspendedTransaction;
> +        if (transaction != suspendedTransaction) {
> +            throw new SystemException("Suspend did not return our  
> transaction: expectedTx=" + transaction + ", suspendedTx=" +  
> suspendedTransaction);
> +        }
>          threadAssociated = false;
>      }
>
> @@ -101,6 +124,29 @@
>      }
>
>      public boolean commit() throws HeuristicMixedException,  
> HeuristicRollbackException, SystemException, RollbackException {
> +        return complete();
> +    }
> +
> +    public void rollback() throws SystemException {
> +        setRollbackOnly();
> +        try {
> +            complete();
> +        } catch (SystemException e) {
> +            throw e;
> +        } catch (RuntimeException e) {
> +            throw e;
> +        } catch (Error e) {
> +            throw e;
> +        } catch (Exception e) {
> +            throw (SystemException) new SystemException("After commit  
> of container transaction failed").initCause(e);
> +        }
> +    }
> +
> +    private boolean complete() throws HeuristicMixedException,  
> HeuristicRollbackException, SystemException, RollbackException {
> +        if (transaction == null) {
> +            throw new IllegalStateException("There is no transaction  
> in progress.");
> +        }
> +
>          boolean wasCommitted = false;
>          try {
>              if (isRolledback()) {
> @@ -120,6 +166,14 @@
>                  return false;
>              }
>
> +            // verify our tx is the current tx associated with the  
> thread
> +            // this is really only an error case and should never  
> happen, but just to be sure double check
> +            // immedately before committing using the transaction  
> manager
> +            Transaction currentTransaction =  
> txnManager.getTransaction();
> +            if (currentTransaction != transaction) {
> +                throw new SystemException("An unknown transaction is  
> currently associated with the thread: expectedTx=" + transaction + ",  
> currentTx=" + currentTransaction);
> +            }
> +
>              txnManager.commit();
>              wasCommitted = true;
>          } catch (Throwable t) {
> @@ -130,23 +184,82 @@
>              } catch (Throwable e) {
>                  rollbackAndThrow("After commit of container  
> transaction failed", e);
>              } finally {
> +                unassociateAll();
>                  connectorAfterCommit();
>                  transaction = null;
> +                threadAssociated = false;
>              }
>          }
>          return wasCommitted;
>      }
>
> +    private void beforeCommit() throws Throwable {
> +        // @todo allow for enrollment during pre-commit
> +        ArrayList toFlush = getAssociatedContexts();
> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
> +            InstanceContext context = (InstanceContext) i.next();
> +            if (!context.isDead()) {
> +                context.beforeCommit();
> +            }
> +        }
> +    }
> +
> +    private void afterCommit(boolean status) throws Throwable {
> +        Throwable firstThrowable = null;
> +        ArrayList toFlush = getAssociatedContexts();
> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
> +            InstanceContext context = (InstanceContext) i.next();
> +            if (!context.isDead()) {
> +                try {
> +                    context.afterCommit(status);
> +                } catch (Throwable e) {
> +                    if (firstThrowable == null) {
> +                        firstThrowable = e;
> +                    }
> +                }
> +            }
> +        }
> +
> +        if (firstThrowable instanceof Error) {
> +            throw (Error) firstThrowable;
> +        } else if (firstThrowable instanceof Exception) {
> +            throw (Exception) firstThrowable;
> +        } else if (firstThrowable != null) {
> +            throw (SystemException) new  
> SystemException().initCause(firstThrowable);
> +        }
> +    }
> +
> +    private void connectorAfterCommit() {
> +        if (managedConnections != null) {
> +            for (Iterator entries =  
> managedConnections.entrySet().iterator(); entries.hasNext();) {
> +                Map.Entry entry = (Map.Entry) entries.next();
> +                ConnectionReleaser key = (ConnectionReleaser)  
> entry.getKey();
> +                key.afterCompletion(entry.getValue());
> +            }
> +            //If BeanTransactionContext never reuses the same  
> instance for sequential BMT, this
> +            //clearing is unnecessary.
> +            managedConnections.clear();
> +        }
> +    }
> +
>      private boolean isRolledback() throws SystemException {
>          int status;
>          try {
>              status = transaction.getStatus();
>          } catch (SystemException e) {
> -            txnManager.rollback();
> +            transaction.rollback();
>              throw e;
>          }
>
>          if (status == Status.STATUS_MARKED_ROLLBACK) {
> +            // verify our tx is the current tx associated with the  
> thread
> +            // this is really only an error case and should never  
> happen, but just to be sure double check
> +            // immedately before committing using the transaction  
> manager
> +            Transaction currentTransaction =  
> txnManager.getTransaction();
> +            if (currentTransaction != transaction) {
> +                throw new SystemException("An unknown transaction is  
> currently associated with the thread: expectedTx=" + transaction + ",  
> currentTx=" + currentTransaction);
> +            }
> +
>              // we need to rollback
>              txnManager.rollback();
>              return true;
> @@ -160,7 +273,6 @@
>
>      private void rollbackAndThrow(String message, Throwable  
> throwable) throws HeuristicMixedException, HeuristicRollbackException,  
> SystemException, RollbackException {
>          try {
> -            // just incase there is a junk transaction on the thread
>              if (txnManager.getStatus() !=  
> Status.STATUS_NO_TRANSACTION) {
>                  txnManager.rollback();
>              }
> @@ -168,6 +280,18 @@
>              log.error("Unable to roll back transaction", t);
>          }
>
> +        try {
> +            // make doubly sure our transaction was rolled back
> +            // this can happen when there was a junk transaction on  
> the thread
> +            int status = transaction.getStatus();
> +            if (status != Status.STATUS_ROLLEDBACK &&
> +                    status != Status.STATUS_ROLLING_BACK) {
> +                transaction.rollback();
> +            }
> +        } catch (Throwable t) {
> +            log.error("Unable to roll back transaction", t);
> +        }
> +
>          if (throwable instanceof HeuristicMixedException) {
>              throw (HeuristicMixedException) throwable;
>          } else if (throwable instanceof HeuristicRollbackException) {
> @@ -182,41 +306,6 @@
>              throw (RuntimeException) throwable;
>          } else {
>              throw (SystemException) new  
> SystemException(message).initCause(throwable);
> -        }
> -    }
> -
> -    public void rollback() throws SystemException {
> -        try {
> -            try {
> -                if (txnManager.getStatus() !=  
> Status.STATUS_NO_TRANSACTION) {
> -                    txnManager.rollback();
> -                }
> -            } finally {
> -                try {
> -                    afterCommit(false);
> -                } catch (Throwable e) {
> -                    try {
> -                        // just incase there is a junk transaction on  
> the thread
> -                        if (txnManager.getStatus() !=  
> Status.STATUS_NO_TRANSACTION) {
> -                            txnManager.rollback();
> -                        }
> -                    } catch (Throwable t1) {
> -                        log.error("Unable to roll back transaction",  
> t1);
> -                    }
> -
> -                    if (e instanceof SystemException) {
> -                        throw (SystemException) e;
> -                    } else if (e instanceof Error) {
> -                        throw (Error) e;
> -                    } else if (e instanceof RuntimeException) {
> -                        throw (RuntimeException) e;
> -                    }
> -                    throw (SystemException) new  
> SystemException("After commit of container transaction  
> failed").initCause(e);
> -                }
> -            }
> -        } finally {
> -            connectorAfterCommit();
> -            transaction = null;
>          }
>      }
>  }
>
> Modified:  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/TransactionContext.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
> java/org/apache/geronimo/transaction/context/TransactionContext.java? 
> view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/TransactionContext.java (original)
> +++  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/TransactionContext.java Fri Feb 25 15:10:24 2005
> @@ -18,27 +18,21 @@
>  package org.apache.geronimo.transaction.context;
>
>  import java.util.ArrayList;
> -import java.util.HashMap;
>  import java.util.Iterator;
> -import java.util.Map;
>  import javax.transaction.HeuristicMixedException;
>  import javax.transaction.HeuristicRollbackException;
>  import javax.transaction.InvalidTransactionException;
>  import javax.transaction.RollbackException;
>  import javax.transaction.SystemException;
> -import javax.transaction.Transaction;
>
>  import org.apache.commons.logging.Log;
>  import org.apache.commons.logging.LogFactory;
> -import org.apache.geronimo.transaction.ConnectionReleaser;
>  import org.apache.geronimo.transaction.DoubleKeyedHashMap;
>  import org.apache.geronimo.transaction.InstanceContext;
>  import org.tranql.cache.InTxCache;
>
>
>  /**
> - *
> - *
>   * @version $Rev$ $Date$
>   */
>  public abstract class TransactionContext {
> @@ -56,9 +50,12 @@
>      private InstanceContext currentContext;
>      private final DoubleKeyedHashMap associatedContexts = new  
> DoubleKeyedHashMap();
>      private final DoubleKeyedHashMap dirtyContexts = new  
> DoubleKeyedHashMap();
> -    private Map managedConnections;
>      private InTxCache inTxCache;
>
> +    public abstract boolean getRollbackOnly() throws SystemException;
> +
> +    public abstract void setRollbackOnly() throws SystemException;
> +
>      public abstract void suspend() throws SystemException;
>
>      public abstract void resume() throws SystemException,  
> InvalidTransactionException;
> @@ -73,21 +70,51 @@
>          }
>      }
>
> -    public final void unassociate(Object containerId, Object id)  
> throws Exception {
> -        associatedContexts.remove(containerId, id);
> -        dirtyContexts.remove(containerId, id);
> +    public final void unassociate(InstanceContext context) throws  
> Throwable {
> +        associatedContexts.remove(context.getContainerId(),  
> context.getId());
> +        context.unassociate();
> +    }
> +
> +    public final void unassociate(Object containerId, Object id)  
> throws Throwable {
> +        InstanceContext context = (InstanceContext)  
> associatedContexts.remove(containerId, id);
> +        if (context != null) {
> +            context.unassociate();
> +        }
> +    }
> +
> +    public final InstanceContext getContext(Object containerId,  
> Object id) {
> +        return (InstanceContext) associatedContexts.get(containerId,  
> id);
> +    }
> +
> +    protected final ArrayList getAssociatedContexts() {
> +        return new ArrayList(associatedContexts.values());
> +    }
> +
> +    protected final void unassociateAll() {
> +        ArrayList toFlush = getAssociatedContexts();
> +        for (Iterator i = toFlush.iterator(); i.hasNext();) {
> +            InstanceContext context = (InstanceContext) i.next();
> +            try {
> +                context.unassociate();
> +            } catch (Throwable throwable) {
> +                log.warn("Error while unassociating instance from  
> transaction context: " + context, throwable);
> +            }
> +        }
>      }
>
> -    public final InstanceContext beginInvocation(InstanceContext  
> context) {
> +    public final InstanceContext beginInvocation(InstanceContext  
> context) throws Throwable {
>          if (context.getId() != null) {
> +            associate(context);
>              dirtyContexts.put(context.getContainerId(),  
> context.getId(), context);
>          }
> +        context.enter();
>          InstanceContext caller = currentContext;
>          currentContext = context;
>          return caller;
>      }
>
>      public final void endInvocation(InstanceContext caller) {
> +        currentContext.exit();
>          currentContext = caller;
>      }
>
> @@ -97,7 +124,9 @@
>              dirtyContexts.clear();
>              for (Iterator i = toFlush.iterator(); i.hasNext();) {
>                  InstanceContext context = (InstanceContext) i.next();
> -                context.flush();
> +                if (!context.isDead()) {
> +                    context.flush();
> +                }
>              }
>          }
>          if (currentContext != null && currentContext.getId() != null)  
> {
> @@ -108,42 +137,6 @@
>          }
>      }
>
> -    protected void beforeCommit() throws Throwable {
> -        // @todo allow for enrollment during pre-commit
> -        ArrayList toFlush = new  
> ArrayList(associatedContexts.values());
> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
> -            InstanceContext context = (InstanceContext) i.next();
> -            context.beforeCommit();
> -        }
> -    }
> -
> -    protected void afterCommit(boolean status) throws Throwable {
> -        Throwable firstThrowable = null;
> -        ArrayList toFlush = new  
> ArrayList(associatedContexts.values());
> -        for (Iterator i = toFlush.iterator(); i.hasNext();) {
> -            InstanceContext context = (InstanceContext) i.next();
> -            try {
> -                context.afterCommit(status);
> -            } catch (Throwable e) {
> -                if (firstThrowable == null) {
> -                    firstThrowable = e;
> -                }
> -            }
> -        }
> -
> -        if (firstThrowable instanceof Error) {
> -            throw (Error) firstThrowable;
> -        } else if (firstThrowable instanceof Exception) {
> -            throw (Exception) firstThrowable;
> -        } else if (firstThrowable != null) {
> -            throw (SystemException) new  
> SystemException().initCause(firstThrowable);
> -        }
> -    }
> -
> -    public final InstanceContext getContext(Object containerId,  
> Object id) {
> -        return (InstanceContext) associatedContexts.get(containerId,  
> id);
> -    }
> -
>      public final void setInTxCache(InTxCache inTxCache) {
>          this.inTxCache = inTxCache;
>      }
> @@ -151,42 +144,4 @@
>      public final InTxCache getInTxCache() {
>          return inTxCache;
>      }
> -
> -    //Geronimo connector framework support
> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
> Object info) {
> -        if (managedConnections == null) {
> -            managedConnections = new HashMap();
> -        }
> -        managedConnections.put(key, info);
> -    }
> -
> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
> -        if (managedConnections == null) {
> -            return null;
> -        }
> -        return managedConnections.get(key);
> -    }
> -
> -    /**
> -     * determines if the transaction is in a pre-prepared state
> -     * of STATUS_ACTIVE or STATUS_MARKED_ROLLBACK.
> -     * @return true if more work can be done in the transaction  
> (although it might be forced to roll back)
> -     */
> -    public abstract boolean isActive();
> -
> -    public abstract Transaction getTransaction();
> -
> -    protected void connectorAfterCommit() {
> -        if (managedConnections != null) {
> -            for (Iterator entries =  
> managedConnections.entrySet().iterator(); entries.hasNext();) {
> -                Map.Entry entry = (Map.Entry) entries.next();
> -                ConnectionReleaser key = (ConnectionReleaser)  
> entry.getKey();
> -                key.afterCompletion(entry.getValue());
> -            }
> -            //If BeanTransactionContext never reuses the same  
> instance for sequential BMT, this
> -            //clearing is unnecessary.
> -            managedConnections.clear();
> -        }
> -    }
> -
>  }
>
> Modified:  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/UnspecifiedTransactionContext.java
> URL:  
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/transaction/src/ 
> java/org/apache/geronimo/transaction/context/ 
> UnspecifiedTransactionContext.java?view=diff&r1=155375&r2=155376
> ======================================================================= 
> =======
> ---  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/UnspecifiedTransactionContext.java (original)
> +++  
> geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/ 
> transaction/context/UnspecifiedTransactionContext.java Fri Feb 25  
> 15:10:24 2005
> @@ -17,16 +17,18 @@
>
>  package org.apache.geronimo.transaction.context;
>
> -import javax.transaction.Transaction;
> -
> -import org.apache.geronimo.transaction.ConnectionReleaser;
> -
> -
>  /**
>   * @version $Rev$ $Date$
>   */
>  public class UnspecifiedTransactionContext extends TransactionContext  
> {
> -    public void begin() {
> +    private boolean failed = false;
> +
> +    public boolean getRollbackOnly() {
> +        return failed;
> +    }
> +
> +    public void setRollbackOnly() {
> +        this.failed = true;
>      }
>
>      public void suspend() {
> @@ -36,33 +38,28 @@
>      }
>
>      public boolean commit() {
> +        complete();
> +        return true;
> +    }
> +
> +    public void rollback() {
> +        setRollbackOnly();
> +        complete();
> +    }
> +
> +    private void complete() {
>          try {
> -            flushState();
> +            if (!failed) {
> +                flushState();
> +            }
>          } catch (Error e) {
>              throw e;
>          } catch (RuntimeException re) {
>              throw re;
>          } catch (Throwable e) {
>              log.error("Unable to flush state, continuing", e);
> +        } finally {
> +            unassociateAll();
>          }
> -        return true;
> -    }
> -
> -    public void rollback() {
> -    }
> -
> -    public void setManagedConnectionInfo(ConnectionReleaser key,  
> Object info) {
> -    }
> -
> -    public Object getManagedConnectionInfo(ConnectionReleaser key) {
> -        return null;
> -    }
> -
> -    public boolean isActive() {
> -        return false;
> -    }
> -
> -    public Transaction getTransaction() {
> -        return null;
>      }
>  }
>
>