[jboss-cvs] JBossAS SVN: r76006 - in projects/ejb3/trunk: core/src/main/java/org/jboss/ejb3/mdb and 6 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jul 18 18:37:00 EDT 2008


Author: pferraro
Date: 2008-07-18 18:37:00 -0400 (Fri, 18 Jul 2008)
New Revision: 76006

Added:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/BlockContainerShutdownInterceptor.java
Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/EJBContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/ConsumerContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MDB.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MessagingContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/service/ServiceContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateless/StatelessContainer.java
   projects/ejb3/trunk/core/src/main/resources/ejb3-interceptors-aop.xml
   projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/ejbthree1116/unit/ContainerShutdownTestCase.java
Log:
[EJBTHREE-1116] Clustered container sees requests during shutdown.
Leverage read-write lock to support clean startup/shutdown of an EJBContainer.
Write lock is acquired on create(), released after start(), and re-acquired on stop().
Read locks are acquired/released via interceptor early in the chain.

Added: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/BlockContainerShutdownInterceptor.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/BlockContainerShutdownInterceptor.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/BlockContainerShutdownInterceptor.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.concurrent.locks.Lock;
+
+import org.jboss.aop.DispatcherConnectException;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.joinpoint.Invocation;
+
+/**
+ * An interceptor that blocks container shutdown until the interceptor chain completes
+ * and rejects invocations if container is not completely started or is stopped.
+ * 
+ * @author Paul Ferraro
+ */
+public class BlockContainerShutdownInterceptor implements Interceptor, Serializable
+{
+   private static final long serialVersionUID = -1683253088746668495L;
+   
+   /**
+    * @see org.jboss.aop.advice.Interceptor#getName()
+    */
+   public String getName()
+   {
+      return this.getClass().getName();
+   }
+
+   /**
+    * @see org.jboss.aop.advice.Interceptor#invoke(org.jboss.aop.joinpoint.Invocation)
+    */
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      EJBContainer container = EJBContainer.getEJBContainer(invocation.getAdvisor());
+      
+      Lock lock = container.getInvocationLock();
+      
+      if (!lock.tryLock())
+      {
+         throw new DispatcherConnectException("EJB container is not completely started, or is stopped.");
+      }
+      
+      try
+      {
+         return invocation.invokeNext();
+      }
+      finally
+      {
+         lock.unlock();
+      }
+   }
+}

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/EJBContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/EJBContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/EJBContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -35,6 +35,9 @@
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
@@ -181,6 +184,9 @@
    
    protected boolean reinitialize = false;
    
+   // To support clean startup/shutdown
+   private ReadWriteLock containerLock = new ReentrantReadWriteLock();
+   
    /**
     * @param name                  Advisor name
     * @param manager               Domain to get interceptor bindings from
@@ -829,6 +835,8 @@
 
    public void create() throws Exception
    {
+      // Lock until start()
+      this.getContainerLock().lock();
       /*
       initializeClassContainer();
       for (int i = 0; i < constructors.length; i++)
@@ -842,8 +850,15 @@
       */
    }
 
+   public final void start() throws Exception
+   {
+      this.lockedStart();
+      
+      this.getContainerLock().unlock();
+   }
+   
    // Everything must be done in start to make sure all dependencies have been satisfied
-   public void start() throws Exception
+   protected void lockedStart() throws Exception
    {
       if (reinitialize)
          reinitialize();
@@ -870,8 +885,15 @@
       log.info("STARTED EJB: " + beanClass.getName() + " ejbName: " + ejbName);
    }
 
-   public void stop() throws Exception
+   public final void stop() throws Exception
    {
+      this.getContainerLock().lockInterruptibly();
+      
+      this.lockedStop();
+   }
+   
+   protected void lockedStop() throws Exception
+   {
       reinitialize = true;
       
       //encFactory.cleanupEnc(this);
@@ -1500,6 +1522,16 @@
       return bridgeMethod;
    }
    
+   public Lock getInvocationLock()
+   {
+      return this.containerLock.readLock();
+   }
+   
+   private Lock getContainerLock()
+   {
+      return this.containerLock.writeLock();
+   }
+   
    public String toString()
    {
       return getObjectName().getCanonicalName();

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/ConsumerContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/ConsumerContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/ConsumerContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -252,9 +252,10 @@
     *
     * @throws Exception Failed to initalize.
     */
-   public void start() throws Exception
+   @Override
+   protected void lockedStart() throws Exception
    {
-      super.start();
+      super.lockedStart();
       
       registerProducers();
    }
@@ -301,9 +302,10 @@
       activationSpec.merge(md.activationConfig());
    }
 
-   public void stop() throws Exception
+   @Override
+   protected void lockedStop() throws Exception
    {
       unregisterProducers();
-      super.stop();
+      super.lockedStop();
    }
 }

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MDB.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MDB.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MDB.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -132,11 +132,6 @@
       list.add(getMessagingType());
       return list;
    }
-   
-   public void start() throws Exception
-   {
-      super.start();
-   }
 
    public ObjectName getJmxName()
    {

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MessagingContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MessagingContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/mdb/MessagingContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -159,9 +159,10 @@
     *
     * @throws Exception Failed to initalize.
     */
-   public void start() throws Exception
+   @Override
+   protected void lockedStart() throws Exception
    {
-      super.start();
+      super.lockedStart();
 
       populateActivationSpec();
          
@@ -293,8 +294,8 @@
       }
    }
 
-
-   public void stop() throws Exception
+   @Override
+   protected void lockedStop() throws Exception
    {
       if (timerService != null)
       {
@@ -304,7 +305,7 @@
 
       stopProxies();
       
-      super.stop();
+      super.lockedStop();
    }
 
    protected void stopProxies() throws Exception

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/service/ServiceContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/service/ServiceContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/service/ServiceContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -203,9 +203,10 @@
       invokeOptionalMethod("create");
    }
    
-   public void start() throws Exception
+   @Override
+   protected void lockedStart() throws Exception
    {
-      super.start();
+      super.lockedStart();
 
       try
       {
@@ -226,11 +227,12 @@
       catch (Exception e)
       {
          e.printStackTrace();
-         stop();
+         this.lockedStop();
       }
    }
 
-   public void stop() throws Exception
+   @Override
+   protected void lockedStop() throws Exception
    {
       invokeOptionalMethod("stop");
       
@@ -246,7 +248,7 @@
       singleton = null;
       beanContext = null;
       
-      super.stop();
+      super.lockedStop();
    }
 
    public void destroy() throws Exception

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/session/SessionContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -180,9 +180,9 @@
       return list;
    }
    
-   public void start() throws Exception
+   protected void lockedStart() throws Exception
    {
-      super.start();
+      super.lockedStart();
       // So that Remoting layer can reference this container easily.
       Dispatcher.singleton.registerTarget(getObjectName().getCanonicalName(), new ClassProxyHack(this));
       proxyDeployer.start();
@@ -208,7 +208,7 @@
       return clusterFamilies;
    }
 
-   public void stop() throws Exception
+   protected void lockedStop() throws Exception
    {
       try
       {
@@ -226,7 +226,7 @@
       {
          log.debug("Dispatcher unregister target failed", ignore);
       }
-      super.stop();
+      super.lockedStop();
    }
 
    @Override

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateful/StatefulContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -278,18 +278,19 @@
       this.cache.start();
    }
    
-   public void start() throws Exception
+   @Override
+   protected void lockedStart() throws Exception
    {
       try
       {
-         super.start();
+         super.lockedStart();
          this.createAndStartCache();
       }
       catch (Exception e)
       {
          try
          {
-            stop();
+            this.lockedStop();
          }
          catch (Exception ignore)
          {
@@ -300,10 +301,12 @@
 
    }
 
-   public void stop() throws Exception
+   @Override
+   protected void lockedStop() throws Exception
    {
-      super.stop();
       if (cache != null) cache.stop();
+      
+      super.lockedStop();
    }
 
    public StatefulCache getCache()

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateless/StatelessContainer.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateless/StatelessContainer.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/stateless/StatelessContainer.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -195,11 +195,12 @@
       this.timeout = getTimeoutCallback(timeoutMethodMetaData, getBeanClass());
    }
    
-   public void start() throws Exception
+   @Override
+   protected void lockedStart() throws Exception
    {
       try
       {
-         super.start();
+         super.lockedStart();
          
          timerService = TimerServiceFactory.getInstance().createTimerService(this, this);
          
@@ -209,7 +210,7 @@
       {
          try
          {
-            stop();
+            this.lockedStop();
          }
          catch (Exception ignore)
          {
@@ -219,7 +220,8 @@
       }
    }
 
-   public void stop() throws Exception
+   @Override
+   protected void lockedStop() throws Exception
    {
       if (timerService != null)
       {
@@ -227,7 +229,7 @@
          timerService = null;
       }
       
-      super.stop();
+      super.lockedStop();
    }
 
    public TimerService getTimerService()

Modified: projects/ejb3/trunk/core/src/main/resources/ejb3-interceptors-aop.xml
===================================================================
--- projects/ejb3/trunk/core/src/main/resources/ejb3-interceptors-aop.xml	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/core/src/main/resources/ejb3-interceptors-aop.xml	2008-07-18 22:37:00 UTC (rev 76006)
@@ -82,6 +82,7 @@
    <interceptor class="org.jboss.ejb3.AllowedOperationsInterceptor" scope="PER_VM"/>
    <interceptor factory="org.jboss.ejb3.mdb.CurrentMessageInjectorInterceptorFactory" scope="PER_CLASS"/>
    <interceptor class="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor" scope="PER_VM"/>
+   <interceptor class="org.jboss.ejb3.BlockContainerShutdownInterceptor" scope="PER_VM"/>
 
    <!--
          INTERCEPTORS
@@ -140,6 +141,7 @@
       
       <bind pointcut="execution(public * *->*(..))">
          <interceptor-ref name="org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor"/>
+         <interceptor-ref name="org.jboss.ejb3.BlockContainerShutdownInterceptor"/>
       </bind>
    </domain>
    

Modified: projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/ejbthree1116/unit/ContainerShutdownTestCase.java
===================================================================
--- projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/ejbthree1116/unit/ContainerShutdownTestCase.java	2008-07-18 21:11:21 UTC (rev 76005)
+++ projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/ejbthree1116/unit/ContainerShutdownTestCase.java	2008-07-18 22:37:00 UTC (rev 76006)
@@ -54,6 +54,8 @@
    {
       MyStateful bean = (MyStateful) new InitialContext().lookup("MyStatefulBean/remote");
       
+      bean.increment();
+      
       this.undeploy(JAR);
       
       try
@@ -80,10 +82,33 @@
    {
       MyStateful bean = (MyStateful) new InitialContext().lookup("MyStatefulBean/remote");
       
-      CountDownLatch latch = new CountDownLatch(2);
+      bean.increment();
       
-      Thread thread = new Thread(new Undeployer(latch));
+      final CountDownLatch latch = new CountDownLatch(2);
       
+      Thread thread = new Thread()
+      {
+         @Override
+         public void run()
+         {
+            try
+            {
+               latch.countDown();
+               latch.await();
+               
+               ContainerShutdownTestCase.this.undeploy(JAR);
+            }
+            catch (InterruptedException e)
+            {
+               Thread.currentThread().interrupt();
+            }
+            catch (Exception e)
+            {
+               ContainerShutdownTestCase.this.log.error(e.getMessage(), e);
+            }
+         }
+      };
+      
       thread.start();
       
       latch.countDown();
@@ -125,36 +150,7 @@
          }
       }
    }
-   
-   private class Undeployer implements Runnable
-   {
-      private CountDownLatch latch;
-      
-      public Undeployer(CountDownLatch latch)
-      {
-         this.latch = latch;
-      }
-      
-      public void run()
-      {
-         try
-         {
-            this.latch.countDown();
-            this.latch.await();
 
-            ContainerShutdownTestCase.this.undeploy(JAR);
-         }
-         catch (InterruptedException e)
-         {
-            Thread.currentThread().interrupt();
-         }
-         catch (Exception e)
-         {
-            ContainerShutdownTestCase.this.log.error(e.getMessage(), e);
-         }
-      }
-   }
-
    public static Test suite() throws Exception
    {
       return getDeploySetup(ContainerShutdownTestCase.class, JAR);




More information about the jboss-cvs-commits mailing list