tomee-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject tomee git commit: TOMEE-1900 better xa pooling handling
Date Thu, 11 Aug 2016 12:00:16 GMT
Repository: tomee
Updated Branches:
  refs/heads/master c9e7fcf5f -> 6d7565af8


TOMEE-1900 better xa pooling handling


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/6d7565af
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/6d7565af
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/6d7565af

Branch: refs/heads/master
Commit: 6d7565af8f6c216644d32dd724bb5a6cd44dc6c5
Parents: c9e7fcf
Author: Romain manni-Bucau <rmannibucau@gmail.com>
Authored: Thu Aug 11 13:59:59 2016 +0200
Committer: Romain manni-Bucau <rmannibucau@gmail.com>
Committed: Thu Aug 11 13:59:59 2016 +0200

----------------------------------------------------------------------
 .../jdbc/managed/local/ManagedConnection.java   |  55 +++++-----
 .../tomee/jdbc/TomcatXADataSourceTest.java      | 100 ++++++++++++++++++-
 2 files changed, 131 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/6d7565af/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java
b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java
index 7dca9c8..03f963a 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java
@@ -102,9 +102,12 @@ public class ManagedConnection implements InvocationHandler {
                         return null;
                     }
 
-                    closeConnection(xaConnection, delegate);
+                    closeConnection(true);
                     return null;
                 }
+                if ("isClosed".equals(mtdName) && closed) {
+                    return true;
+                }
                 if (delegate == null) {
                     newConnection();
                 }
@@ -116,27 +119,29 @@ public class ManagedConnection implements InvocationHandler {
                 if (!currentTransaction.equals(transaction)) {
                     throw new SQLException("Connection can not be used while enlisted in
another transaction");
                 }
-                return invokeUnderTransaction(delegate, method, args);
+                return invokeUnderTransaction(method, args);
             }
 
             // get the already bound connection to the current transaction or enlist this
one in the tx
-            if (isUnderTransaction(transaction.getStatus())) {
+            final int transactionStatus = transaction.getStatus();
+            if (isUnderTransaction(transactionStatus)) {
                 Connection connection = Connection.class.cast(registry.getResource(key));
                 if (connection == null && delegate == null) {
                     newConnection();
-                    connection = delegate;
 
-                    registry.putResource(key, delegate);
                     currentTransaction = transaction;
                     try {
-                        transaction.enlistResource(getXAResource());
+                        if (!transaction.enlistResource(getXAResource())) {
+                            throw new SQLException("Unable to enlist connection in transaction:
enlistResource returns 'false'.");
+                        }
                     } catch (final RollbackException ignored) {
                         // no-op
                     } catch (final SystemException e) {
                         throw new SQLException("Unable to enlist connection the transaction",
e);
                     }
 
-                    transaction.registerSynchronization(new ClosingSynchronization(xaConnection,
delegate));
+                    registry.putResource(key, delegate);
+                    transaction.registerSynchronization(new ClosingSynchronization());
 
                     if (xaConnection == null) {
                         try {
@@ -155,7 +160,14 @@ public class ManagedConnection implements InvocationHandler {
                     delegate = connection;
                 }
 
-                return invokeUnderTransaction(connection, method, args);
+                return invokeUnderTransaction(method, args);
+            }
+
+            if ("isClosed".equals(mtdName) && closed) {
+                return true;
+            }
+            if ("close".equals(mtdName)) { // let it be handled by the ClosingSynchronisation
since we have a tx there
+                return close();
             }
 
             // we shouldn't come here, tempted to just throw an exception
@@ -182,8 +194,8 @@ public class ManagedConnection implements InvocationHandler {
                 (key.user == null ? XADataSource.class.cast(key.ds).getXAConnection() : XADataSource.class.cast(key.ds).getXAConnection(key.user,
key.pwd));
         if (XAConnection.class.isInstance(connection)) {
             xaConnection = XAConnection.class.cast(connection);
-            delegate = xaConnection.getConnection();
             xaResource = xaConnection.getXAResource();
+            delegate = xaConnection.getConnection();
         } else {
             delegate = Connection.class.cast(connection);
             xaResource = new LocalXAResource(delegate);
@@ -206,7 +218,7 @@ public class ManagedConnection implements InvocationHandler {
         }
     }
 
-    private Object invokeUnderTransaction(final Connection delegate, final Method method,
final Object[] args) throws Exception {
+    private Object invokeUnderTransaction(final Method method, final Object[] args) throws
Exception {
         final String mtdName = method.getName();
         if ("setAutoCommit".equals(mtdName)
             || "commit".equals(mtdName)
@@ -239,15 +251,7 @@ public class ManagedConnection implements InvocationHandler {
         return new SQLException("can't call " + mtdName + " when the connection is JtaManaged");
     }
 
-    private static class ClosingSynchronization implements Synchronization {
-        private final XAConnection xaConnection;
-        private final Connection connection;
-
-        public ClosingSynchronization(final XAConnection xaConnection, final Connection delegate)
{
-            this.xaConnection = xaConnection;
-            this.connection = delegate;
-        }
-
+    private class ClosingSynchronization implements Synchronization {
         @Override
         public void beforeCompletion() {
             // no-op
@@ -255,19 +259,24 @@ public class ManagedConnection implements InvocationHandler {
 
         @Override
         public void afterCompletion(final int status) {
-            closeConnection(xaConnection, connection);
+            closeConnection(true);
         }
     }
 
-    private static void closeConnection(final XAConnection xaConnection, final Connection
connection) {
+    private void closeConnection(final boolean force) {
+        if (!force && closed) {
+            return;
+        }
         try {
             if (xaConnection != null) { // handles the underlying connection
                 xaConnection.close();
-            } else if (connection != null && !connection.isClosed()) {
-                connection.close();
+            } else if (delegate != null && !delegate.isClosed()) {
+                delegate.close();
             }
         } catch (final SQLException e) {
             // no-op
+        } finally {
+            close(); // set the flag
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tomee/blob/6d7565af/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatXADataSourceTest.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatXADataSourceTest.java
b/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatXADataSourceTest.java
index db72221..0e19a78 100644
--- a/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatXADataSourceTest.java
+++ b/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatXADataSourceTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomee.jdbc;
 
+import org.apache.openejb.OpenEJB;
 import org.apache.openejb.jee.EjbJar;
 import org.apache.openejb.junit.ApplicationComposer;
 import org.apache.openejb.resource.jdbc.managed.local.ManagedDataSource;
@@ -32,16 +33,19 @@ import javax.annotation.Resource;
 import javax.ejb.EJB;
 import javax.ejb.Singleton;
 import javax.sql.DataSource;
+import javax.transaction.Synchronization;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 @RunWith(ApplicationComposer.class)
@@ -118,7 +122,7 @@ public class TomcatXADataSourceTest {
             assertEquals(25, tds.getIdle());
         }
 
-        // in tx
+        // in tx - closing in tx
         for (int it = 0; it < 5; it++) { // ensures it always works and not only the first
time
             for (int i = 0; i < 25; i++) {
                 tx.run(new Runnable() {
@@ -135,6 +139,7 @@ public class TomcatXADataSourceTest {
                                     c = connection;
                                 }
                             }
+                            c.close(); // ensure we handle properly eager close invocations
                         } catch (final SQLException sql) {
                             fail(sql.getMessage());
                         }
@@ -144,6 +149,99 @@ public class TomcatXADataSourceTest {
             assertEquals(0, tds.getActive());
             assertEquals(25, tds.getIdle());
         }
+
+        // in tx - not closing
+        for (int it = 0; it < 5; it++) { // ensures it always works and not only the first
time
+            for (int i = 0; i < 25; i++) {
+                tx.run(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            Connection c = null;
+                            for (int i = 0; i < 25; i++) {
+                                final Connection connection = ds.getConnection();
+                                connection.getMetaData(); // trigger connection retrieving
otherwise nothing is done (pool is not used)
+                                if (c != null) {
+                                    assertEquals(c, connection);
+                                } else {
+                                    c = connection;
+                                }
+                            }
+                        } catch (final SQLException sql) {
+                            fail(sql.getMessage());
+                        }
+                    }
+                });
+            }
+            assertEquals(0, tds.getActive());
+            assertEquals(25, tds.getIdle());
+        }
+
+        // in tx - closing after tx
+        for (int it = 0; it < 5; it++) { // ensures it always works and not only the first
time
+            for (int i = 0; i < 25; i++) {
+                final AtomicReference<Connection> ref = new AtomicReference<>();
+                tx.run(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            Connection c = null;
+                            for (int i = 0; i < 25; i++) {
+                                final Connection connection = ds.getConnection();
+                                connection.getMetaData(); // trigger connection retrieving
otherwise nothing is done (pool is not used)
+                                if (c != null) {
+                                    assertEquals(c, connection);
+                                } else {
+                                    c = connection;
+                                    ref.set(c);
+                                }
+                            }
+                        } catch (final SQLException sql) {
+                            fail(sql.getMessage());
+                        }
+                    }
+                });
+                assertTrue(ref.get().isClosed()); // closed with tx
+                ref.get().close();
+                assertTrue(ref.get().isClosed());
+            }
+            assertEquals(0, tds.getActive());
+            assertEquals(25, tds.getIdle());
+        }
+
+        // in tx - closing in commit
+        for (int it = 0; it < 5; it++) { // ensures it always works and not only the first
time
+            for (int i = 0; i < 25; i++) {
+                tx.run(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            final Connection ref = ds.getConnection();
+                            ref.getMetaData();
+                            OpenEJB.getTransactionManager().getTransaction().registerSynchronization(new
Synchronization() {
+                                @Override
+                                public void beforeCompletion() {
+                                    // no-op
+                                }
+
+                                @Override
+                                public void afterCompletion(final int status) { // JPA does
it
+                                    try {
+                                        ref.close();
+                                    } catch (final SQLException e) {
+                                        fail(e.getMessage());
+                                    }
+                                }
+                            });
+                        } catch (final Exception sql) {
+                            fail(sql.getMessage());
+                        }
+                    }
+                });
+            }
+            assertEquals(0, tds.getActive());
+            assertEquals(25, tds.getIdle());
+        }
     }
 
     @Singleton


Mime
View raw message