[jboss-cvs] JBossAS SVN: r112497 - projects/ejb3/branches/jboss-ejb3-core-1.3/src/main/java/org/jboss/ejb3/cache/simple.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Dec 1 04:10:18 EST 2011


Author: wolfc
Date: 2011-12-01 04:10:18 -0500 (Thu, 01 Dec 2011)
New Revision: 112497

Modified:
   projects/ejb3/branches/jboss-ejb3-core-1.3/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
Log:
JBPAPP-7523: make sure activation runs outside the lock

Modified: projects/ejb3/branches/jboss-ejb3-core-1.3/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java
===================================================================
--- projects/ejb3/branches/jboss-ejb3-core-1.3/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2011-12-01 09:09:54 UTC (rev 112496)
+++ projects/ejb3/branches/jboss-ejb3-core-1.3/src/main/java/org/jboss/ejb3/cache/simple/SimpleStatefulCache.java	2011-12-01 09:10:18 UTC (rev 112497)
@@ -21,14 +21,17 @@
  */
 package org.jboss.ejb3.cache.simple;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Queue;
-import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
 import java.util.concurrent.LinkedBlockingQueue;
-
 import javax.ejb.EJBException;
 import javax.ejb.NoSuchEJBException;
 
@@ -68,6 +71,8 @@
    
    private Queue<StatefulBeanContext> passivationQueue = new LinkedBlockingQueue<StatefulBeanContext>();
 
+   private Map<Object, FutureTask<StatefulBeanContext>> activations = new HashMap<Object, FutureTask<StatefulBeanContext>>();
+
    protected class CacheMap extends LinkedHashMap<Object, StatefulBeanContext>
    {
       private static final long serialVersionUID = 4514182777643616159L;
@@ -430,7 +435,7 @@
       return get(key, true);
    }
    
-   public StatefulBeanContext get(Object key, boolean markInUse) throws EJBException
+   public StatefulBeanContext get(final Object key, boolean markInUse) throws EJBException
    {
       StatefulBeanContext entry = null;
       synchronized (cacheMap)
@@ -465,34 +470,69 @@
       }
       if (entry == null)
       {
+         // JBPAPP-7523: create a task for activation while holding the pm lock,
+         // then execute said task outside the lock
+         FutureTask<StatefulBeanContext> activation;
+         final boolean executeActivation;
          synchronized(pm)
          {
-            synchronized (cacheMap)
+            activation = activations.get(key);
+            if (activation == null)
             {
-               entry = cacheMap.get(key);
-            }
-            if(entry == null)
-            {
-               entry = pm.activateSession(key);
-               if (entry == null)
+               activation = new FutureTask<StatefulBeanContext>(new Callable<StatefulBeanContext>()
                {
-                  throw new NoSuchEJBException("Could not find stateful bean: " + key);
-               }
-               --passivatedCount;
-               
-               // We cache the entry even if we will throw an exception below
-               // as we may still need it for its children and XPC references
-               if (log.isTraceEnabled())
-               {
-                  log.trace("Caching activated context " + entry.getId() + " of type " + entry.getClass());
-               }
-               
-               synchronized (cacheMap)
-               {
-                  cacheMap.put(key, entry);
-               }
+                  @Override
+                  public StatefulBeanContext call() throws Exception {
+                      StatefulBeanContext entry;
+                      synchronized (cacheMap)
+                      {
+                         entry = cacheMap.get(key);
+                      }
+                      if(entry == null)
+                      {
+                         entry = pm.activateSession(key);
+                         if (entry == null)
+                         {
+                            throw new NoSuchEJBException("Could not find stateful bean: " + key);
+                         }
+                         --passivatedCount;
+
+                         // We cache the entry even if we will throw an exception below
+                         // as we may still need it for its children and XPC references
+                         if (log.isTraceEnabled())
+                         {
+                            log.trace("Caching activated context " + entry.getId() + " of type " + entry.getClass());
+                         }
+
+                         synchronized (cacheMap)
+                         {
+                            cacheMap.put(key, entry);
+                         }
+                      }
+                      return entry;
+                  }
+               });
+               activations.put(key, activation);
+               executeActivation = true;
             }
+            else
+               executeActivation = false;
          }
+         if (executeActivation)
+            activation.run();
+         try {
+            entry = activation.get();
+         }
+         catch (InterruptedException e)
+         {
+            throw new EJBException(e);
+         }
+         catch (ExecutionException e)
+         {
+            if (e.getCause() instanceof RuntimeException)
+               throw (RuntimeException) e.getCause();
+            throw (EJBException) new EJBException().initCause(e.getCause());
+         }
       }
       
       // Now we know entry isn't null



More information about the jboss-cvs-commits mailing list