You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2010/05/17 23:40:44 UTC

svn commit: r945401 - in /openejb/branches/openejb-3.1.x: ./ assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/ assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb....

Author: dblevins
Date: Mon May 17 21:40:43 2010
New Revision: 945401

URL: http://svn.apache.org/viewvc?rev=945401&view=rev
Log:
svn merge -r 944756:944757 https://svn.apache.org/repos/asf/openejb/trunk/openejb3

http://svn.apache.org/viewvc?rev=944757&view=rev
------------------------------------------------------------------------
r944757 | dblevins | 2010-05-15 19:40:43 -0700 (Sat, 15 May 2010) | 3 lines

OPENEJB-1279: Stateless PostConstruct called on undeploy/shutdown
OPENEJB-1235

------------------------------------------------------------------------

Added:
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/CountingLatch.java
      - copied unchanged from r944757, openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/CountingLatch.java
    openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/CountingLatchTest.java
      - copied unchanged from r944757, openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/CountingLatchTest.java
Modified:
    openejb/branches/openejb-3.1.x/   (props changed)
    openejb/branches/openejb-3.1.x/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
    openejb/branches/openejb-3.1.x/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
    openejb/branches/openejb-3.1.x/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
    openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
    openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java   (props changed)
    openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
    openejb/branches/openejb-3.1.x/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
    openejb/branches/openejb-3.1.x/examples/alternate-descriptors/src/main/resources/META-INF/test.ejb-jar.xml   (props changed)

Propchange: openejb/branches/openejb-3.1.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May 17 21:40:43 2010
@@ -1,2 +1,2 @@
 /openejb/branches/openejb-3.1.1:779593
-/openejb/trunk/openejb3:943472,943862,943965
+/openejb/trunk/openejb3:943472,943862,943965,944757

Modified: openejb/branches/openejb-3.1.x/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml Mon May 17 21:40:43 2010
@@ -251,6 +251,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
 

Modified: openejb/branches/openejb-3.1.x/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml Mon May 17 21:40:43 2010
@@ -251,6 +251,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
 

Modified: openejb/branches/openejb-3.1.x/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml Mon May 17 21:40:43 2010
@@ -251,6 +251,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
 

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java Mon May 17 21:40:43 2010
@@ -62,11 +62,11 @@ public class StatelessContainer implemen
     private Object containerID = null;
     private SecurityService securityService;
 
-    public StatelessContainer(Object id, SecurityService securityService, Duration accessTimeout, Pool.Builder poolBuilder, int callbackThreads) {
+    public StatelessContainer(Object id, SecurityService securityService, Duration accessTimeout, Duration closeTimeout, Pool.Builder poolBuilder, int callbackThreads) {
         this.containerID = id;
         this.securityService = securityService;
 
-        instanceManager = new StatelessInstanceManager(securityService, accessTimeout, poolBuilder, callbackThreads);
+        instanceManager = new StatelessInstanceManager(securityService, accessTimeout, closeTimeout, poolBuilder, callbackThreads);
 
         for (DeploymentInfo deploymentInfo : deploymentRegistry.values()) {
             org.apache.openejb.core.CoreDeploymentInfo di = (org.apache.openejb.core.CoreDeploymentInfo) deploymentInfo;

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java Mon May 17 21:40:43 2010
@@ -32,6 +32,7 @@ public class StatelessContainerFactory {
     private SecurityService securityService;
     private Duration accessTimeout;
     private int callbackThreads = 5;
+    private Duration closeTimeout;
 
     public void setCallbackThreads(int callbackThreads) {
         this.callbackThreads = callbackThreads;
@@ -105,7 +106,11 @@ public class StatelessContainerFactory {
         pool.setMaxAgeOffset(maxAgeOffset);
     }
 
+    public void setCloseTimeout(Duration closeTimeout) {
+        this.closeTimeout = closeTimeout;
+    }
+
     public StatelessContainer create() {
-        return new StatelessContainer(id, securityService, accessTimeout, pool, callbackThreads);
+        return new StatelessContainer(id, securityService, accessTimeout, closeTimeout, pool, callbackThreads);
     }
 }

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Mon May 17 21:40:43 2010
@@ -39,10 +39,6 @@ import javax.naming.NamingException;
 import javax.xml.ws.WebServiceContext;
 import javax.management.ObjectName;
 import javax.management.MBeanServer;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanRegistrationException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.InstanceNotFoundException;
 
 import org.apache.openejb.Injection;
 import org.apache.openejb.OpenEJBException;
@@ -72,7 +68,8 @@ import org.apache.xbean.recipe.Option;
 public class StatelessInstanceManager {
     private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources");
 
-    protected Duration timeout;
+    protected Duration accessTimeout;
+    protected Duration closeTimeout;
     protected int beanCount = 0;
 
     protected final SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager");
@@ -80,12 +77,13 @@ public class StatelessInstanceManager {
     private final Pool.Builder poolBuilder;
     private final Executor executor;
 
-    public StatelessInstanceManager(SecurityService securityService, Duration timeout, Pool.Builder poolBuilder, int callbackThreads) {
+    public StatelessInstanceManager(SecurityService securityService, Duration accessTimeout, Duration closeTimeout, Pool.Builder poolBuilder, int callbackThreads) {
         this.securityService = securityService;
-        this.timeout = timeout;
+        this.accessTimeout = accessTimeout;
+        this.closeTimeout = closeTimeout;
         this.poolBuilder = poolBuilder;
         
-        if (timeout.getUnit() == null) timeout.setUnit(TimeUnit.MILLISECONDS);
+        if (accessTimeout.getUnit() == null) accessTimeout.setUnit(TimeUnit.MILLISECONDS);
 
         executor = new ThreadPoolExecutor(callbackThreads, callbackThreads*2,
                 0L, TimeUnit.MILLISECONDS,
@@ -394,17 +392,20 @@ public class StatelessInstanceManager {
 
         final Pool.Builder builder = new Pool.Builder(poolBuilder);
 
-        String timeString = options.get("Timeout", this.timeout.toString());
+        String timeString = options.get("Timeout", this.accessTimeout.toString());
         timeString = options.get("AccessTimeout", timeString);
         Duration accessTimeout = new Duration(timeString);
 
+        String s = options.get("CloseTimeout", this.closeTimeout.toString());
+        Duration closeTimeout = new Duration(s);
+
         final ObjectRecipe recipe = PassthroughFactory.recipe(builder);
         recipe.setAllProperties(deploymentInfo.getProperties());
 
         builder.setSupplier(new StatelessSupplier(deploymentInfo));
         builder.setExecutor(executor);
         
-        Data data = new Data(builder.build(), accessTimeout);
+        Data data = new Data(builder.build(), accessTimeout, closeTimeout);
         deploymentInfo.setContainerData(data);
 
         final int min = builder.getMin();
@@ -474,11 +475,6 @@ public class StatelessInstanceManager {
     public void undeploy(CoreDeploymentInfo deploymentInfo) {
         Data data = (Data) deploymentInfo.getContainerData();
         if (data == null) return;
-        data.getPool().stop();
-
-        //TODO *maybe* call ejbRemove on each bean in pool.
-
-        deploymentInfo.setContainerData(null);
 
         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
         for (ObjectName objectName : data.jmxNames) {
@@ -488,16 +484,28 @@ public class StatelessInstanceManager {
                 logger.error("Unable to unregister MBean "+objectName);
             }
         }
+
+        try {
+            if (!data.closePool()) {
+                logger.error("Timed-out waiting for stateless pool to close: for deployment '" + deploymentInfo.getDeploymentID() + "'");
+            }
+        } catch (InterruptedException e) {
+            Thread.interrupted();
+        }
+
+        deploymentInfo.setContainerData(null);
     }
 
     private static final class Data {
         private final Pool<Instance> pool;
-        private Duration accessTimeout;
+        private final Duration accessTimeout;
+        private final Duration closeTimeout;
         private final List<ObjectName> jmxNames = new ArrayList<ObjectName>();
 
-        public Data(Pool<Instance> pool, Duration accessTimeout) {
-            this.accessTimeout = accessTimeout;
+        private Data(Pool<Instance> pool, Duration accessTimeout, Duration closeTimeout) {
             this.pool = pool;
+            this.accessTimeout = accessTimeout;
+            this.closeTimeout = closeTimeout;
         }
 
         public Duration getAccessTimeout() {
@@ -512,6 +520,10 @@ public class StatelessInstanceManager {
             return pool;
         }
 
+        public boolean closePool() throws InterruptedException {
+            return pool.close(closeTimeout.getTime(), closeTimeout.getUnit());
+        }
+
         public ObjectName add(ObjectName name) {
             jmxNames.add(name);
             return name;

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java Mon May 17 21:40:43 2010
@@ -70,6 +70,8 @@ public class Pool<T> {
     private final AtomicReference<Timer> timer = new AtomicReference<Timer>();
     private final Sweeper sweeper;
 
+    private final CountingLatch out = new CountingLatch();
+
     @Managed
     private final long interval;
 
@@ -112,11 +114,15 @@ public class Pool<T> {
 
     public void stop() {
         Timer timer = this.timer.get();
-        if (this.timer.compareAndSet(timer, null)) {
+        if (timer != null && this.timer.compareAndSet(timer, null)) {
             timer.cancel();
         }
     }
 
+    public boolean running() {
+        return timer.get() != null;
+    }
+
     private Executor createExecutor() {
         return new ThreadPoolExecutor(5, 10,
                                       0L, TimeUnit.SECONDS,
@@ -142,11 +148,28 @@ public class Pool<T> {
      * @return an entry from the pool or null indicating permission to create and push() an instance into the pool
      * @throws InterruptedException  vm level thread interruption
      * @throws IllegalStateException if a permit could not be acquired
-     * @throws TimeoutException      if no instance could be obtained within the timeout
+     * @throws java.util.concurrent.TimeoutException      if no instance could be obtained within the timeout
      */
     public Entry<T> pop(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
+        return pop(timeout, unit, true);
+    }
+
+    /**
+     * Any successful pop() call requires a corresponding push() or discard() call
+     * <p/>
+     * A pop() call that returns null is considered successful.
+     *
+     * @param timeout time to block while waiting for an instance
+     * @param unit    unit of time dicated by the timeout
+     * @param record should this be reflected in the stats
+     * @return an entry from the pool or null indicating permission to create and push() an instance into the pool
+     * @throws InterruptedException  vm level thread interruption
+     * @throws IllegalStateException if a permit could not be acquired
+     * @throws TimeoutException      if no instance could be obtained within the timeout
+     */
+    private Entry<T> pop(long timeout, TimeUnit unit, boolean record) throws InterruptedException, TimeoutException {
         if (!available.tryAcquire(timeout, unit)) {
-            stats.accessTimeouts.record();
+            if (record) stats.accessTimeouts.record();
             throw new TimeoutException("Waited " + timeout + " " + unit);
         }
 
@@ -346,6 +369,25 @@ public class Pool<T> {
         available.release();
     }
 
+    public boolean close(long timeout, TimeUnit unit) throws InterruptedException {
+        // drain all keys so no new instances will be accepted into the pool
+        while (instances.tryAcquire());
+        while (minimum.tryAcquire());
+
+        // Stop the sweeper thread
+        stop();
+
+        // flush and sweep
+        flush();
+        sweeper.run();
+
+        // Drain all leases
+        if (!(available instanceof Overdraft)) while (available.tryAcquire());
+
+        // Wait for any pending discards
+        return out.await(timeout, unit);
+    }
+
     /**
      * This internal method allows us to "swap" the status
      * of two entries before returning them to the pool.
@@ -468,7 +510,7 @@ public class Pool<T> {
             // Pull all the entries from the pool
             try {
                 while (true) {
-                    final Entry<T> entry = pop(0, MILLISECONDS);
+                    final Entry<T> entry = pop(0, MILLISECONDS, false);
                     if (entry == null) {
                         push(entry, true);
                         break;
@@ -640,6 +682,11 @@ public class Pool<T> {
         }
 
         public void run() {
+            if (!running()) {
+                discard(expired);
+                return;
+            }
+            
             try {
                 final T t = supplier.create();
 
@@ -665,6 +712,7 @@ public class Pool<T> {
         private final Event event;
 
         private Discard(T expired, Event event) {
+            out.countUp();
             if (expired == null) throw new NullPointerException("expired object cannot be null");
             this.expired = expired;
             this.event = event;
@@ -677,7 +725,11 @@ public class Pool<T> {
                 case FULL: stats.overdrafts.record(); break;
                 case IDLE: stats.idleTimeouts.record(); break;
             }
-            supplier.discard(expired, event);
+            try {
+                supplier.discard(expired, event);
+            } finally {
+                out.countDown();
+            }
         }
     }
 

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml Mon May 17 21:40:43 2010
@@ -244,6 +244,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
   <!--

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml Mon May 17 21:40:43 2010
@@ -246,6 +246,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
 

Propchange: openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May 17 21:40:43 2010
@@ -1,2 +1,2 @@
 /openejb/branches/openejb-3.1.1/container/openejb-core/src/test/java/org/apache/openejb/config/UberInterfaceTest.java:779593
-/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java:943472,943862,943965
+/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java:943472,943862,943965,944757

Modified: openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java Mon May 17 21:40:43 2010
@@ -259,6 +259,66 @@ public class PoolTest extends TestCase {
 
     }
 
+    public void testClose() throws Exception {
+        System.out.println("PoolTest.testClose");
+
+        final int min = 4;
+        final int max = 9;
+        final int sweepInterval = 200;
+        final int pause = 1000;
+
+        final List<Bean> discarded = new CopyOnWriteArrayList<Bean>();
+        final CountDownLatch discard = new CountDownLatch(max);
+        final Pool.Builder builder = new Pool.Builder();
+        builder.setPoolMin(min);
+        builder.setPoolMax(max);
+        builder.setPollInterval(new Duration(sweepInterval, TimeUnit.MILLISECONDS));
+        builder.setSupplier(new Pool.Supplier<Bean>() {
+            public void discard(Bean bean, Pool.Event reason) {
+                try {
+                    Thread.sleep(pause);
+                } catch (InterruptedException e) {
+                    Thread.interrupted();
+                }
+                bean.discard();
+                discarded.add(bean);
+                discard.countDown();
+            }
+
+            public Bean create() {
+                return new Bean();
+            }
+        });
+
+
+        final Pool pool = this.pool = builder.build().start();
+
+        // Fill pool to max
+        Bean.instances.set(0);
+        for (int i = 0; i < max; i++) {
+            assertTrue(pool.add(new Bean()));
+        }
+
+
+        { // Should have a full, non-null pool
+            final List entries = drain(pool, 100);
+            checkMin(min, entries);
+            checkEntries(max, entries);
+            push(pool, entries);
+        }
+
+        long start = System.currentTimeMillis();
+        assertTrue(pool.close(10, TimeUnit.SECONDS));
+        long time = System.currentTimeMillis() - start;
+
+        // All instances should have been removed
+        assertEquals(max, discarded.size());
+
+        // Should have taken at least three seconds
+        assertTrue(time >= pause);
+
+    }
+
     /**
      * Tests the idle timeout as well as the Thread pool
      * used to invoke the discard/create jobs.

Modified: openejb/branches/openejb-3.1.x/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.1.x/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=945401&r1=945400&r2=945401&view=diff
==============================================================================
--- openejb/branches/openejb-3.1.x/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml (original)
+++ openejb/branches/openejb-3.1.x/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml Mon May 17 21:40:43 2010
@@ -246,6 +246,17 @@
 
     CallbackThreads = 5
 
+    # PostConstruct methods are invoked on all instances in the pool
+    # when the bean is undeployed and its pool is closed.  The
+    # CloseTimeout specifies the maximum time to wait for the pool to
+    # close and PostConstruct methods to be invoked.
+    #
+    # Usable time units: nanoseconds, microsecons, milliseconds,
+    # seconds, minutes, hours, days.  Or any combination such as
+    # "1 hour and 27 minutes and 10 seconds"
+
+    CloseTimeout = 5 minutes
+
   </ServiceProvider>
 
 

Propchange: openejb/branches/openejb-3.1.x/examples/alternate-descriptors/src/main/resources/META-INF/test.ejb-jar.xml
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May 17 21:40:43 2010
@@ -1,2 +1,2 @@
 /openejb/branches/openejb-3.1.1/examples/alternate-descriptors/src/main/resources/META-INF/ejb-jar.xml:779593
-/openejb/trunk/openejb3/examples/alternate-descriptors/src/main/resources/META-INF/test.ejb-jar.xml:943472,943862,943965
+/openejb/trunk/openejb3/examples/alternate-descriptors/src/main/resources/META-INF/test.ejb-jar.xml:943472,943862,943965,944757