[jboss-cvs] JBossAS SVN: r80330 - in projects/ejb3/trunk/core/src: test/java/org/jboss/ejb3/core/test/ejbthree1549 and 1 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Nov 2 03:29:10 EST 2008


Author: ALRubinger
Date: 2008-11-02 03:29:10 -0500 (Sun, 02 Nov 2008)
New Revision: 80330

Added:
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCache.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCacheFactory.java
Removed:
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCacheFactory.java
Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulBean.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulLocal.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java
Log:
[EJBTHREE-1549] Add tests that Removal does not lock up w/ Passivation in progress

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -57,8 +57,8 @@
    protected CacheMap cacheMap;
    private int maxSize = 1000;
    private StatefulSessionPersistenceManager pm;
-   protected long sessionTimeout = 300; // 5 minutes
-   private long removalTimeout = 0; 
+   private long sessionTimeout = 300; // 5 minutes
+   private long removalTimeout = 0; // 0 == Never
    private Thread timeoutTask;
    private RemovalTimeoutTask removalTask = null;
    private boolean running = true;
@@ -114,20 +114,35 @@
       }
    }
    
-   private class RemovalTimeoutTask extends Thread
+   protected class RemovalTimeoutTask extends Thread
    {
       public RemovalTimeoutTask(String name)
       {
          super(name);
       }
+      
+      protected void block() throws InterruptedException
+      {
+         Thread.sleep(removalTimeout * 1000);
+      }
+      
+      protected void preRemoval()
+      {
+         
+      }
+      
+      protected void postRemoval()
+      {
+         
+      }
 
       public void run()
       {
          while (running)
-         {
+         { 
             try
             {
-               Thread.sleep(removalTimeout * 1000);
+               this.block();
             }
             catch (InterruptedException e)
             {
@@ -136,6 +151,9 @@
             }
             try
             {
+               // Invoke pre-removal callback
+               this.preRemoval();
+               
                long now = System.currentTimeMillis();
                
                synchronized (cacheMap)
@@ -166,8 +184,11 @@
                   {
                      get(centry.getId(), false);
                      remove(centry.getId());
-                  }               
+                  }
                }
+               
+               // Invoke post-removal callback
+               this.postRemoval();
             }
             catch (Exception ex)
             {
@@ -274,8 +295,8 @@
                prePassivationCompleted();
                
                StatefulBeanContext ctx;
-               while((ctx = passivationQueue.poll()) != null)
-               {
+               while ((ctx = passivationQueue.poll()) != null)
+               {  
                   passivate(ctx);
                }
                
@@ -589,4 +610,24 @@
    {
       this.timeoutTask = timeoutTask;
    }
+
+   protected long getSessionTimeout()
+   {
+      return sessionTimeout;
+   }
+
+   protected long getRemovalTimeout()
+   {
+      return removalTimeout;
+   }
+
+   protected RemovalTimeoutTask getRemovalTask()
+   {
+      return removalTask;
+   }
+
+   protected void setRemovalTask(RemovalTimeoutTask removalTask)
+   {
+      this.removalTask = removalTask;
+   }
 }

Copied: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCache.java (from rev 80328, projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java)
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCache.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCache.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -0,0 +1,375 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.core.test.ejbthree1549;
+
+import java.io.Serializable;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import org.jboss.ejb3.cache.simple.SimpleStatefulCache;
+import org.jboss.ejb3.stateful.StatefulBeanContext;
+import org.jboss.logging.Logger;
+
+/**
+ * ForceEventsCache
+ * 
+ * An extension of the SimpleStatefulCache which provides for
+ * forcing the Passivation and Removal tasks to run, also supplanting
+ * barriers and locks throughout the tasks' lifecycle callbacks
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class ForceEventsCache extends SimpleStatefulCache
+{
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   private static final Logger log = Logger.getLogger(ForceEventsCache.class);
+
+   /**
+    * Shared barrier between the Cache and the test so that 
+    * the test may block until passivation is completed
+    */
+   public static final CyclicBarrier POST_PASSIVATE_BARRIER = new CyclicBarrier(2);
+
+   /**
+    * Internal lock used to manually block the passivation task from running
+    */
+   private static final Object START_PASSIVATION_LOCK = new Object();
+
+   private static volatile boolean passivationForced = false;
+
+   /**
+    * Internal lock used to manually block the removal task from running
+    */
+   private static final Object START_REMOVAL_LOCK = new Object();
+
+   /**
+    * Flag that removal has been forced
+    */
+   private static volatile boolean removalForced = false;
+
+   public static final CyclicBarrier PRE_PASSIVATE_BARRIER = new CyclicBarrier(2);
+
+   /**
+    * Public barrier for removal to block until both test and removal tasks are ready
+    */
+   public static final CyclicBarrier PRE_REMOVE_BARRIER = new CyclicBarrier(2);
+
+   // --------------------------------------------------------------------------------||
+   // Functional Methods -------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   public void clear()
+   {
+      cacheMap.clear();
+   }
+
+   /**
+    * Triggers passivation to run
+    */
+   public static void forcePassivation()
+   {
+      // Get a lock
+      log.info("Awaiting lock to force passivation");
+      synchronized (START_PASSIVATION_LOCK)
+      {
+         passivationForced = true;
+         // Notify that passivation should run
+         log.info("Notifying passivation via manual force...");
+         START_PASSIVATION_LOCK.notify();
+      }
+   }
+
+   /**
+    * Triggers removal to run
+    */
+   public static void forceRemoval()
+   {
+      // Get a lock
+      log.info("Awaiting lock to force removal");
+      synchronized (START_REMOVAL_LOCK)
+      {
+         removalForced = true;
+         // Notify that removal should run
+         log.info("Notifying removal via manual force...");
+         START_REMOVAL_LOCK.notify();
+      }
+   }
+
+   /**
+    * Manually sets the session with the specified sessionId
+    * past expiry for passivation
+    * 
+    * @param sessionId
+    */
+   public void makeSessionEligibleForPassivation(Serializable sessionId)
+   {
+      this.setSessionLastUsedPastTimeout(sessionId, this.getSessionTimeout());
+   }
+
+   /**
+    * Manually sets the session with the specified sessionId
+    * past expiry for removal
+    * 
+    * @param sessionId
+    */
+   public void makeSessionEligibleForRemoval(Serializable sessionId)
+   {
+      this.setSessionLastUsedPastTimeout(sessionId, this.getRemovalTimeout());
+   }
+
+   /**
+    * Exposed for testing only
+    * 
+    * Returns whether or not the internal cacheMap contains
+    * the specified key
+    * 
+    * @return
+    */
+   public boolean doesCacheMapContainKey(Serializable sessionId)
+   {
+      // Get the cacheMap
+      CacheMap cm = this.cacheMap;
+
+      // Synchronize on it
+      synchronized (cm)
+      {
+         // Return whether the specified key was found
+         return cm.containsKey(sessionId);
+      }
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Overridden Implementations -----------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Lifecycle start, overridden to switch up the Passivate and Removal tasks to
+    * test-specific implementations
+    */
+   @Override
+   public void start()
+   {
+      // Initialize
+      String threadNamePrefix = "EJBTHREE-1549 SFSB Thread: ";
+
+      // Switch up the Passivation and Removal Tasks to blocking implementations
+      this.setTimeoutTask(new BlockingPassivationTask(threadNamePrefix + "PASSIVATION"));
+      this.setRemovalTask(new BlockingRemovalTask(threadNamePrefix + "REMOVAL"));
+
+      // Call super implementation
+      super.start();
+
+   }
+
+   /**
+    * BlockingRemovalTask
+    * 
+    * An extension of the default removal task which, instead 
+    * of waiting for a timeout, will block until forced
+    *
+    * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+    * @version $Revision: $
+    */
+   private class BlockingRemovalTask extends RemovalTimeoutTask
+   {
+      public BlockingRemovalTask(String name)
+      {
+         super(name);
+      }
+
+      @Override
+      public void block() throws InterruptedException
+      {
+         // Get a lock on our monitor
+         synchronized (START_REMOVAL_LOCK)
+         {
+            if (!removalForced)
+            {
+               // Wait until we're signaled
+               log.info("Waiting to be notified to run removal...");
+               START_REMOVAL_LOCK.wait();
+            }
+            removalForced = false;
+         }
+
+         // Log that we've been notified
+         log.info("Notified to run removal");
+      }
+
+      @Override
+      protected void preRemoval()
+      {
+
+         // Block until the barrier is cleared
+         try
+         {
+            PRE_REMOVE_BARRIER.await();
+         }
+         catch (InterruptedException e)
+         {
+            throw new RuntimeException(e);
+         }
+         catch (BrokenBarrierException e)
+         {
+            throw new RuntimeException(e);
+         }
+
+         // Invoke super implementation
+         super.preRemoval();
+      }
+
+   }
+
+   /**
+    * BlockingPassivationTask
+    * 
+    * An extension of the default timeout task which, instead of 
+    * waiting for a timeout, will await (block until) notification that passivation
+    * should run
+    *
+    * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+    * @version $Revision: $
+    */
+   private class BlockingPassivationTask extends SessionTimeoutTask
+   {
+
+      public BlockingPassivationTask(String name)
+      {
+         super(name);
+      }
+
+      @Override
+      public void block() throws InterruptedException
+      {
+         // Get a lock on our monitor
+         synchronized (START_PASSIVATION_LOCK)
+         {
+            if (!passivationForced)
+            {
+               // Wait until we're signaled
+               log.info("Waiting to be notified to run passivation...");
+               START_PASSIVATION_LOCK.wait();
+            }
+            passivationForced = false;
+         }
+
+         // Log that we've been notified
+         log.info("Notified to run passivation");
+      }
+
+      @Override
+      protected void passivationCompleted()
+      {
+         // Call super
+         super.passivationCompleted();
+
+         // Tell the barrier we've arrived
+         try
+         {
+            log.info("Waiting on the post-passivate barrier...");
+            POST_PASSIVATE_BARRIER.await();
+         }
+         catch (InterruptedException e)
+         {
+            throw new RuntimeException("Post Passivate prematurely interrupted", e);
+         }
+         catch (BrokenBarrierException e)
+         {
+            throw new RuntimeException("Post Passivate prematurely broken", e);
+         }
+         finally
+         {
+            // Reset the barrier
+            log.info("Post-passivate of PM is done, resetting the barrier");
+            POST_PASSIVATE_BARRIER.reset();
+         }
+      }
+
+      @Override
+      protected void prePassivationCompleted()
+      {
+         super.prePassivationCompleted();
+
+         try
+         {
+            PRE_PASSIVATE_BARRIER.await();
+         }
+         catch (BrokenBarrierException e)
+         {
+            throw new RuntimeException("PRE_PASSIVATE_BARRIER prematurely broken", e);
+         }
+         catch (InterruptedException e)
+         {
+            throw new RuntimeException(e);
+         }
+      }
+   }
+
+   // --------------------------------------------------------------------------------||
+   // Internal Helper Methods --------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Obtains a time in the past further away than the specified timeout value,
+    * expressed in milliseconds since the epoch (per contract of System.currentTimeMillis()
+    * 
+    * @param timeoutValue
+    * @return
+    */
+   private long getExpiredTime(long timeoutValue)
+   {
+      long now = System.currentTimeMillis();
+      return (now - (timeoutValue * 1000)) - 1;
+   }
+
+   /**
+    * Marks the session with the specified ID as last used past the 
+    * specified timeout period
+    * 
+    * @param sessionId
+    * @param timeout
+    */
+   private void setSessionLastUsedPastTimeout(Serializable sessionId, long timeout)
+   {
+      // Get the cacheMap
+      CacheMap cm = this.cacheMap;
+
+      // Synchronize on it
+      synchronized (cm)
+      {
+         // Find the session
+         StatefulBeanContext session = (StatefulBeanContext) cm.get(sessionId);
+
+         // Synchronize on the session
+         synchronized (session)
+         {
+            // Manually set past expiry
+            session.lastUsed = this.getExpiredTime(timeout);
+         }
+      }
+   }
+
+}
\ No newline at end of file

Copied: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCacheFactory.java (from rev 80327, projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCacheFactory.java)
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCacheFactory.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForceEventsCacheFactory.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.core.test.ejbthree1549;
+
+import org.jboss.ejb3.cache.Ejb3CacheFactory;
+import org.jboss.ejb3.cache.StatefulCache;
+
+/**
+ * ForceEventsCacheFactory
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class ForceEventsCacheFactory implements Ejb3CacheFactory
+{
+
+   // --------------------------------------------------------------------------------||
+   // Class Members ------------------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Name under which this Cache Factory will be bound into the registry
+    */
+   public static final String REGISTRY_BIND_NAME = "ForceEventsCache";
+
+   // --------------------------------------------------------------------------------||
+   // Required Implementations -------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /*
+    * (non-Javadoc)
+    * @see org.jboss.ejb3.cache.Ejb3CacheFactory#createCache()
+    */
+   public StatefulCache createCache()
+   {
+      return new ForceEventsCache();
+   }
+
+}

Deleted: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCache.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -1,238 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
-  *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.core.test.ejbthree1549;
-
-import java.io.Serializable;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-import org.jboss.ejb3.cache.simple.SimpleStatefulCache;
-import org.jboss.ejb3.stateful.StatefulBeanContext;
-import org.jboss.logging.Logger;
-
-/**
- * ForcePassivationCache
- * 
- * An extension of the SimpleStatefulCache which provides for
- * forcing the Passivation Thread to run
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public class ForcePassivationCache extends SimpleStatefulCache
-{
-   // --------------------------------------------------------------------------------||
-   // Class Members ------------------------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   private static final Logger log = Logger.getLogger(ForcePassivationCache.class);
-
-   /**
-    * Shared barrier between the Cache and the test so that 
-    * the test may block until passivation is completed
-    */
-   public static final CyclicBarrier POST_PASSIVATE_BARRIER = new CyclicBarrier(2);
-
-   /**
-    * Internal lock used to manually block the passivation task from running
-    */
-   private static final Object START_PASSIVATION_LOCK = new Object();
-   private static volatile boolean passivationForced = false;
-   
-   public static final CyclicBarrier PRE_PASSIVATE_BARRIER = new CyclicBarrier(2);
-
-   // --------------------------------------------------------------------------------||
-   // Functional Methods -------------------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   public void clear()
-   {
-      cacheMap.clear();
-   }
-   
-   /**
-    * Triggers passivation to run
-    */
-   public static void forcePassivation()
-   {
-      // Get a lock
-      log.info("Awaiting lock to force passivation");
-      synchronized (START_PASSIVATION_LOCK)
-      {
-         passivationForced = true;
-         // Notify that passivation should run
-         log.info("Notifying passivation via manual force...");
-         START_PASSIVATION_LOCK.notify();
-      }
-   }
-
-   /**
-    * Manually sets the session with the specified sessionId
-    * past expiry for passivation
-    * 
-    * @param sessionId
-    */
-   public void makeSessionEligibleForPassivation(Serializable sessionId)
-   {
-      // Get the cacheMap
-      CacheMap cm = this.cacheMap;
-
-      // Synchronize on it
-      synchronized (cm)
-      {
-         // Find the session
-         StatefulBeanContext session = (StatefulBeanContext) cm.get(sessionId);
-
-         // Synchronize on the session
-         synchronized (session)
-         {
-            // Get now
-            long now = System.currentTimeMillis();
-
-            // Manually set past expiry
-            session.lastUsed = (now - (sessionTimeout * 1000)) - 1;
-         }
-      }
-   }
-
-   /**
-    * Exposed for testing only
-    * 
-    * Returns whether or not the internal cacheMap contains
-    * the specified key
-    * 
-    * @return
-    */
-   public boolean doesCacheMapContainKey(Serializable sessionId)
-   {
-      // Get the cacheMap
-      CacheMap cm = this.cacheMap;
-
-      // Synchronize on it
-      synchronized (cm)
-      {
-         // Return whether the specified key was found
-         return cm.containsKey(sessionId);
-      }
-   }
-
-   // --------------------------------------------------------------------------------||
-   // Overridden Implementations -----------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   @Override
-   public void start()
-   {
-      // Switch up the Timeout (Passivation) Task to a blocking implementation
-      this.setTimeoutTask(new BlockingPassivationTask("EJBTHREE-1549 SFSB Passivation Thread"));
-
-      // Call super implementation
-      super.start();
-
-   }
-
-   /**
-    * BlockingPassivationTask
-    * 
-    * An extension of the default timeout task which, instead of 
-    * waiting for a timeout, will await (block until) notification that passivation
-    * should run
-    *
-    * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
-    * @version $Revision: $
-    */
-   private class BlockingPassivationTask extends SessionTimeoutTask
-   {
-
-      public BlockingPassivationTask(String name)
-      {
-         super(name);
-      }
-
-      @Override
-      public void block() throws InterruptedException
-      {
-         // Get a lock on our monitor
-         synchronized (START_PASSIVATION_LOCK)
-         {
-            if(!passivationForced)
-            {
-               // Wait until we're signaled
-               log.info("Waiting to be notified to run passivation...");
-               START_PASSIVATION_LOCK.wait();
-            }
-            passivationForced = false;
-         }
-
-         // Log that we've been notified
-         log.info("Notified to run passivation");
-      }
-
-      @Override
-      protected void passivationCompleted()
-      {
-         // Call super
-         super.passivationCompleted();
-
-         // Tell the barrier we've arrived
-         try
-         {
-            log.info("Waiting on the post-passivate barrier...");
-            POST_PASSIVATE_BARRIER.await();
-         }
-         catch (InterruptedException e)
-         {
-            throw new RuntimeException("Post Passivate prematurely interrupted", e);
-         }
-         catch (BrokenBarrierException e)
-         {
-            throw new RuntimeException("Post Passivate prematurely broken", e);
-         }
-         finally
-         {
-            // Reset the barrier
-            log.info("Post-passivate of PM is done, resetting the barrier");
-            POST_PASSIVATE_BARRIER.reset();
-         }
-      }
-      
-      @Override
-      protected void prePassivationCompleted()
-      {
-         super.prePassivationCompleted();
-         
-         try
-         {
-            PRE_PASSIVATE_BARRIER.await();
-         }
-         catch (BrokenBarrierException e)
-         {
-            throw new RuntimeException("PRE_PASSIVATE_BARRIER prematurely broken", e);
-         }
-         catch(InterruptedException e)
-         {
-            throw new RuntimeException(e);
-         }
-      }
-   }
-
-}
\ No newline at end of file

Deleted: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCacheFactory.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCacheFactory.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/ForcePassivationCacheFactory.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -1,58 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
-  *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.core.test.ejbthree1549;
-
-import org.jboss.ejb3.cache.Ejb3CacheFactory;
-import org.jboss.ejb3.cache.StatefulCache;
-
-/**
- * ForcePassivationCacheFactory
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public class ForcePassivationCacheFactory implements Ejb3CacheFactory
-{
-
-   // --------------------------------------------------------------------------------||
-   // Class Members ------------------------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   /**
-    * Name under which this Cache Factory will be bound into the registry
-    */
-   public static final String REGISTRY_BIND_NAME = "ForcePassivationCache";
-
-   // --------------------------------------------------------------------------------||
-   // Required Implementations -------------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   /*
-    * (non-Javadoc)
-    * @see org.jboss.ejb3.cache.Ejb3CacheFactory#createCache()
-    */
-   public StatefulCache createCache()
-   {
-      return new ForcePassivationCache();
-   }
-
-}

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulBean.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulBean.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulBean.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -35,7 +35,9 @@
  * A SFSB with the following overrides:
  * 
  * 1) Uses a Cache implementation that provides mechanism to
- * force passivation (instead of waiting upon a Thread.sleep timeout)
+ * block tasks such as passivation and removal, in addition to 
+ * adding support for internal lifecycle implementations for these
+ * tasks
  * 
  * 2) Uses a backing PersistenceManager that provides mechanism to
  * block completion of passivation from the test until ready
@@ -47,14 +49,14 @@
 @Local(MyStatefulLocal.class)
 @LocalBinding(jndiBinding = MyStatefulLocal.JNDI_NAME)
 /*
- * Use a CacheFctory that instead of using a timed reaping Thread,
- * exposes a static "forcePassivation" method for the tests 
+ * Use a CacheFactory that is extended to enable 
+ * blocking hooks that we need for testing
  */
- at Cache(ForcePassivationCacheFactory.REGISTRY_BIND_NAME)
+ at Cache(ForceEventsCacheFactory.REGISTRY_BIND_NAME)
 /*
- * Make instances eligible for timeout very soon after last invocation
+ * Make instances eligible for timeout very soon after last invocation, and be removed (as default is NEVER)
  */
- at CacheConfig(idleTimeoutSeconds = MyStatefulLocal.PASSIVATION_TIMEOUT)
+ at CacheConfig(idleTimeoutSeconds = MyStatefulLocal.PASSIVATION_TIMEOUT, removalTimeoutSeconds = MyStatefulLocal.REMOVAL_TIMEOUT)
 /*
  * Set up a persistence manager that allows us to block, and therefore
  * lets the test decide how long the processes of performing passivation

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulLocal.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulLocal.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/MyStatefulLocal.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -36,9 +36,11 @@
    // --------------------------------------------------------------------------------||
 
    String JNDI_NAME = "TestSFSB/local";
-   
+
    int PASSIVATION_TIMEOUT = 1;
 
+   int REMOVAL_TIMEOUT = 100;
+
    // --------------------------------------------------------------------------------||
    // Contracts ----------------------------------------------------------------------||
    // --------------------------------------------------------------------------------||

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java	2008-11-02 07:52:23 UTC (rev 80329)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/core/test/ejbthree1549/unit/PassivationDoesNotPreventNewActivityUnitTestCase.java	2008-11-02 08:29:10 UTC (rev 80330)
@@ -26,6 +26,7 @@
 
 import java.io.Serializable;
 import java.lang.reflect.Proxy;
+import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -40,8 +41,8 @@
 import org.jboss.ejb3.core.test.common.AbstractEJB3TestCase;
 import org.jboss.ejb3.core.test.ejbthree1549.BlockingPersistenceManager;
 import org.jboss.ejb3.core.test.ejbthree1549.BlockingPersistenceManagerFactory;
-import org.jboss.ejb3.core.test.ejbthree1549.ForcePassivationCache;
-import org.jboss.ejb3.core.test.ejbthree1549.ForcePassivationCacheFactory;
+import org.jboss.ejb3.core.test.ejbthree1549.ForceEventsCache;
+import org.jboss.ejb3.core.test.ejbthree1549.ForceEventsCacheFactory;
 import org.jboss.ejb3.core.test.ejbthree1549.MyStatefulBean;
 import org.jboss.ejb3.core.test.ejbthree1549.MyStatefulLocal;
 import org.jboss.ejb3.proxy.handler.session.stateful.StatefulLocalProxyInvocationHandler;
@@ -75,13 +76,132 @@
    // Tests --------------------------------------------------------------------------||
    // --------------------------------------------------------------------------------||
 
+   /**
+    * Tests that removal may take place during the course 
+    * of passivation
+    */
    @Test
+   public void testSessionRemovalDuringPassivation() throws Throwable
+   {
+      /*
+       * First we invoke upon a new session
+       */
+
+      // Initialize
+      final String sfsbJndiName = MyStatefulLocal.JNDI_NAME;
+
+      // Create a new session, which should be allowed during passivation
+      MyStatefulLocal sfsb = (MyStatefulLocal) container.getInitialContext().lookup(sfsbJndiName);
+
+      // If we've got nothing
+      if (sfsb == null)
+      {
+         // Fail
+         TestCase.fail("Lookup did not succeed");
+      }
+
+      // Invoke upon the new Session
+      final int next = sfsb.getNextCounter();
+
+      // Test the value is expected
+      TestCase.assertEquals("Next counter received was not expected", 0, next);
+
+      /*
+       * Mark this session as eligible for removal
+       */
+
+      // Get the cache
+      ForceEventsCache cache = (ForceEventsCache) container.getCache();
+
+      // Get the Session ID
+      Serializable sessionId = this.getSessionId(sfsb);
+
+      // Mark
+      cache.makeSessionEligibleForRemoval(sessionId);
+
+      /*
+       * All's OK with traditional invocation, so define a task to force removal 
+       * of the SFSB, but don't invoke it yet (we're going to fire this off 
+       * *during* passivation
+       */
+
+      // Define the task to invoke upon a SFSB, and trigger removal while passivation is suspended
+      Callable<Boolean> invokeDuringPasssivationTest = new Callable<Boolean>()
+      {
+         /**
+          * Force removal
+          */
+         public Boolean call()
+         {
+
+            /*
+             * Force removal
+             */
+
+            // Force
+            ForceEventsCache.forceRemoval();
+
+            // Clear the barrier
+            try
+            {
+               log.info("Test is waiting on the pre-remove barrier");
+               ForceEventsCache.PRE_REMOVE_BARRIER.await();
+               log.info("Test has cleared the pre-remove barrier");
+            }
+            catch (InterruptedException e)
+            {
+               throw new RuntimeException(e);
+            }
+            catch (BrokenBarrierException e)
+            {
+               throw new RuntimeException(e);
+            }
+
+            // Return OK
+            return true;
+
+         }
+      };
+
+      /*
+       * Force passivation, but block it from completing (because we don't 
+       * await on the PM)
+       */
+      
+      // Force passivation
+      ForceEventsCache.forcePassivation();
+      ForceEventsCache.PRE_PASSIVATE_BARRIER.await();
+      
+
+      /*
+       * Spawn off the test in another Thread
+       */
+
+      ExecutorService executor = Executors.newFixedThreadPool(1);
+      Future<Boolean> futureResult = executor.submit(invokeDuringPasssivationTest);
+      Boolean result = null;
+
+      /*
+       * Try to get the result of the test to remove, which 
+       * should not be blocked by passivation already in progress
+       */
+
+      // Get result
+      log.info("Attempting to get the result of the removal task...");
+      result = futureResult.get(5, TimeUnit.SECONDS);
+
+      // Make sure the result is expected
+      TestCase.assertTrue("Removal task completed when expected, but got wrong result", result);
+   }
+
+   @Test
    public void testInvokeSameSessionDuringPassivation() throws Throwable
    {
       final MyStatefulLocal bean = lookup(MyStatefulLocal.JNDI_NAME, MyStatefulLocal.class);
-      
+
       // Get our bean's Session ID
-      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy.getInvocationHandler(bean);
+      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
+            .getInvocationHandler(bean);
       Serializable sessionId = handler.getSessionId();
 
       // Invoke upon our bean
@@ -90,7 +210,7 @@
       TestCase.assertEquals("SFSB did not return expected next counter", 0, next);
 
       // Get the Cache
-      ForcePassivationCache cache = (ForcePassivationCache) container.getCache();
+      ForceEventsCache cache = (ForceEventsCache) container.getCache();
 
       // Get the lock to block the PM, now
       boolean gotLock = BlockingPersistenceManager.PASSIVATION_LOCK.tryLock();
@@ -102,7 +222,7 @@
          // Ensure we got the PM lock, else fail the test
          TestCase.assertTrue("Test was not able to immediately get the lock to block the PersistenceManager", gotLock);
          log.info("Locked " + BlockingPersistenceManager.class.getSimpleName());
-         
+
          // Mark
          cache.makeSessionEligibleForPassivation(sessionId);
 
@@ -111,17 +231,18 @@
           */
 
          // Trigger Passivation
-         ForcePassivationCache.forcePassivation();
+         ForceEventsCache.forcePassivation();
          log.info("Passivation forced, carrying out test");
 
-         ForcePassivationCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
-         
+         ForceEventsCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+
          // Block until the PM is ready to passivate
          log.info("Waiting on common barrier for PM to run...");
          BlockingPersistenceManager.BARRIER.await(5, TimeUnit.SECONDS);
          log.info("PM and test have met barrier, passivation running (but will be blocked to complete by test)");
-         
-         Callable<Integer> task = new Callable<Integer>() {
+
+         Callable<Integer> task = new Callable<Integer>()
+         {
             public Integer call() throws Exception
             {
                return bean.getNextCounter();
@@ -129,9 +250,9 @@
          };
          ExecutorService executor = Executors.newFixedThreadPool(1);
          result = executor.submit(task);
-         
+
          // TODO: there is no way to know where we are in StatefulInstanceInterceptor
-         Thread.sleep(5000);   
+         Thread.sleep(5000);
       }
       finally
       {
@@ -139,28 +260,30 @@
          log.info("Letting the PM perform passivation...");
          BlockingPersistenceManager.PASSIVATION_LOCK.unlock();
       }
-      
+
       // We need to allow time to let the Cache finish passivation, so block until it's done
       log.info("Waiting on Cache to tell us passivation is completed...");
-      ForcePassivationCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+      ForceEventsCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
       log.info("Test sees Cache reports passivation completed.");
-      
+
       int duringPassivation = result.get(5, TimeUnit.SECONDS);
       log.info("Got counter from " + sessionId + ": " + duringPassivation);
-      
+
       int postPassivation = bean.getNextCounter();
       log.info("Got counter from " + sessionId + ": " + postPassivation);
-      
-      assertEquals("the postPassivation counter should be 1 higher than the previous (during passivation)", duringPassivation + 1, postPassivation);
+
+      assertEquals("the postPassivation counter should be 1 higher than the previous (during passivation)",
+            duringPassivation + 1, postPassivation);
    }
-   
+
    @Test
    public void testInvokeSameSessionDuringPrePassivation() throws Throwable
    {
       final MyStatefulLocal bean = lookup(MyStatefulLocal.JNDI_NAME, MyStatefulLocal.class);
-      
+
       // Get our bean's Session ID
-      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy.getInvocationHandler(bean);
+      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
+            .getInvocationHandler(bean);
       Serializable sessionId = handler.getSessionId();
 
       // Invoke upon our bean
@@ -169,7 +292,7 @@
       TestCase.assertEquals("SFSB did not return expected next counter", 0, next);
 
       // Get the Cache
-      ForcePassivationCache cache = (ForcePassivationCache) container.getCache();
+      ForceEventsCache cache = (ForceEventsCache) container.getCache();
 
       // Get the lock to block the PM, now
       boolean gotLock = BlockingPersistenceManager.PASSIVATION_LOCK.tryLock();
@@ -181,7 +304,7 @@
          // Ensure we got the PM lock, else fail the test
          TestCase.assertTrue("Test was not able to immediately get the lock to block the PersistenceManager", gotLock);
          log.info("Locked " + BlockingPersistenceManager.class.getSimpleName());
-         
+
          // Mark
          cache.makeSessionEligibleForPassivation(sessionId);
 
@@ -190,10 +313,11 @@
           */
 
          // Trigger Passivation
-         ForcePassivationCache.forcePassivation();
+         ForceEventsCache.forcePassivation();
          log.info("Passivation forced, carrying out test");
 
-         Callable<Integer> task = new Callable<Integer>() {
+         Callable<Integer> task = new Callable<Integer>()
+         {
             public Integer call() throws Exception
             {
                return bean.getNextCounter();
@@ -201,12 +325,12 @@
          };
          ExecutorService executor = Executors.newFixedThreadPool(1);
          result = executor.submit(task);
-         
+
          // TODO: there is no way to know where we are in StatefulInstanceInterceptor
          Thread.sleep(5000);
-         
-         ForcePassivationCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
-         
+
+         ForceEventsCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+
          // Block until the PM is ready to passivate
          /* we're not passivating, we yanked it out
          log.info("Waiting on common barrier for PM to run...");
@@ -220,21 +344,22 @@
          log.info("Letting the PM perform passivation...");
          BlockingPersistenceManager.PASSIVATION_LOCK.unlock();
       }
-      
+
       // We need to allow time to let the Cache finish passivation, so block until it's done
       log.info("Waiting on Cache to tell us passivation is completed...");
-      ForcePassivationCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+      ForceEventsCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
       log.info("Test sees Cache reports passivation completed.");
-      
+
       int duringPassivation = result.get(5, TimeUnit.SECONDS);
       log.info("Got counter from " + sessionId + ": " + duringPassivation);
-      
+
       int postPassivation = bean.getNextCounter();
       log.info("Got counter from " + sessionId + ": " + postPassivation);
-      
-      assertEquals("the postPassivation counter should be 1 higher than the previous (during passivation)", duringPassivation + 1, postPassivation);
+
+      assertEquals("the postPassivation counter should be 1 higher than the previous (during passivation)",
+            duringPassivation + 1, postPassivation);
    }
-   
+
    /**
     * Tests that a new session may be created while another is being passivated
     */
@@ -245,23 +370,22 @@
       final String sfsbJndiName = MyStatefulLocal.JNDI_NAME;
 
       // Define the task to lookup a new session
-      TestThread lookupNewSessionTest = new TestThread("Lookup New Session Test Thread")
+      Callable<Boolean> lookupNewSessionTest = new Callable<Boolean>()
       {
          /**
           * Lookup a new session, and set that the test succeeded if we're able
           */
-         public void run()
+         public Boolean call()
          {
             try
             {
                // Create a new session, which should be allowed during passivation
                MyStatefulLocal bean2 = (MyStatefulLocal) container.getInitialContext().lookup(sfsbJndiName);
 
-               // If we've got a new session
-               if (bean2 != null)
+               // If we've don't have a new session
+               if (bean2 == null)
                {
-                  // Test is good
-                  this.setTestSucceeded(true);
+                  throw new RuntimeException("Got back null SFSB");
                }
 
             }
@@ -270,11 +394,14 @@
             {
                log.error("Test encountered an error", e);
             }
+
+            // Test is good
+            return true;
          }
       };
 
       // Run the Test
-      this.runTest(lookupNewSessionTest);
+      this.runTestDuringPassivation(lookupNewSessionTest);
    }
 
    /**
@@ -288,12 +415,12 @@
       final String sfsbJndiName = MyStatefulLocal.JNDI_NAME;
 
       // Define the task to invoke upon a SFSB
-      TestThread invokeDuringPasssivationTest = new TestThread("Invoke During Passivation Test Thread")
+      Callable<Boolean> invokeDuringPasssivationTest = new Callable<Boolean>()
       {
          /**
           * Lookup a new session, invoke upon it, and set that the test succeeded if we're able
           */
-         public void run()
+         public Boolean call()
          {
             try
             {
@@ -303,9 +430,8 @@
                // If we've got nothing
                if (bean2 == null)
                {
-                  // Let test fail, logging along the wayF
+                  // Let test fail, logging along the way
                   log.error("Lookup did not succeed");
-                  return;
                }
 
                // Invoke upon the new Session
@@ -314,8 +440,7 @@
                // Test the value
                if (next == 0)
                {
-                  this.setTestSucceeded(true);
-                  return;
+                  return true;
                }
 
                // Value was not expected, let the test fail and log
@@ -327,11 +452,14 @@
             {
                log.error("Test encountered an error", e);
             }
+
+            // Fail, should have gotten expected value and returned above
+            return false;
          }
       };
 
       // Run the Test
-      this.runTest(invokeDuringPasssivationTest);
+      this.runTestDuringPassivation(invokeDuringPasssivationTest);
    }
 
    // --------------------------------------------------------------------------------||
@@ -349,7 +477,7 @@
     * 6) Allows the test to complete either successfully or unsuccessfully, or times out if stuck
     * 7) Reports failure or success overall
     */
-   protected void runTest(TestThread testThread) throws Throwable
+   protected void runTestDuringPassivation(Callable<Boolean> testThread) throws Throwable
    {
       // Initialize
       final String sfsbJndiName = MyStatefulLocal.JNDI_NAME;
@@ -364,12 +492,10 @@
       TestCase.assertEquals("SFSB did not return expected next counter", 0, next);
 
       // Get our bean's Session ID
-      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
-            .getInvocationHandler(bean1);
-      Serializable sessionId = handler.getSessionId();
+      Serializable sessionId = this.getSessionId(bean1);
 
       // Get the Cache
-      ForcePassivationCache cache = (ForcePassivationCache) container.getCache();
+      ForceEventsCache cache = (ForceEventsCache) container.getCache();
 
       // Get the lock to block the PM, now
       boolean gotLock = BlockingPersistenceManager.PASSIVATION_LOCK.tryLock();
@@ -393,11 +519,11 @@
           */
 
          // Trigger Passivation
-         ForcePassivationCache.forcePassivation();
+         ForceEventsCache.forcePassivation();
          log.info("Passivation forced, carrying out test");
 
-         ForcePassivationCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
-         
+         ForceEventsCache.PRE_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+
          // Block until the PM is ready to passivate
          log.info("Waiting on common barrier for PM to run...");
          BlockingPersistenceManager.BARRIER.await(5, TimeUnit.SECONDS);
@@ -408,36 +534,26 @@
           * locked it from completing.  So let's try our test in another Thread
           * so we can detect a deadlock or permanent blocking after a timeout
           */
+         ExecutorService executor = Executors.newFixedThreadPool(1);
+         Future<Boolean> futureResult = executor.submit(testThread);
+         boolean result = futureResult.get(5, TimeUnit.SECONDS);
 
-         // Start up the test Thread
-         testThread.start();
+         /*
+          * Assert on the result
+          */
 
-         // Define a timeout for the Test Thread to complete
-         int timeoutSeconds = 5;
-         long startTime = System.currentTimeMillis();
-         long endTime = timeoutSeconds * 1000 + startTime;
+         // If the test has not succeeded
+         if (!result)
+         {
+            // Fail
+            TestCase.fail("The test has completed without success");
+         }
 
-         // Loop until timeout
-         while (System.currentTimeMillis() < endTime)
+         // If the test has been successful
+         else
          {
-            // If the test has not succeeded, and the test Thread is dead
-            if (!testThread.testSucceeded && !testThread.isAlive())
-            {
-               // Fail
-               TestCase.fail("The test has completed without success");
-               break;
-            }
-
-            // If the test has been successful
-            if (testThread.testSucceeded)
-            {
-               log.info("Test Succeeded");
-               testSucceeded = true;
-               break;
-            }
-
-            // Wait a little before looping again
-            Thread.sleep(50);
+            log.info("Test Succeeded");
+            testSucceeded = true;
          }
       }
       finally
@@ -450,7 +566,7 @@
 
       // We need to allow time to let the Cache finish passivation, so block until it's done
       log.info("Waiting on Cache to tell us passivation is completed...");
-      ForcePassivationCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
+      ForceEventsCache.POST_PASSIVATE_BARRIER.await(5, TimeUnit.SECONDS);
       log.info("Test sees Cache reports passivation completed.");
 
       /*
@@ -464,37 +580,6 @@
    }
 
    // --------------------------------------------------------------------------------||
-   // Inner Classes ------------------------------------------------------------------||
-   // --------------------------------------------------------------------------------||
-
-   /**
-    * Defines a test task to run alongside main test execution, providing
-    * hooks to test whether the task was successful or not
-    */
-   protected static class TestThread extends Thread
-   {
-      /**
-       * Whether or not the test succeeded
-       */
-      private boolean testSucceeded;
-
-      public TestThread(String threadName)
-      {
-         super(threadName);
-      }
-
-      public boolean isTestSucceeded()
-      {
-         return testSucceeded;
-      }
-
-      public void setTestSucceeded(boolean testSucceeded)
-      {
-         this.testSucceeded = testSucceeded;
-      }
-   }
-
-   // --------------------------------------------------------------------------------||
    // Lifecycle Methods --------------------------------------------------------------||
    // --------------------------------------------------------------------------------||
 
@@ -513,8 +598,8 @@
       // Add the Force Passivation Cache
       CacheFactoryRegistry cacheFactoryRegistry = Ejb3RegistrarLocator.locateRegistrar().lookup(
             "EJB3CacheFactoryRegistry", CacheFactoryRegistry.class);
-      String forcePassivationCacheRegistryName = ForcePassivationCacheFactory.REGISTRY_BIND_NAME;
-      cacheFactoryRegistry.getFactories().put(forcePassivationCacheRegistryName, ForcePassivationCacheFactory.class);
+      String forcePassivationCacheRegistryName = ForceEventsCacheFactory.REGISTRY_BIND_NAME;
+      cacheFactoryRegistry.getFactories().put(forcePassivationCacheRegistryName, ForceEventsCacheFactory.class);
       log.info("Added " + forcePassivationCacheRegistryName);
 
       // Deploy the test SFSB
@@ -522,13 +607,16 @@
       log.info("Deploying SFSB: " + ejbImplClass.getName());
       container = (StatefulContainer) deploySessionEjb(ejbImplClass);
    }
-   
+
    @After
    public void after()
    {
-      ForcePassivationCache.POST_PASSIVATE_BARRIER.reset();
-      ForcePassivationCache.PRE_PASSIVATE_BARRIER.reset();
-      ForcePassivationCache cache = (ForcePassivationCache) container.getCache();
+      log.info("Resetting all barriers and clearing the cache...");
+      ForceEventsCache.POST_PASSIVATE_BARRIER.reset();
+      ForceEventsCache.PRE_PASSIVATE_BARRIER.reset();
+      ForceEventsCache.PRE_REMOVE_BARRIER.reset();
+      BlockingPersistenceManager.BARRIER.reset();
+      ForceEventsCache cache = (ForceEventsCache) container.getCache();
       cache.clear();
    }
 
@@ -540,4 +628,20 @@
 
       AbstractEJB3TestCase.afterClass();
    }
+
+   // --------------------------------------------------------------------------------||
+   // Internal Helper Methods --------------------------------------------------------||
+   // --------------------------------------------------------------------------------||
+
+   /**
+    * Returns the Session ID of the specified proxy
+    */
+   private Serializable getSessionId(MyStatefulLocal bean)
+   {
+      // Get our bean's Session ID
+      StatefulLocalProxyInvocationHandler handler = (StatefulLocalProxyInvocationHandler) Proxy
+            .getInvocationHandler(bean);
+      Serializable sessionId = handler.getSessionId();
+      return sessionId;
+   }
 }




More information about the jboss-cvs-commits mailing list