You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2012/04/11 22:57:56 UTC

svn commit: r1325009 - in /commons/proper/pool/trunk/src: java/org/apache/commons/pool2/impl/ test/org/apache/commons/pool2/ test/org/apache/commons/pool2/impl/

Author: markt
Date: Wed Apr 11 20:57:56 2012
New Revision: 1325009

URL: http://svn.apache.org/viewvc?rev=1325009&view=rev
Log:
POOL-131. Implement a form of logging for swallowed exceptions that makes the last 10 stack traces available via a getter and all swallowed stack traces are sent out via JMX notifications.
Added tests for JMX registration and deregistration and cleaned up a lot of tests that did not close the pool.
Enable test that were previously disabled for no obvious reason (since they currently pass).

Modified:
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java
    commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestBaseObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestKeyedObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java
    commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java Wed Apr 11 20:57:56 2012
@@ -17,8 +17,12 @@
 
 package org.apache.commons.pool2.impl;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -37,10 +41,17 @@ import java.util.concurrent.locks.ReadWr
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
 import javax.management.ObjectName;
 
 import org.apache.commons.pool2.KeyedObjectPool;
@@ -211,7 +222,7 @@ import org.apache.commons.pool2.PoolUtil
  * @since Pool 1.0
  */
 public class GenericKeyedObjectPool<K,T> implements KeyedObjectPool<K,T>,
-    GenericKeyedObjectPoolMBean<K> {
+    GenericKeyedObjectPoolMBean<K>, NotificationEmitter {
 
     //--- constructors -----------------------------------------------
 
@@ -250,6 +261,7 @@ public class GenericKeyedObjectPool<K,T>
         if (config.isJmxEnabled()) {
             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
             String jmxNamePrefix = config.getJmxNamePrefix();
+            this.jmxNotificationSupport = new NotificationBroadcasterSupport();
             int i = 1;
             boolean registered = false;
             while (!registered) {
@@ -281,8 +293,15 @@ public class GenericKeyedObjectPool<K,T>
                     registered = true;
                 }
             }
+        } else {
+            this.jmxNotificationSupport = null;
         }
         this.oname = onameTemp;
+        
+        // Populate the swallowed exceptions queue
+        for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) {
+            swallowedExceptions.add(null);
+        }
     }
 
     //--- configuration methods --------------------------------------
@@ -949,6 +968,10 @@ public class GenericKeyedObjectPool<K,T>
       * <p>If {@link #getTestOnReturn() testOnReturn} == true, the returning instance is validated before being returned
       * to the idle instance pool under the given key.  In this case, if validation fails, the instance is destroyed.</p>
       *
+      * <p>
+      * Exceptions encountered destroying objects for any reason are swallowed.
+      * </p>
+      * 
       * @param key pool key
       * @param t instance to return to the keyed pool
       * @throws Exception
@@ -972,7 +995,7 @@ public class GenericKeyedObjectPool<K,T>
                  try {
                      destroy(key, p, true);
                  } catch (Exception e) {
-                     // TODO - Ignore?
+                     swallowException(e);
                  }
                  updateStatsReturn(activeTime);
                  return;
@@ -982,10 +1005,11 @@ public class GenericKeyedObjectPool<K,T>
          try {
              factory.passivateObject(key, t);
          } catch (Exception e1) {
+             swallowException(e1);
              try {
                  destroy(key, p, true);
              } catch (Exception e) {
-                 // TODO - Ignore?
+                 swallowException(e);
              }
              updateStatsReturn(activeTime);
              return;
@@ -1004,7 +1028,7 @@ public class GenericKeyedObjectPool<K,T>
              try {
                  destroy(key, p, true);
              } catch (Exception e) {
-                 // TODO - Ignore?
+                 swallowException(e);
              }
          } else {
              if (getLifo()) {
@@ -1021,7 +1045,30 @@ public class GenericKeyedObjectPool<K,T>
          updateStatsReturn(activeTime);
      }
 
+     
+    private void swallowException (Exception e) {
+        // Need the exception in string form to prevent the retention of
+        // references to classes in the stack trace that could trigger a memory
+        // leak in a container environment
+        Writer w = new StringWriter();
+        PrintWriter pw = new PrintWriter(w);
+        e.printStackTrace(pw);
+        String msg = w.toString();
+
+        if (oname != null) {
+            Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION,
+                    oname, swallowedExcpetionCount.incrementAndGet(), msg);
+            jmxNotificationSupport.sendNotification(n);
+        }
+        
+        // Add the exception the queue, removing the oldest
+        synchronized (swallowedExceptions) {
+            swallowedExceptions.addLast(msg);
+            swallowedExceptions.pollFirst();
+        }
+    }
 
+         
      private void updateStatsReturn(long activeTime) {
          returnedCount.incrementAndGet();
          synchronized (activeTimes) {
@@ -1102,7 +1149,7 @@ public class GenericKeyedObjectPool<K,T>
                  try {
                      destroy(key, p, true);
                  } catch (Exception e) {
-                     // TODO - Ignore?
+                     swallowException(e);
                  }
                  p = idleObjects.poll();
              }
@@ -1281,7 +1328,7 @@ public class GenericKeyedObjectPool<K,T>
              try {
                  destroyed = destroy(key, p, false);
             } catch (Exception e) {
-                // TODO - Ignore?
+                swallowException(e);
             }
             if (destroyed) {
                 itemsToRemove--;
@@ -1871,7 +1918,7 @@ public class GenericKeyedObjectPool<K,T>
     }
 
 
-    //--- JMX specific attributes ----------------------------------------------
+    //--- JMX support ----------------------------------------------------------
 
     private void initStats() {
         for (int i = 0; i < AVERAGE_TIMING_STATS_CACHE_SIZE; i++) {
@@ -2014,6 +2061,63 @@ public class GenericKeyedObjectPool<K,T>
         }
     }
 
+    @Override
+    public String[] getSwallowedExceptions() {
+        List<String> temp =
+                new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE);
+        synchronized (swallowedExceptions) {
+            temp.addAll(swallowedExceptions);
+        }
+        return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]);
+    }
+
+    @Override
+    public void addNotificationListener(NotificationListener listener,
+            NotificationFilter filter, Object handback)
+            throws IllegalArgumentException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.addNotificationListener(
+                listener, filter, handback);
+    }
+
+    @Override
+    public void removeNotificationListener(NotificationListener listener)
+            throws ListenerNotFoundException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.removeNotificationListener(listener);
+    }
+
+    @Override
+    public MBeanNotificationInfo[] getNotificationInfo() {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        return jmxNotificationSupport.getNotificationInfo();
+    }
+
+    @Override
+    public void removeNotificationListener(NotificationListener listener,
+            NotificationFilter filter, Object handback)
+            throws ListenerNotFoundException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.removeNotificationListener(
+                listener, filter, handback);
+    }
+    
+    public ObjectName getJmxName() {
+        return oname;
+    }
+
     //--- inner classes ----------------------------------------------
 
     /**
@@ -2372,7 +2476,14 @@ public class GenericKeyedObjectPool<K,T>
     private final Object maxBorrowWaitTimeMillisLock = new Object();
     private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock")
 
+    public static final String NOTIFICATION_SWALLOWED_EXCEPTION =
+            "SWALLOWED_EXCEPTION";
+    private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10;
+    private final Deque<String> swallowedExceptions = new LinkedList<String>();
+    private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0);
+            
     private final ObjectName oname;
+    private final NotificationBroadcasterSupport jmxNotificationSupport;
 
     private static final String ONAME_BASE =
         "org.apache.commoms.pool2:type=GenericKeyedObjectPool,name=";

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMBean.java Wed Apr 11 20:57:56 2012
@@ -48,4 +48,5 @@ public interface GenericKeyedObjectPoolM
     long getMeanIdleTimeMillis();
     long getMeanBorrowWaitTimeMillis();
     long getMaxBorrowWaitTimeMillis();
+    String[] getSwallowedExceptions();
 }

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java Wed Apr 11 20:57:56 2012
@@ -17,8 +17,12 @@
 
 package org.apache.commons.pool2.impl;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -27,13 +31,21 @@ import java.util.NoSuchElementException;
 import java.util.TimerTask;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
 import javax.management.ObjectName;
 
 import org.apache.commons.pool2.BaseObjectPool;
@@ -175,7 +187,7 @@ import org.apache.commons.pool2.Poolable
  * @since Pool 1.0
  */
 public class GenericObjectPool<T> extends BaseObjectPool<T>
-        implements GenericObjectPoolMBean {
+        implements GenericObjectPoolMBean, NotificationEmitter {
 
     // --- constructors -----------------------------------------------
 
@@ -203,6 +215,7 @@ public class GenericObjectPool<T> extend
         if (config.isJmxEnabled()) {
             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
             String jmxNamePrefix = config.getJmxNamePrefix();
+            this.jmxNotificationSupport = new NotificationBroadcasterSupport();
             int i = 1;
             boolean registered = false;
             while (!registered) {
@@ -234,8 +247,15 @@ public class GenericObjectPool<T> extend
                     registered = true;
                 }
             }
+        } else {
+            this.jmxNotificationSupport = null;
         }
         this.oname = onameTemp;
+        
+        // Populate the swallowed exceptions queue
+        for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) {
+            swallowedExceptions.add(null);
+        }
     }
 
 
@@ -885,7 +905,9 @@ public class GenericObjectPool<T> extend
      * instance is validated before being returned to the idle instance pool. In
      * this case, if validation fails, the instance is destroyed.
      * </p>
-     *
+     * <p>
+     * Exceptions encountered destroying objects for any reason are swallowed.
+     * </p>
      * @param obj
      *            instance to return to the pool
      */
@@ -906,7 +928,7 @@ public class GenericObjectPool<T> extend
                 try {
                     destroy(p);
                 } catch (Exception e) {
-                    // TODO - Ignore?
+                    swallowException(e);
                 }
                 updateStatsReturn(activeTime);
                 return;
@@ -916,10 +938,11 @@ public class GenericObjectPool<T> extend
         try {
             factory.passivateObject(obj);
         } catch (Exception e1) {
+            swallowException(e1);
             try {
                 destroy(p);
             } catch (Exception e) {
-                // TODO - Ignore?
+                swallowException(e);
             }
             updateStatsReturn(activeTime);
             return;
@@ -935,7 +958,7 @@ public class GenericObjectPool<T> extend
             try {
                 destroy(p);
             } catch (Exception e) {
-                // TODO - Ignore?
+                swallowException(e);
             }
         } else {
             if (getLifo()) {
@@ -955,6 +978,28 @@ public class GenericObjectPool<T> extend
         }
     }
 
+    private void swallowException (Exception e) {
+        // Need the exception in string form to prevent the retention of
+        // references to classes in the stack trace that could trigger a memory
+        // leak in a container environment
+        Writer w = new StringWriter();
+        PrintWriter pw = new PrintWriter(w);
+        e.printStackTrace(pw);
+        String msg = w.toString();
+
+        if (oname != null) {
+            Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION,
+                    oname, swallowedExcpetionCount.incrementAndGet(), msg);
+            jmxNotificationSupport.sendNotification(n);
+        }
+        
+        // Add the exception the queue, removing the oldest
+        synchronized (swallowedExceptions) {
+            swallowedExceptions.addLast(msg);
+            swallowedExceptions.pollFirst();
+        }
+    }
+
     /**
      * {@inheritDoc}
      * <p>
@@ -1002,7 +1047,7 @@ public class GenericObjectPool<T> extend
             try {
                 destroy(p);
             } catch (Exception e) {
-                // TODO - Ignore?
+                swallowException(e);
             }
             p = idleObjects.poll();
         }
@@ -1317,7 +1362,7 @@ public class GenericObjectPool<T> extend
         }
     }
 
-    //--- JMX specific attributes ----------------------------------------------
+    //--- JMX support ----------------------------------------------------------
 
     private void initStats() {
         for (int i = 0; i < AVERAGE_TIMING_STATS_CACHE_SIZE; i++) {
@@ -1412,6 +1457,63 @@ public class GenericObjectPool<T> extend
         }
     }
 
+    @Override
+    public String[] getSwallowedExceptions() {
+        List<String> temp =
+                new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE);
+        synchronized (swallowedExceptions) {
+            temp.addAll(swallowedExceptions);
+        }
+        return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]);
+    }
+
+    @Override
+    public void addNotificationListener(NotificationListener listener,
+            NotificationFilter filter, Object handback)
+            throws IllegalArgumentException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.addNotificationListener(
+                listener, filter, handback);
+    }
+
+    @Override
+    public void removeNotificationListener(NotificationListener listener)
+            throws ListenerNotFoundException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.removeNotificationListener(listener);
+    }
+
+    @Override
+    public MBeanNotificationInfo[] getNotificationInfo() {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        return jmxNotificationSupport.getNotificationInfo();
+    }
+
+    @Override
+    public void removeNotificationListener(NotificationListener listener,
+            NotificationFilter filter, Object handback)
+            throws ListenerNotFoundException {
+
+        if (jmxNotificationSupport == null) {
+            throw new UnsupportedOperationException("JMX is not enabled");
+        }
+        jmxNotificationSupport.removeNotificationListener(
+                listener, filter, handback);
+    }
+
+    public ObjectName getJmxName() {
+        return oname;
+    }
+    
     // --- inner classes ----------------------------------------------
 
     /**
@@ -1670,7 +1772,14 @@ public class GenericObjectPool<T> extend
     private final Object maxBorrowWaitTimeMillisLock = new Object();
     private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock")
 
+    public static final String NOTIFICATION_SWALLOWED_EXCEPTION =
+            "SWALLOWED_EXCEPTION";
+    private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10;
+    private final Deque<String> swallowedExceptions = new LinkedList<String>();
+    private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0);
+    
     private final ObjectName oname;
+    private final NotificationBroadcasterSupport jmxNotificationSupport;
 
     private static final String ONAME_BASE =
         "org.apache.commoms.pool2:type=GenericObjectPool,name=";

Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java (original)
+++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPoolMBean.java Wed Apr 11 20:57:56 2012
@@ -44,4 +44,5 @@ public interface GenericObjectPoolMBean 
     long getMeanIdleTimeMillis();
     long getMeanBorrowWaitTimeMillis();
     long getMaxBorrowWaitTimeMillis();
+    String[] getSwallowedExceptions();
 }

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestBaseObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestBaseObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestBaseObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestBaseObjectPool.java Wed Apr 11 20:57:56 2012
@@ -139,6 +139,7 @@ public class TestBaseObjectPool extends 
         assertEquals(getNthObject(0),_pool.borrowObject());
         assertEquals(getNthObject(1),_pool.borrowObject());
         assertEquals(getNthObject(2),_pool.borrowObject());
+        _pool.close();
     }
 
     @Test
@@ -163,6 +164,8 @@ public class TestBaseObjectPool extends 
             assertEquals(0,_pool.getNumActive());
         } catch(UnsupportedOperationException e) {
             return; // skip this test if one of those calls is unsupported
+        } finally {
+            _pool.close();
         }
     }
 
@@ -202,6 +205,7 @@ public class TestBaseObjectPool extends 
         if (isFifo()) {
             assertEquals(getNthObject(2),obj0);
         }
+        _pool.close();
     }
 
     @Test
@@ -225,6 +229,7 @@ public class TestBaseObjectPool extends 
         _pool.returnObject(obj0);
         assertEquals(0,_pool.getNumActive());
         assertEquals(2,_pool.getNumIdle());
+        _pool.close();
     }
 
     @Test
@@ -249,6 +254,7 @@ public class TestBaseObjectPool extends 
         assertEquals(0,_pool.getNumIdle());
         Object obj2 = _pool.borrowObject();
         assertEquals(getNthObject(2),obj2);
+        _pool.close();
     }
 
     @Test
@@ -270,6 +276,7 @@ public class TestBaseObjectPool extends 
         _pool.invalidateObject(obj1);
         assertEquals(0,_pool.getNumActive());
         assertEquals(0,_pool.getNumIdle());
+        _pool.close();
     }
 
     @Test

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestKeyedObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestKeyedObjectPool.java Wed Apr 11 20:57:56 2012
@@ -174,6 +174,7 @@ public abstract class TestKeyedObjectPoo
         expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE));
         expectedMethods.add(new MethodCall("passivateObject", KEY, ONE));
         assertEquals(expectedMethods, factory.getMethodCalls());
+        pool.close();
     }
 
     @Test
@@ -261,6 +262,7 @@ public abstract class TestKeyedObjectPoo
         expectedMethods.add(new MethodCall("validateObject", KEY, ONE));
         TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
         assertEquals(expectedMethods, factory.getMethodCalls());
+        pool.close();
     }
 
     @Test
@@ -318,6 +320,7 @@ public abstract class TestKeyedObjectPoo
         } catch (PrivateException ex) {
             // Expected
         }
+        pool.close();
     }
 
     @Test
@@ -356,6 +359,7 @@ public abstract class TestKeyedObjectPoo
         Thread.sleep(250); // could be defered
         TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
         assertEquals(expectedMethods, factory.getMethodCalls());
+        pool.close();
     }
 
     @Test
@@ -378,6 +382,7 @@ public abstract class TestKeyedObjectPoo
         factory.setDestroyObjectFail(true);
         PoolUtils.prefill(pool, KEY, 5);
         pool.clear();
+        pool.close();
     }
 
     @Test
@@ -406,11 +411,15 @@ public abstract class TestKeyedObjectPoo
 
     @Test
     public void testToString() throws Exception {
-        final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
+        final FailingKeyedPoolableObjectFactory factory =
+                new FailingKeyedPoolableObjectFactory();
+        KeyedObjectPool<Object,Object> pool = makeEmptyPool(factory);
         try {
-            makeEmptyPool(factory).toString();
+            pool.toString();
         } catch(UnsupportedOperationException uoe) {
             return; // test not supported
+        } finally {
+            pool.close();
         }
     }
     
@@ -450,6 +459,7 @@ public abstract class TestKeyedObjectPoo
         if (isFifo()) {
             assertEquals(getNthObject(keya,2),obj0);
         }
+        _pool.close();
     }
 
     @Test
@@ -467,6 +477,7 @@ public abstract class TestKeyedObjectPoo
         assertEquals("4",getNthObject(keya,1),_pool.borrowObject(keya));
         assertEquals("5",getNthObject(keyb,2),_pool.borrowObject(keyb));
         assertEquals("6",getNthObject(keya,2),_pool.borrowObject(keya));
+        _pool.close();
     }
 
     @Test
@@ -494,6 +505,8 @@ public abstract class TestKeyedObjectPoo
 
         assertEquals(0,_pool.getNumActive("xyzzy12345"));
         assertEquals(0,_pool.getNumIdle("xyzzy12345"));
+        
+        _pool.close();
     }
 
     @Test
@@ -551,6 +564,8 @@ public abstract class TestKeyedObjectPoo
         assertEquals(2,_pool.getNumIdle(keya));
         assertEquals(0,_pool.getNumActive(keyb));
         assertEquals(2,_pool.getNumIdle(keyb));
+        
+        _pool.close();
     }
 
     @Test
@@ -576,6 +591,7 @@ public abstract class TestKeyedObjectPoo
         assertEquals(0,_pool.getNumIdle(keya));
         Object obj2 = _pool.borrowObject(keya);
         assertEquals(getNthObject(keya,2),obj2);
+        _pool.close();
     }
 
     @Test
@@ -598,6 +614,7 @@ public abstract class TestKeyedObjectPoo
         _pool.invalidateObject(keya,obj1);
         assertEquals(0,_pool.getNumActive(keya));
         assertEquals(0,_pool.getNumIdle(keya));
+        _pool.close();
     }
 
     @Test
@@ -631,6 +648,8 @@ public abstract class TestKeyedObjectPoo
             assertEquals(0,_pool.getNumActive(key));
         } catch(UnsupportedOperationException e) {
             return; // skip this test if one of those calls is unsupported
+        } finally {
+            _pool.close();
         }
     }
 

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/TestObjectPool.java Wed Apr 11 20:57:56 2012
@@ -163,6 +163,7 @@ public abstract class TestObjectPool {
         }
         expectedMethods.add(new MethodCall("passivateObject", ONE));
         assertEquals(expectedMethods, factory.getMethodCalls());
+        pool.close();
     }
 
     @Test
@@ -246,6 +247,7 @@ public abstract class TestObjectPool {
         removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here.
         // Second activate and validate are missing from expectedMethods
         assertTrue(factory.getMethodCalls().containsAll(expectedMethods));
+        pool.close();
     }
 
     @Test
@@ -306,6 +308,7 @@ public abstract class TestObjectPool {
         factory.setPassivateObjectFail(true);
         factory.setDestroyObjectFail(true);
         pool.returnObject(obj);
+        pool.close();
     }
 
     @Test
@@ -344,6 +347,7 @@ public abstract class TestObjectPool {
         Thread.sleep(250); // could be defered
         removeDestroyObjectCall(factory.getMethodCalls());
         assertEquals(expectedMethods, factory.getMethodCalls());
+        pool.close();
     }
 
     @Test
@@ -366,6 +370,7 @@ public abstract class TestObjectPool {
         factory.setDestroyObjectFail(true);
         PoolUtils.prefill(pool, 5);
         pool.clear();
+        pool.close();
     }
 
     @Test
@@ -397,7 +402,7 @@ public abstract class TestObjectPool {
     }
 
     @Test
-    public void testToString() {
+    public void testToString() throws Exception {
         ObjectPool<Object> pool;
         try {
             pool = makeEmptyPool(new MethodCallPoolableObjectFactory());
@@ -405,6 +410,7 @@ public abstract class TestObjectPool {
             return; // test not supported
         }
         pool.toString();
+        pool.close();
     }
 
     static void removeDestroyObjectCall(List<MethodCall> calls) {

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java Wed Apr 11 20:57:56 2012
@@ -26,12 +26,20 @@ import static junit.framework.Assert.fai
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Random;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
 import org.apache.commons.pool2.KeyedObjectPool;
 import org.apache.commons.pool2.KeyedPoolableObjectFactory;
 import org.apache.commons.pool2.TestKeyedObjectPool;
@@ -40,6 +48,7 @@ import org.apache.commons.pool2.VisitTra
 import org.apache.commons.pool2.Waiter;
 import org.apache.commons.pool2.WaiterFactory;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -102,14 +111,15 @@ public class TestGenericKeyedObjectPool 
     }
 
     private GenericKeyedObjectPool<String,String> pool = null;
+    private SimpleFactory<String> factory = null;
     private final Integer zero = new Integer(0);
     private final Integer one = new Integer(1);
     private final Integer two = new Integer(2);
 
     @Before
     public void setUp() throws Exception {
-        pool = new GenericKeyedObjectPool<String,String>(
-                new SimpleFactory<String>());
+        factory = new SimpleFactory<String>();
+        pool = new GenericKeyedObjectPool<String,String>(factory);
     }
 
     @Override
@@ -119,6 +129,19 @@ public class TestGenericKeyedObjectPool 
         pool.clear();
         pool.close();
         pool = null;
+        factory = null;
+        
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        Set<ObjectName> result = mbs.queryNames(new ObjectName(
+                "org.apache.commoms.pool2:type=GenericKeyedObjectPool,*"),
+                null);
+        // There should be no registered pools at this point
+        int registeredPoolCount = result.size();
+        for (ObjectName name : result) {
+            // Clean these up ready for the next test
+            mbs.unregisterMBean(name);
+        }
+        Assert.assertEquals(0, registeredPoolCount);
     }
 
     @Test(timeout=60000)
@@ -351,9 +374,6 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testSettersAndGetters() throws Exception {
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(
-                    new SimpleFactory<String>());
         {
             pool.setMaxTotalPerKey(123);
             assertEquals(123,pool.getMaxTotalPerKey());
@@ -541,12 +561,10 @@ public class TestGenericKeyedObjectPool 
     @Test(timeout=60000)
     public void testMaxTotalInvariant() throws Exception {
         int maxTotal = 15;
-        SimpleFactory<String> factory = new SimpleFactory<String>();
         factory.setEvenValid(false);     // Every other validation fails
         factory.setDestroyLatency(100);  // Destroy takes 100 ms
         factory.setMaxTotalPerKey(maxTotal);  // (makes - destroys) bound
         factory.setValidationEnabled(true);
-        pool = new GenericKeyedObjectPool<String,String>(factory);
         pool.setMaxTotal(maxTotal);
         pool.setMaxIdlePerKey(-1);
         pool.setTestOnReturn(true);
@@ -827,6 +845,7 @@ public class TestGenericKeyedObjectPool 
         } else {
             assertEquals("15", obj);
         }
+        pool.close();
     }
 
 
@@ -919,6 +938,7 @@ public class TestGenericKeyedObjectPool 
                         2, tracker.getValidateCount());
             }
         }
+        pool.close();
 
         // Randomly generate some pools with random numTests
         // and make sure evictor cycles through elements appropriately
@@ -1004,12 +1024,13 @@ public class TestGenericKeyedObjectPool 
                                 "totalInstances", totalInstances, zeroLength, oneLength, twoLength));
                     }
                 }
+                pool.close();
             }
         }
     }
 
     @Test(timeout=60000)
-    public void testConstructors() {
+    public void testConstructors() throws Exception {
 
         // Make constructor arguments all different from defaults
         int maxTotalPerKey = 1;
@@ -1048,6 +1069,7 @@ public class TestGenericKeyedObjectPool 
         assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED,
                 pool.getBlockWhenExhausted());
         assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_LIFO, pool.getLifo());
+        pool.close();
 
         GenericKeyedObjectPoolConfig config =
                 new GenericKeyedObjectPoolConfig();
@@ -1080,6 +1102,7 @@ public class TestGenericKeyedObjectPool 
                 pool.getTimeBetweenEvictionRunsMillis());
         assertEquals(blockWhenExhausted,pool.getBlockWhenExhausted());
         assertEquals(lifo, pool.getLifo());
+        pool.close();
     }
 
     @Test(timeout=60000)
@@ -1096,11 +1119,8 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringBorrow() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>();
         factory.setThrowExceptionOnDestroy(true);
         factory.setValidationEnabled(true);
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         pool.setTestOnBorrow(true);
         pool.borrowObject("one");
         factory.setValid(false); // Make validation fail on next borrow attempt
@@ -1118,11 +1138,8 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringReturn() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>();
         factory.setThrowExceptionOnDestroy(true);
         factory.setValidationEnabled(true);
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         pool.setTestOnReturn(true);
         String obj1 = pool.borrowObject("one");
         pool.borrowObject("one");
@@ -1136,9 +1153,6 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testExceptionOnActivateDuringBorrow() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>();
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         String obj1 = pool.borrowObject("one");
         String obj2 = pool.borrowObject("one");
         pool.returnObject("one", obj1);
@@ -1171,9 +1185,6 @@ public class TestGenericKeyedObjectPool 
 
     @Test(timeout=60000)
     public void testBlockedKeyDoesNotBlockPool() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>();
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         pool.setBlockWhenExhausted(true);
         pool.setMaxWait(5000);
         pool.setMaxTotalPerKey(1);
@@ -1217,9 +1228,6 @@ public class TestGenericKeyedObjectPool 
         final long holdTime = 4 * maxWait; // how long to hold connection
         final int keyCount = 4; // number of different keys
         final int threadsPerKey = 5; // number of threads to grab the key initially
-        SimpleFactory<String> factory = new SimpleFactory<String>();
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         pool.setBlockWhenExhausted(true);
         pool.setMaxWait(maxWait);
         pool.setMaxTotalPerKey(threadsPerKey);
@@ -1268,7 +1276,7 @@ public class TestGenericKeyedObjectPool 
      * Test case for POOL-180.
      */
     @Test(timeout=200000)
-    public void testMaxActivePerKeyExceeded() {
+    public void testMaxActivePerKeyExceeded() throws Exception {
         WaiterFactory<String> factory = new WaiterFactory<String>(0, 20, 0, 0, 0, 0, 8, 5, 0);
         // TODO Fix this. Can't use local pool since runTestThreads uses the
         //      protected pool field
@@ -1280,6 +1288,7 @@ public class TestGenericKeyedObjectPool 
         pool.setMaxIdlePerKey(5);
         pool.setMaxWait(-1);
         runTestThreads(20, 300, 250, pool);
+        pool.close();
     }
 
     /**
@@ -1313,6 +1322,7 @@ public class TestGenericKeyedObjectPool 
         Waiter waiter = pool.borrowObject("1");
         Thread.sleep(200); // Wait for execution to happen
         pool.returnObject("1", waiter);  // Will throw IllegalStateException if dead
+        pool.close();
     }
 
 
@@ -1320,11 +1330,8 @@ public class TestGenericKeyedObjectPool 
      * Verifies that threads that get parked waiting for keys not in use
      * when the pool is at maxTotal eventually get served.
      */
-    @Test
+    @Test(timeout=60000)
     public void testLivenessPerKey() throws Exception {
-        SimpleFactory<String> factory = new SimpleFactory<String>();
-        GenericKeyedObjectPool<String,String> pool =
-            new GenericKeyedObjectPool<String,String>(factory);
         pool.setMaxIdlePerKey(3);
         pool.setMaxTotal(3);
         pool.setMaxTotalPerKey(3);
@@ -1347,6 +1354,7 @@ public class TestGenericKeyedObjectPool 
      * POOL-192
      * Verify that clear(key) does not leak capacity.
      */
+    @Test(timeout=60000)
     public void testClear() throws Exception {
         SimpleFactory<String> factory = new SimpleFactory<String>();
         GenericKeyedObjectPool<String,String> pool =
@@ -1677,6 +1685,49 @@ public class TestGenericKeyedObjectPool 
         return sb.toString();
     }
 
+    /**
+     * Ensure the pool is registered.
+     */
+    @Test(timeout=60000)
+    public void testJmxRegistration() {
+        ObjectName oname = pool.getJmxName();
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        Set<ObjectName> result = mbs.queryNames(oname, null);
+        Assert.assertEquals(1, result.size());
+    }
+    
+    @Test(timeout=60000)
+    public void testJmxNotification() throws Exception {
+        factory.setThrowExceptionOnPassivate(true);
+        ObjectName oname = pool.getJmxName();
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        JmxNotificationListener listener = new JmxNotificationListener();
+        mbs.addNotificationListener(oname, listener, null, null);
+        
+        String obj = pool.borrowObject("one");
+        pool.returnObject("one", obj);
+        
+        List<String> messages = listener.getMessages();
+        Assert.assertEquals(1, messages.size());
+        Assert.assertNotNull(messages.get(0));
+        Assert.assertTrue(messages.get(0).length() > 0);
+    }
+    
+    private static class JmxNotificationListener
+            implements NotificationListener {
+
+        private List<String> messages = new ArrayList<String>();
+        
+        public List<String> getMessages() {
+            return messages;
+        }
+        
+        @Override
+        public void handleNotification(Notification notification,
+                Object handback) {
+            messages.add(notification.getMessage());
+        }
+    }
 }
 
 

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java Wed Apr 11 20:57:56 2012
@@ -23,10 +23,19 @@ import static junit.framework.Assert.ass
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Random;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
 import org.apache.commons.pool2.BasePoolableObjectFactory;
 import org.apache.commons.pool2.ObjectPool;
 import org.apache.commons.pool2.PoolUtils;
@@ -35,6 +44,7 @@ import org.apache.commons.pool2.TestBase
 import org.apache.commons.pool2.VisitTracker;
 import org.apache.commons.pool2.VisitTrackerFactory;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -69,7 +79,8 @@ public class TestGenericObjectPool exten
 
     @Before
     public void setUp() throws Exception {
-        pool = new GenericObjectPool<Object>(new SimpleFactory());
+        factory = new SimpleFactory();
+        pool = new GenericObjectPool<Object>(factory);
     }
 
     @After
@@ -77,6 +88,18 @@ public class TestGenericObjectPool exten
         pool.clear();
         pool.close();
         pool = null;
+        factory = null;
+        
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        Set<ObjectName> result = mbs.queryNames(new ObjectName(
+                "org.apache.commoms.pool2:type=GenericObjectPool,*"), null);
+        // There should be no registered pools at this point
+        int registeredPoolCount = result.size();
+        for (ObjectName name : result) {
+            // Clean these up ready for the next test
+            mbs.unregisterMBean(name);
+        }
+        Assert.assertEquals(0, registeredPoolCount);
     }
 
     @Test(timeout=60000)
@@ -161,16 +184,14 @@ public class TestGenericObjectPool exten
         pool.close();
     }
 
-    @Test(timeout=60000)
     /**
      * Tests addObject contention between ensureMinIdle triggered by
      * the Evictor with minIdle > 0 and borrowObject.
      */
+    @Test(timeout=60000)
     public void testEvictAddObjects() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
         factory.setMakeLatency(300);
         factory.setMaxTotal(2);
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setMaxTotal(2);
         pool.setMinIdle(1);
         pool.borrowObject(); // numActive = 1, numIdle = 0
@@ -183,7 +204,6 @@ public class TestGenericObjectPool exten
         borrowerThread.start();  // Off to the races
         borrowerThread.join();
         assertTrue(!borrower.failed());
-        pool.close();
     }
 
     @Test(timeout=60000)
@@ -196,11 +216,8 @@ public class TestGenericObjectPool exten
         checkEvict(false);
     }
 
-    public void checkEvict(boolean lifo) throws Exception {
+    private void checkEvict(boolean lifo) throws Exception {
         // yea this is hairy but it tests all the code paths in GOP.evict()
-        final SimpleFactory factory = new SimpleFactory();
-        final GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(factory);
         pool.setSoftMinEvictableIdleTimeMillis(10);
         pool.setMinIdle(2);
         pool.setTestWhileIdle(true);
@@ -225,20 +242,26 @@ public class TestGenericObjectPool exten
 
     /**
      * Test to make sure evictor visits least recently used objects first,
-     * regardless of FIFO/LIFO
+     * regardless of FIFO/LIFO.
      *
      * JIRA: POOL-86
      */
     @Test(timeout=60000)
     public void testEvictionOrder() throws Exception {
         checkEvictionOrder(false);
+        tearDown();
+        setUp();
         checkEvictionOrder(true);
     }
 
     private void checkEvictionOrder(boolean lifo) throws Exception {
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(factory);
+        checkEvictionOrderPart1(lifo);
+        tearDown();
+        setUp();
+        checkEvictionOrderPart2(lifo);
+    }
+    
+    private void checkEvictionOrderPart1(boolean lifo) throws Exception {
         pool.setNumTestsPerEvictionRun(2);
         pool.setMinEvictableIdleTimeMillis(100);
         pool.setLifo(lifo);
@@ -253,10 +276,10 @@ public class TestGenericObjectPool exten
         assertTrue("second oldest not evicted", !obj.equals("1"));
         // 2 should be next out for FIFO, 4 for LIFO
         assertEquals("Wrong instance returned", lifo ? "4" : "2" , obj);
+    }
 
+    private void checkEvictionOrderPart2(boolean lifo) throws Exception {
         // Two eviction runs in sequence
-        factory = new SimpleFactory();
-        pool = new GenericObjectPool<Object>(factory);
         pool.setNumTestsPerEvictionRun(2);
         pool.setMinEvictableIdleTimeMillis(100);
         pool.setLifo(lifo);
@@ -266,7 +289,7 @@ public class TestGenericObjectPool exten
         }
         pool.evict(); // Should evict "0" and "1"
         pool.evict(); // Should evict "2" and "3"
-        obj = pool.borrowObject();
+        Object obj = pool.borrowObject();
         assertEquals("Wrong instance remaining in pool", "4", obj);
     }
 
@@ -274,6 +297,7 @@ public class TestGenericObjectPool exten
      * Verifies that the evictor visits objects in expected order
      * and frequency.
      */
+    @Test
     public void testEvictorVisiting() throws Exception {
         checkEvictorVisiting(true);
         checkEvictorVisiting(false);
@@ -312,6 +336,7 @@ public class TestGenericObjectPool exten
                         1, tracker.getValidateCount());
             }
         }
+        pool.close();
 
         factory = new VisitTrackerFactory<Object>();
         pool = new GenericObjectPool<VisitTracker<Object>>(factory);
@@ -350,16 +375,17 @@ public class TestGenericObjectPool exten
                         2, tracker.getValidateCount());
             }
         }
+        pool.close();
+        
         // Randomly generate a pools with random numTests
         // and make sure evictor cycles through elements appropriately
         int[] smallPrimes = {2, 3, 5, 7};
         Random random = new Random();
         random.setSeed(System.currentTimeMillis());
         for (int i = 0; i < 4; i++) {
-            pool.setNumTestsPerEvictionRun(smallPrimes[i]);
             for (int j = 0; j < 5; j++) {
                 pool = new GenericObjectPool<VisitTracker<Object>>(factory);
-                pool.setNumTestsPerEvictionRun(3);
+                pool.setNumTestsPerEvictionRun(smallPrimes[i]);
                 pool.setMinEvictableIdleTimeMillis(-1);
                 pool.setTestWhileIdle(true);
                 pool.setLifo(lifo);
@@ -393,26 +419,22 @@ public class TestGenericObjectPool exten
                     assertTrue(visitCount >= cycleCount &&
                             visitCount <= cycleCount + 1);
                 }
+                pool.close();
             }
         }
     }
 
     @Test(timeout=60000)
     public void testExceptionOnPassivateDuringReturn() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         Object obj = pool.borrowObject();
         factory.setThrowExceptionOnPassivate(true);
         pool.returnObject(obj);
         assertEquals(0,pool.getNumIdle());
-        pool.close();
     }
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringBorrow() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
         factory.setThrowExceptionOnDestroy(true);
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setTestOnBorrow(true);
         pool.borrowObject();
         factory.setValid(false); // Make validation fail on next borrow attempt
@@ -428,9 +450,7 @@ public class TestGenericObjectPool exten
 
     @Test(timeout=60000)
     public void testExceptionOnDestroyDuringReturn() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
         factory.setThrowExceptionOnDestroy(true);
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setTestOnReturn(true);
         Object obj1 = pool.borrowObject();
         pool.borrowObject();
@@ -442,8 +462,6 @@ public class TestGenericObjectPool exten
 
     @Test(timeout=60000)
     public void testExceptionOnActivateDuringBorrow() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         Object obj1 = pool.borrowObject();
         Object obj2 = pool.borrowObject();
         pool.returnObject(obj1);
@@ -570,9 +588,7 @@ public class TestGenericObjectPool exten
         int delay = 25;
         int maxTotal = 10;
 
-        SimpleFactory factory = new SimpleFactory();
         factory.setMaxTotal(maxTotal);
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setMaxTotal(maxTotal);
         pool.setBlockWhenExhausted(true);
         pool.setTimeBetweenEvictionRunsMillis(-1);
@@ -643,8 +659,6 @@ public class TestGenericObjectPool exten
 
     @Test(timeout=60000)
     public void testSettersAndGetters() throws Exception {
-        GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(new SimpleFactory());
         {
             pool.setMaxTotal(123);
             assertEquals(123,pool.getMaxTotal());
@@ -701,17 +715,12 @@ public class TestGenericObjectPool exten
 
     @Test(timeout=60000)
     public void testDefaultConfiguration() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(factory);
         assertConfiguration(new GenericObjectPoolConfig(),pool);
     }
 
     @Test(timeout=60000)
     public void testSetConfig() throws Exception {
         GenericObjectPoolConfig expected = new GenericObjectPoolConfig();
-        GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(new SimpleFactory());
         assertConfiguration(expected,pool);
         expected.setMaxTotal(2);
         expected.setMaxIdle(3);
@@ -729,8 +738,6 @@ public class TestGenericObjectPool exten
 
     @Test(timeout=60000)
     public void testDebugInfo() throws Exception {
-        GenericObjectPool<Object> pool =
-            new GenericObjectPool<Object>(new SimpleFactory());
         pool.setMaxIdle(3);
         assertNotNull(pool.debugInfo());
         Object obj = pool.borrowObject();
@@ -945,6 +952,7 @@ public class TestGenericObjectPool exten
         Thread.sleep(2000L);
         pool.evict();
         assertEquals("Idle count different than expected.", 0, pool.getNumIdle());
+        pool.close();
     }
 
     @Test(timeout=60000)
@@ -1009,6 +1017,7 @@ public class TestGenericObjectPool exten
         // Should have an empty pool
         assertEquals("Idle count different than expected.", 0, pool.getNumIdle());
         assertEquals("Total count different than expected.", 0, pool.getNumActive());
+        pool.close();
     }
 
     @Test(timeout=60000)
@@ -1097,7 +1106,7 @@ public class TestGenericObjectPool exten
      * <iterations> borrow-return cycles with random delay times <= delay
      * in between.
      */
-    public void runTestThreads(int numThreads, int iterations, int delay) {
+    private void runTestThreads(int numThreads, int iterations, int delay) {
         TestThread[] threads = new TestThread[numThreads];
         for(int i=0;i<numThreads;i++) {
             threads[i] = new TestThread(pool,iterations,delay);
@@ -1134,12 +1143,10 @@ public class TestGenericObjectPool exten
     @Test(timeout=60000)
     public void testMaxTotalInvariant() throws Exception {
         int maxTotal = 15;
-        SimpleFactory factory = new SimpleFactory();
         factory.setEvenValid(false);     // Every other validation fails
         factory.setDestroyLatency(100);  // Destroy takes 100 ms
         factory.setMaxTotal(maxTotal); // (makes - destroys) bound
         factory.setValidationEnabled(true);
-        pool = new GenericObjectPool<Object>(factory);
         pool.setMaxTotal(maxTotal);
         pool.setMaxIdle(-1);
         pool.setTestOnReturn(true);
@@ -1365,6 +1372,8 @@ public class TestGenericObjectPool exten
     }
 
     protected GenericObjectPool<Object> pool = null;
+    
+    private SimpleFactory factory = null;
 
     private void assertConfiguration(GenericObjectPoolConfig expected, GenericObjectPool<?> actual) throws Exception {
         assertEquals("testOnBorrow",expected.getTestOnBorrow(),actual.getTestOnBorrow());
@@ -1614,9 +1623,7 @@ public class TestGenericObjectPool exten
     public void testBrokenFactoryShouldNotBlockPool() {
         int maxTotal = 1;
 
-        SimpleFactory factory = new SimpleFactory();
         factory.setMaxTotal(maxTotal);
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setMaxTotal(maxTotal);
         pool.setBlockWhenExhausted(true);
         pool.setTestOnBorrow(true);
@@ -1651,7 +1658,6 @@ public class TestGenericObjectPool exten
         } catch (Exception e) {
             fail();
         }
-
     }
 
     /*
@@ -1712,8 +1718,6 @@ public class TestGenericObjectPool exten
         final long maxWait = 500; // wait for connection
         final long holdTime = 2 * maxWait; // how long to hold connection
         final int threads = 10; // number of threads to grab the object initially
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setBlockWhenExhausted(true);
         pool.setMaxWait(maxWait);
         pool.setMaxTotal(threads);
@@ -1765,8 +1769,6 @@ public class TestGenericObjectPool exten
      */
     @Test(timeout=60000)
     public void testMakeConcurrentWithReturn() throws Exception {
-        SimpleFactory factory = new SimpleFactory();
-        GenericObjectPool<Object> pool = new GenericObjectPool<Object>(factory);
         pool.setTestOnBorrow(true);
         factory.setValid(true);
         // Borrow and return an instance, with a short wait
@@ -1781,4 +1783,48 @@ public class TestGenericObjectPool exten
         pool.returnObject(instance);
         assertEquals(factory.getMakeCounter(), pool.getNumIdle());
     }
+    
+    /**
+     * Ensure the pool is registered.
+     */
+    @Test(timeout=60000)
+    public void testJmxRegistration() {
+        ObjectName oname = pool.getJmxName();
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        Set<ObjectName> result = mbs.queryNames(oname, null);
+        Assert.assertEquals(1, result.size());
+    }
+    
+    @Test(timeout=60000)
+    public void testJmxNotification() throws Exception {
+        factory.setThrowExceptionOnPassivate(true);
+        ObjectName oname = pool.getJmxName();
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        JmxNotificationListener listener = new JmxNotificationListener();
+        mbs.addNotificationListener(oname, listener, null, null);
+        
+        Object obj = pool.borrowObject();
+        pool.returnObject(obj);
+        
+        List<String> messages = listener.getMessages();
+        Assert.assertEquals(1, messages.size());
+        Assert.assertNotNull(messages.get(0));
+        Assert.assertTrue(messages.get(0).length() > 0);
+    }
+    
+    private static class JmxNotificationListener
+            implements NotificationListener {
+
+        private List<String> messages = new ArrayList<String>();
+        
+        public List<String> getMessages() {
+            return messages;
+        }
+        
+        @Override
+        public void handleNotification(Notification notification,
+                Object handback) {
+            messages.add(notification.getMessage());
+        }
+    }
 }

Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java
URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java?rev=1325009&r1=1325008&r2=1325009&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java (original)
+++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java Wed Apr 11 20:57:56 2012
@@ -65,6 +65,8 @@ public class TestGenericObjectPoolClassL
 			assertEquals("Wrong number of  idle objects in pool2", 1,
 			        pool2.getNumIdle());
 
+			pool1.close();
+			pool2.close();
 		} finally {
 			Thread.currentThread().setContextClassLoader(savedClassloader);
 		}