Don't leak Connections when PoolableConnectionFactory.makeObject() fails
to create a JMX ObjectName.
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 73226f9..9c07a75 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -108,6 +108,9 @@
       <action dev="ggregory" type="add" due-to="Gary Gregory">

         Replace Exception with SQLException in some method signatures (preserves binary compatibility, not source).

       </action>

+      <action dev="ggregory" type="add" due-to="Gary Gregory">

+        Don't leak Connections when PoolableConnectionFactory.makeObject() fails to create a JMX ObjectName.

+      </action>

       <!-- UPDATE -->

       <action dev="ggregory" type="update" due-to="Dependabot, Gary Gregory">

         Bump actions/cache from 2.1.6 to 3.0.4 #147, #176.

diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
index 68f7928..937c55c 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
@@ -24,6 +24,7 @@
 import java.util.Objects;

 import java.util.concurrent.atomic.AtomicLong;

 

+import javax.management.MalformedObjectNameException;

 import javax.management.ObjectName;

 

 import org.apache.commons.logging.Log;

@@ -417,11 +418,11 @@
         }

         try {

             initializeConnection(conn);

-        } catch (final SQLException sqle) {

+        } catch (final SQLException e) {

             // Make sure the connection is closed

             Utils.closeQuietly((AutoCloseable) conn);

             // Rethrow original exception so it is visible to caller

-            throw sqle;

+            throw e;

         }

 

         final long connIndex = connectionIndex.getAndIncrement();

@@ -444,8 +445,7 @@
                 config.setJmxEnabled(false);

             }

             final PoolingConnection poolingConn = (PoolingConnection) conn;

-            final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(

-                    poolingConn, config);

+            final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config);

             poolingConn.setStatementPool(stmtPool);

             poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);

             poolingConn.setCacheState(cacheState);

@@ -456,12 +456,16 @@
         if (dataSourceJmxObjectName == null) {

             connJmxName = null;

         } else {

-            connJmxName = new ObjectName(

-                    dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex);

+            final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex;

+            try {

+                connJmxName = new ObjectName(name);

+            } catch (MalformedObjectNameException e) {

+                Utils.closeQuietly((AutoCloseable) conn);

+                throw new SQLException(name, e);

+            }

         }

 

-        final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes,

-                fastFailValidation);

+        final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation);

         pc.setCacheState(cacheState);

 

         return new DefaultPooledObject<>(pc);