Author: psteitz
Date: Sun Jan 18 18:59:59 2015
New Revision: 1652830

URL: http://svn.apache.org/r1652830
Log:
Made Datasources implement AutoCloseable. JIRA: DBCP-423.

Modified:
    commons/proper/dbcp/trunk/src/changes/changes.xml
    
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
    
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
    
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
    
commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestCPDSConnectionFactory.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestInstanceKeyDataSource.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestKeyedCPDSConnectionFactory.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestSharedPoolDataSource.java
    
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java

Modified: commons/proper/dbcp/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/changes/changes.xml?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/changes/changes.xml (original)
+++ commons/proper/dbcp/trunk/src/changes/changes.xml Sun Jan 18 18:59:59 2015
@@ -60,7 +60,12 @@ The <action> type attribute can be add,u
      -->
 
   <body>
-    <release version="2.1" date="TBD" description="This is minor release, 
including bug fixes and enhancements.">
+    <release version="2.1" date="TBD" description=
+ "This is minor release, including bug fixes and enhancements. Note that
+  one of the enhancements (DBCP-423) is to implement AutoCloseable in
+  BasicDataSource, PoolingDataSource and the InstanceKeyDataSource
+  implementations.
+      ">
       <action issue="DBCP-420" dev="sebb" type="fix">
         InstanceKeyDataSource discards native SQLException when given password 
does not match
         password used to create the connection.
@@ -86,6 +91,9 @@ The <action> type attribute can be add,u
         Made expired connection logging configurable in BasicDataSource.  
Setting
         logExpiredConnections to false suppresses expired connection log 
messages.
       </action>
+      <action issue="DBCP-423" dev="psteitz" type="update">
+        Made Datasources implement AutoCloseable.
+      </action>
     </release>
     <release version="2.0.1" date="24 May 2014" description="This is a bug fix 
release.">
       <action dev="markt" type="fix">

Modified: 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -66,7 +66,7 @@ import org.apache.commons.pool2.impl.Gen
  * @version $Id$
  * @since 2.0
  */
-public class BasicDataSource implements DataSource, BasicDataSourceMXBean, 
MBeanRegistration {
+public class BasicDataSource implements DataSource, BasicDataSourceMXBean, 
MBeanRegistration, AutoCloseable {
 
     private static final Log log = LogFactory.getLog(BasicDataSource.class);
 
@@ -1861,7 +1861,7 @@ public class BasicDataSource implements
         } catch(RuntimeException e) {
             throw e;
         } catch(Exception e) {
-            throw new SQLException("Cannot close connection pool", e);
+            throw new SQLException(Utils.getMessage("pool.close.fail"), e);
         }
     }
 

Modified: 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -43,7 +43,7 @@ import org.apache.commons.pool2.impl.Gen
  * @version $Id$
  * @since 2.0
  */
-public class PoolingDataSource<C extends Connection> implements DataSource {
+public class PoolingDataSource<C extends Connection> implements DataSource, 
AutoCloseable {
 
     private static final Log log = LogFactory.getLog(PoolingDataSource.class);
     
@@ -70,6 +70,21 @@ public class PoolingDataSource<C extends
         }
     }
 
+    /**
+     * Close and free all {@link Connections}s from the pool.
+     * @since 2.1
+     */
+    @Override
+    public void close() throws Exception {
+        try {
+            _pool.close();
+        } catch(RuntimeException rte) {
+            throw new RuntimeException(Utils.getMessage("pool.close.fail"), 
rte);
+        } catch(Exception e) {
+            throw new SQLException(Utils.getMessage("pool.close.fail"), e);
+        }
+    }
+
     /**
      * Returns the value of the accessToUnderlyingConnectionAllowed property.
      *

Modified: 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -85,7 +85,7 @@ import org.apache.commons.pool2.impl.Gen
  * @since 2.0
  */
 public abstract class InstanceKeyDataSource
-        implements DataSource, Referenceable, Serializable {
+        implements DataSource, Referenceable, Serializable, AutoCloseable {
 
     private static final long serialVersionUID = -6819270431752240878L;
 

Modified: 
commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties
 (original)
+++ 
commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2/LocalStrings.properties
 Sun Jan 18 18:59:59 2015
@@ -21,3 +21,4 @@ swallowedExceptionLogger.onSwallowedExce
 
 poolingDataSource.factoryConfig=PoolableConnectionFactory not linked to pool. 
Calling setPool() to fix the configuration.
 
+pool.close.fail=Cannot close connection pool.

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -428,6 +428,61 @@ public class TestBasicDataSource extends
 
         assertEquals(0, ds.getNumActive());
     }
+    
+    /**
+     * Verifies correct handling of exceptions generated by the underlying 
pool as it closes
+     * connections in response to BDS#close. Exceptions have to be either 
swallowed by the
+     * underlying pool and logged, or propagated and wrapped.
+     */
+    @Test
+    public void testPoolCloseCheckedException() throws Exception {
+        ds.setAccessToUnderlyingConnectionAllowed(true);  // Allow dirty tricks
+        
+        // Get an idle connection into the pool
+        Connection conn = ds.getConnection();
+        TesterConnection tc = (TesterConnection) ((DelegatingConnection<?>) 
conn).getInnermostDelegate();
+        conn.close();
+        
+        // After returning the connection to the pool, bork it.
+        // Don't try this at home - bad violation of pool contract!
+        tc.setFailure(new SQLException("bang"));
+        
+        // Now close Datasource, which will cause tc to be closed, triggering 
SQLE
+        // Pool 2.x swallows and logs exceptions on pool close.  Below 
verifies that
+        // Either exceptions get logged or wrapped appropriately.
+        try {
+            StackMessageLog.lock();
+            StackMessageLog.clear();
+            ds.close();  
+            // Exception must have been swallowed by the pool - verify it is 
logged
+            assertTrue(StackMessageLog.popMessage().indexOf("bang") > 0);
+        } catch (SQLException ex) {
+            assertTrue(ex.getMessage().indexOf("Cannot close") > 0);
+            assertTrue(ex.getCause().getMessage().indexOf("bang") > 0);
+        } finally {
+            StackMessageLog.unLock();
+        }     
+    }
+    
+    @Test
+    public void testPoolCloseRTE() throws Exception {
+        // RTE version of testPoolCloseCheckedException - see comments there.
+        ds.setAccessToUnderlyingConnectionAllowed(true);
+        Connection conn = ds.getConnection();
+        TesterConnection tc = (TesterConnection) ((DelegatingConnection<?>) 
conn).getInnermostDelegate();
+        conn.close();
+        tc.setFailure(new IllegalStateException("boom"));
+        try {
+            StackMessageLog.lock();
+            StackMessageLog.clear();
+            ds.close();  
+            assertTrue(StackMessageLog.popMessage().indexOf("boom") > 0);
+        } catch (IllegalStateException ex) {
+            assertTrue(ex.getMessage().indexOf("boom") > 0); // RTE is not 
wrapped by BDS#close
+        } finally {
+            StackMessageLog.unLock();
+        }
+    }
 
     /**
      * Bugzilla Bug 29054:
@@ -613,6 +668,7 @@ public class TestBasicDataSource extends
     public void testMaxConnLifetimeExceededMutedLog() throws Exception {
         try {
             StackMessageLog.lock();
+            StackMessageLog.clear();
             ds.setMaxConnLifetimeMillis(100);
             ds.setLogExpiredConnections(false);
             Connection conn = ds.getConnection();

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java
 Sun Jan 18 18:59:59 2015
@@ -141,7 +141,7 @@ public class TestPStmtPooling {
                 new GenericObjectPool<>(pcf, config);
         pcf.setPool(connPool);
 
-        DataSource ds = new PoolingDataSource<>(connPool);
+        PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
 
         try (Connection conn = ds.getConnection()) {
             Statement stmt1 = conn.prepareStatement("select 1 from dual");
@@ -165,6 +165,7 @@ public class TestPStmtPooling {
             assertNotSame(ustmt1, ustmt3);
             assertNotSame(ustmt3, ucstmt1);
         }
+        ds.close();
     }
 
     @Test
@@ -182,7 +183,7 @@ public class TestPStmtPooling {
         ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
         pcf.setPool(connPool);
 
-        DataSource ds = new PoolingDataSource<>(connPool);
+        PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
         ((PoolingDataSource<?>) 
ds).setAccessToUnderlyingConnectionAllowed(true);
 
         Connection conn = ds.getConnection();
@@ -197,6 +198,7 @@ public class TestPStmtPooling {
         } catch (SQLException ex) {
             assertTrue(ex.getMessage().endsWith("invalid PoolingConnection."));
         }
+        ds.close();
     }
 
     @Test
@@ -213,7 +215,7 @@ public class TestPStmtPooling {
         ObjectPool<PoolableConnection> connPool = new GenericObjectPool<>(pcf);
         pcf.setPool(connPool);
 
-        DataSource ds = new PoolingDataSource<>(connPool);
+        PoolingDataSource<?> ds = new PoolingDataSource<>(connPool);
 
         Connection conn = ds.getConnection();
         PreparedStatement ps = conn.prepareStatement("select 1 from dual");
@@ -223,5 +225,6 @@ public class TestPStmtPooling {
         ps.close();
         conn.close();
         Assert.assertFalse(inner.isClosed());
+        ds.close();
     }
 }

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestPoolingDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -17,7 +17,9 @@
 
 package org.apache.commons.dbcp2;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.sql.Connection;
@@ -67,7 +69,7 @@ public class TestPoolingDataSource exten
 
     @After
     public void tearDown() throws Exception {
-        pool.close();
+        ds.close();
         super.tearDown();
     }
 
@@ -169,4 +171,34 @@ public class TestPoolingDataSource exten
         assertTrue(f.getPool().equals(p));
         ds.getConnection();
     }
+    
+    @Test
+    public void testClose() throws Exception {
+
+        Properties props = new Properties();
+        props.setProperty("user", "username");
+        props.setProperty("password", "password");
+        PoolableConnectionFactory f =
+            new PoolableConnectionFactory(
+                    new DriverConnectionFactory(new TesterDriver(),
+                            "jdbc:apache:commons:testdriver", props),
+                    null);
+        f.setValidationQuery("SELECT DUMMY FROM DUAL");
+        f.setDefaultReadOnly(Boolean.TRUE);
+        f.setDefaultAutoCommit(Boolean.TRUE);
+        GenericObjectPool<PoolableConnection> p = new GenericObjectPool<>(f);
+        p.setMaxTotal(getMaxTotal());
+        p.setMaxWaitMillis(getMaxWaitMillis());
+
+        try ( PoolingDataSource<PoolableConnection> dataSource =
+                new PoolingDataSource<PoolableConnection>(p) ) {
+            Connection connection = dataSource.getConnection();
+            assertNotNull(connection);
+            connection.close();
+        }
+        
+        assertTrue(p.isClosed());
+        assertEquals(0, p.getNumIdle());
+        assertEquals(0, p.getNumActive());
+    }
 }

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestCPDSConnectionFactory.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestCPDSConnectionFactory.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestCPDSConnectionFactory.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestCPDSConnectionFactory.java
 Sun Jan 18 18:59:59 2015
@@ -72,6 +72,7 @@ public class TestCPDSConnectionFactory {
        assertEquals(2, ds.getNumIdle("username"));
        conn3.close(); // Return to pool will trigger destroy -> close sequence
        assertEquals(2, ds.getNumIdle("username"));
+       ds.close();
     }
 
     /**

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestInstanceKeyDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestInstanceKeyDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestInstanceKeyDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestInstanceKeyDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -54,7 +54,8 @@ public class TestInstanceKeyDataSource {
         } catch (SQLException ex) {
            //Expected
         }
-        assertEquals(numConnections,tds.getNumActive());     
+        assertEquals(numConnections,tds.getNumActive());  
+        tds.close();
     }
     
     private static class ThrowOnSetupDefaultsDataSource

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestKeyedCPDSConnectionFactory.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestKeyedCPDSConnectionFactory.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestKeyedCPDSConnectionFactory.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestKeyedCPDSConnectionFactory.java
 Sun Jan 18 18:59:59 2015
@@ -73,6 +73,7 @@ public class TestKeyedCPDSConnectionFact
        assertEquals(2, ds.getNumIdle());
        conn3.close(); // Return to pool will trigger destroy -> close sequence
        assertEquals(2, ds.getNumIdle());
+       ds.close();
     }
 
     /**

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestSharedPoolDataSource.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestSharedPoolDataSource.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestSharedPoolDataSource.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/datasources/TestSharedPoolDataSource.java
 Sun Jan 18 18:59:59 2015
@@ -538,6 +538,7 @@ public class TestSharedPoolDataSource ex
         assertTrue(l3HashCode == l4HashCode);
         conn.close();
         conn = null;
+        tds.close();
     }
 
     @Test

Modified: 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java
URL: 
http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java?rev=1652830&r1=1652829&r2=1652830&view=diff
==============================================================================
--- 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java
 (original)
+++ 
commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java
 Sun Jan 18 18:59:59 2015
@@ -46,6 +46,7 @@ public class TestTransactionContext {
         final TransactionContext transactionContext =
                 new 
TransactionContext(basicManagedDataSource.getTransactionRegistry(), 
transaction);
         transactionContext.setSharedConnection(conn);
+        basicManagedDataSource.close();
     }
     
     /**


Reply via email to