You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rz...@apache.org on 2022/06/23 09:15:58 UTC

[tomee] branch TOMEE-3800 created (now c3187a4498)

This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a change to branch TOMEE-3800
in repository https://gitbox.apache.org/repos/asf/tomee.git


      at c3187a4498 TOMEE-3800 - DBCP 2.9.0

This branch includes the following new commits:

     new c3187a4498 TOMEE-3800 - DBCP 2.9.0

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tomee] 01/01: TOMEE-3800 - DBCP 2.9.0

Posted by rz...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch TOMEE-3800
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit c3187a4498c3128c28d6bf57da0f36e24c176eb6
Author: Richard Zowalla <rz...@apache.org>
AuthorDate: Thu Jun 23 11:15:48 2022 +0200

    TOMEE-3800 - DBCP 2.9.0
---
 .../resource/jdbc/dbcp/BasicManagedDataSource.java | 63 +++++++++++++++++++-
 .../resource/jdbc/dbcp/DbcpManagedDataSource.java  | 12 ++++
 .../jdbc/dbcp/DbcpTransactionRegistry.java         | 69 ++++++++++++++++++++++
 pom.xml                                            |  2 +-
 4 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/BasicManagedDataSource.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/BasicManagedDataSource.java
index f2ff9ffde6..09369d3333 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/BasicManagedDataSource.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/BasicManagedDataSource.java
@@ -20,9 +20,13 @@ package org.apache.openejb.resource.jdbc.dbcp;
 import org.apache.commons.dbcp2.ConnectionFactory;
 import org.apache.commons.dbcp2.PoolableConnection;
 import org.apache.commons.dbcp2.PoolingDataSource;
+import org.apache.commons.dbcp2.Utils;
+import org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory;
+import org.apache.commons.dbcp2.managed.LocalXAConnectionFactory;
 import org.apache.commons.dbcp2.managed.ManagedConnection;
 import org.apache.commons.dbcp2.managed.ManagedDataSource;
 import org.apache.commons.dbcp2.managed.TransactionRegistry;
+import org.apache.commons.dbcp2.managed.XAConnectionFactory;
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.cipher.PasswordCipher;
 import org.apache.openejb.cipher.PasswordCipherFactory;
@@ -37,9 +41,11 @@ import org.apache.openejb.util.reflection.Reflections;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.sql.DataSource;
+import javax.sql.XADataSource;
 import java.io.File;
 import java.io.ObjectStreamException;
 import java.io.Serializable;
+import java.lang.reflect.Field;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
@@ -130,9 +136,64 @@ public class BasicManagedDataSource extends org.apache.commons.dbcp2.managed.Bas
                 // no-op
             }
         }
-        return super.createConnectionFactory();
+
+        if (getTransactionManager() == null) {
+            throw new SQLException("Transaction manager must be set before a connection can be created");
+        } else if (getXADataSource() == null) {
+            ConnectionFactory connectionFactory = super.createConnectionFactory();
+            XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(this.getTransactionManager(), this.getTransactionSynchronizationRegistry(), connectionFactory);
+            setTransactionRegistry(xaConnectionFactory, new DbcpTransactionRegistry(getTransactionManager()));
+            setTransactionRegistry(xaConnectionFactory.getTransactionRegistry());
+            return xaConnectionFactory;
+        } else {
+            XADataSource xaDataSourceInstance = getXaDataSourceInstance();
+            if (xaDataSourceInstance == null) {
+                Class xaDataSourceClass;
+
+                String message;
+                try {
+                    xaDataSourceClass = Class.forName(xaDataSource);
+                } catch (Exception var5) {
+                    message = "Cannot load XA data source class '" + xaDataSource + "'";
+                    throw new SQLException(message, var5);
+                }
+
+                try {
+                   setXaDataSourceInstance((XADataSource) xaDataSourceClass.getConstructor().newInstance());
+                } catch (Exception var4) {
+                    message = "Cannot create XA data source of class '" + xaDataSource + "'";
+                    throw new SQLException(message, var4);
+                }
+            }
+
+            XAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(this.getTransactionManager(), getXaDataSourceInstance(), this.getUsername(), Utils.toCharArray(this.getPassword()), this.getTransactionSynchronizationRegistry());
+            setTransactionRegistry(xaConnectionFactory, new DbcpTransactionRegistry(getTransactionManager()));
+            setTransactionRegistry(xaConnectionFactory.getTransactionRegistry());
+            return xaConnectionFactory;
+        }
     }
 
+    private void setTransactionRegistry(final TransactionRegistry registry) {
+        try {
+            final Field field = org.apache.commons.dbcp2.managed.BasicManagedDataSource.class.getDeclaredField("transactionRegistry");
+            field.setAccessible(true);
+            field.set(this, registry);
+        } catch (final Throwable e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void setTransactionRegistry(XAConnectionFactory xaConnectionFactory, final TransactionRegistry registry) {
+        try {
+            final Field field = xaConnectionFactory.getClass().getDeclaredField("transactionRegistry");
+            field.setAccessible(true);
+            field.set(xaConnectionFactory, registry);
+        } catch (final Throwable e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+
     private void setJndiXaDataSource(final String xaDataSource) {
         setXaDataSourceInstance( // proxy cause we don't know if this datasource was created before or not the delegate
                 XADataSourceResource.proxy(getDriverClassLoader() != null ? getDriverClassLoader() : Thread.currentThread().getContextClassLoader(), xaDataSource));
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpManagedDataSource.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpManagedDataSource.java
index 5d6025c833..9b23c231fd 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpManagedDataSource.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpManagedDataSource.java
@@ -59,6 +59,7 @@ public class DbcpManagedDataSource extends BasicManagedDataSource {
             // Create the XAConectionFactory using the XA data source
             final XADataSource xaDataSourceInstance = (XADataSource) ds;
             final XAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(getTransactionManager(), xaDataSourceInstance, getUsername(), getPassword());
+            setTransactionRegistry(xaConnectionFactory, new DbcpTransactionRegistry(getTransactionManager()));
             setTransactionRegistry(xaConnectionFactory.getTransactionRegistry());
             return xaConnectionFactory;
 
@@ -67,6 +68,7 @@ public class DbcpManagedDataSource extends BasicManagedDataSource {
         // If xa data source is not specified a DriverConnectionFactory is created and wrapped with a LocalXAConnectionFactory
         final ConnectionFactory connectionFactory = new DataSourceConnectionFactory(DataSource.class.cast(ds), getUsername(), getPassword());
         final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(getTransactionManager(), connectionFactory);
+        setTransactionRegistry(xaConnectionFactory, new DbcpTransactionRegistry(getTransactionManager()));
         setTransactionRegistry(xaConnectionFactory.getTransactionRegistry());
         return xaConnectionFactory;
     }
@@ -80,4 +82,14 @@ public class DbcpManagedDataSource extends BasicManagedDataSource {
             throw new IllegalStateException(e);
         }
     }
+
+    public void setTransactionRegistry(XAConnectionFactory xaConnectionFactory, final TransactionRegistry registry) {
+        try {
+            final Field field = xaConnectionFactory.getClass().getDeclaredField("transactionRegistry");
+            field.setAccessible(true);
+            field.set(xaConnectionFactory, registry);
+        } catch (final Throwable e) {
+            throw new IllegalStateException(e);
+        }
+    }
 }
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpTransactionRegistry.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpTransactionRegistry.java
new file mode 100644
index 0000000000..011176e716
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/dbcp/DbcpTransactionRegistry.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.resource.jdbc.dbcp;
+
+import org.apache.commons.dbcp2.managed.TransactionContext;
+
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import java.sql.SQLException;
+
+public class DbcpTransactionRegistry extends org.apache.commons.dbcp2.managed.TransactionRegistry{
+
+    private TransactionManager transactionManager;
+
+    public DbcpTransactionRegistry(TransactionManager transactionManager) {
+        this(transactionManager, null);
+    }
+
+    public DbcpTransactionRegistry(TransactionManager transactionManager, TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
+        super(transactionManager, transactionSynchronizationRegistry);
+        this.transactionManager = transactionManager;
+    }
+
+    /**
+     * Gets the active TransactionContext or null if not Transaction is active.
+     *
+     * @return The active TransactionContext or null if no Transaction is active.
+     * @throws SQLException
+     *             Thrown when an error occurs while fetching the transaction.
+     */
+    public TransactionContext getActiveTransactionContext() throws SQLException {
+        Transaction transaction;
+        try {
+            transaction = transactionManager.getTransaction();
+
+            // was there a transaction?
+            if (transaction == null) {
+                return null;
+            }
+
+            // is it active
+            final int status = transaction.getStatus();
+            if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) {
+                return null;
+            }
+        } catch (final SystemException e) {
+            throw new SQLException("Unable to determine current transaction ", e);
+        }
+
+        return super.getActiveTransactionContext();
+    }
+}
diff --git a/pom.xml b/pom.xml
index 672f384bb9..c52b25a3e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -182,7 +182,7 @@
       'QuartzPersistenceForEJBTimersTest' is unable to obtain DB connection with
       commons-dbcp.version > 2.3.0
     -->
-    <commons-dbcp.version>2.3.0</commons-dbcp.version>
+    <commons-dbcp.version>2.9.0</commons-dbcp.version>
     <commons-pool.version>2.11.1</commons-pool.version>
     <commons-collections.version>3.2.2</commons-collections.version>
     <commons-codec.version>1.15</commons-codec.version>