You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/05/14 14:19:28 UTC
[commons-dbcp] branch master updated: [DBCP-564] Fix
BasicManagedDataSource leak of connections opened after transaction is
rollback-only (#39)
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git
The following commit(s) were added to refs/heads/master by this push:
new 1474ba3 [DBCP-564] Fix BasicManagedDataSource leak of connections opened after transaction is rollback-only (#39)
1474ba3 is described below
commit 1474ba327798ebfabbcf5ab1db01330851f3377c
Author: Florent Guillaume <fg...@nuxeo.com>
AuthorDate: Thu May 14 16:19:21 2020 +0200
[DBCP-564] Fix BasicManagedDataSource leak of connections opened after transaction is rollback-only (#39)
---
.../dbcp2/managed/BasicManagedDataSource.java | 2 +-
.../dbcp2/managed/LocalXAConnectionFactory.java | 20 ++++++++++++++++-
.../dbcp2/managed/TestBasicManagedDataSource.java | 25 +++++++++++++++++++++-
3 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java
index 9e312ce..11dcbcd 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java
@@ -174,7 +174,7 @@ public class BasicManagedDataSource extends BasicDataSource {
if (xaDataSource == null) {
final ConnectionFactory connectionFactory = super.createConnectionFactory();
final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(getTransactionManager(),
- connectionFactory);
+ getTransactionSynchronizationRegistry(), connectionFactory);
transactionRegistry = xaConnectionFactory.getTransactionRegistry();
return xaConnectionFactory;
}
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
index 3fa6636..50e9f91 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
@@ -20,6 +20,7 @@ package org.apache.commons.dbcp2.managed;
import org.apache.commons.dbcp2.ConnectionFactory;
import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
@@ -310,17 +311,34 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
*
* @param transactionManager
* the transaction manager in which connections will be enlisted
+ * @param transactionSynchronizationRegistry
+ * the optional TSR to register synchronizations with
* @param connectionFactory
* the connection factory from which connections will be retrieved
*/
public LocalXAConnectionFactory(final TransactionManager transactionManager,
+ final TransactionSynchronizationRegistry transactionSynchronizationRegistry,
final ConnectionFactory connectionFactory) {
Objects.requireNonNull(transactionManager, "transactionManager is null");
Objects.requireNonNull(connectionFactory, "connectionFactory is null");
- this.transactionRegistry = new TransactionRegistry(transactionManager);
+ this.transactionRegistry = new TransactionRegistry(transactionManager, transactionSynchronizationRegistry);
this.connectionFactory = connectionFactory;
}
+ /**
+ * Creates an LocalXAConnectionFactory which uses the specified connection factory to create database connections.
+ * The connections are enlisted into transactions using the specified transaction manager.
+ *
+ * @param transactionManager
+ * the transaction manager in which connections will be enlisted
+ * @param connectionFactory
+ * the connection factory from which connections will be retrieved
+ */
+ public LocalXAConnectionFactory(final TransactionManager transactionManager,
+ final ConnectionFactory connectionFactory) {
+ this(transactionManager, null, connectionFactory);
+ }
+
@Override
public Connection createConnection() throws SQLException {
// create a new connection
diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TestBasicManagedDataSource.java b/src/test/java/org/apache/commons/dbcp2/managed/TestBasicManagedDataSource.java
index d4576ef..64de034 100644
--- a/src/test/java/org/apache/commons/dbcp2/managed/TestBasicManagedDataSource.java
+++ b/src/test/java/org/apache/commons/dbcp2/managed/TestBasicManagedDataSource.java
@@ -48,7 +48,9 @@ public class TestBasicManagedDataSource extends TestBasicDataSource {
@Override
protected BasicDataSource createDataSource() throws Exception {
final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
- basicManagedDataSource.setTransactionManager(new TransactionManagerImpl());
+ TransactionManagerImpl transactionManager = new TransactionManagerImpl();
+ basicManagedDataSource.setTransactionManager(transactionManager);
+ basicManagedDataSource.setTransactionSynchronizationRegistry(transactionManager);
return basicManagedDataSource;
}
@@ -219,4 +221,25 @@ public class TestBasicManagedDataSource extends TestBasicDataSource {
tm.commit();
}
}
+
+ /** DBCP-564 */
+ @Test
+ public void testSetRollbackOnlyBeforeGetConnectionDoesNotLeak() throws Exception {
+ final TransactionManager transactionManager = ((BasicManagedDataSource) ds).getTransactionManager();
+ final int n = 3;
+ ds.setMaxIdle(n);
+ ds.setMaxTotal(n);
+
+ for (int i = 0; i <= n; i++) { // loop n+1 times
+ transactionManager.begin();
+ transactionManager.setRollbackOnly();
+ final Connection conn = getConnection();
+ assertNotNull(conn);
+ conn.close();
+ transactionManager.rollback();
+ }
+
+ assertEquals(0, ds.getNumActive());
+ assertEquals(1, ds.getNumIdle());
+ }
}