TOMEE-1900 test case where resource cannot be enlisted in tx
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/1965d0f5 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/1965d0f5 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/1965d0f5 Branch: refs/heads/tomee-1.7.x Commit: 1965d0f5b5c7bb187d7e37dc9e8b4b43ad96d6ef Parents: 31a3491 Author: Jonathan Gallimore <j...@jrg.me.uk> Authored: Thu Aug 11 16:35:32 2016 +0100 Committer: Jonathan Gallimore <j...@jrg.me.uk> Committed: Thu Aug 11 16:35:32 2016 +0100 ---------------------------------------------------------------------- .../jdbc/managed/local/ManagedConnection.java | 1 + .../tomee/jdbc/TomEEDataSourceCreator.java | 15 +-- .../tomee/jdbc/TomcatXADataSourceTest.java | 114 +++++++++++++++++-- 3 files changed, 112 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/1965d0f5/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 d1c2364..452ea76 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 @@ -131,6 +131,7 @@ public class ManagedConnection implements InvocationHandler { currentTransaction = transaction; try { if (!transaction.enlistResource(getXAResource())) { + closeConnection(true); throw new SQLException("Unable to enlist connection in transaction: enlistResource returns 'false'."); } } catch (final RollbackException ignored) { http://git-wip-us.apache.org/repos/asf/tomee/blob/1965d0f5/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java b/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java index b855073..700d73a 100644 --- a/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java +++ b/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java @@ -48,6 +48,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.Properties; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public class TomEEDataSourceCreator extends PoolDataSourceCreator { @@ -219,6 +220,10 @@ public class TomEEDataSourceCreator extends PoolDataSourceCreator { this(poolConfiguration, name, null); } + @Override public Future<Connection> getConnectionAsync() throws SQLException { + return super.getConnectionAsync(); + } + public TomEEDataSource(final PoolConfiguration poolConfiguration, final String name, final XADataSource xaDs) { super(readOnly(poolConfiguration)); if (xaDs != null) { @@ -306,16 +311,6 @@ public class TomEEDataSourceCreator extends PoolDataSourceCreator { } } } - - @Override - public Connection getConnection() throws SQLException { - return super.getConnection(); - } - - @Override - public Connection getConnection(final String username, final String password) throws SQLException { - return super.getConnection(username, password); - } } private static class ReadOnlyConnectionpool implements InvocationHandler { http://git-wip-us.apache.org/repos/asf/tomee/blob/1965d0f5/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 fdf151d..df9ebb7 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 @@ -32,10 +32,15 @@ import org.junit.runner.RunWith; import javax.annotation.Resource; import javax.ejb.EJB; import javax.ejb.Singleton; +import javax.sql.ConnectionEventListener; import javax.sql.DataSource; +import javax.sql.StatementEventListener; import javax.sql.XAConnection; import javax.transaction.Synchronization; import javax.transaction.Transaction; +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; +import javax.transaction.xa.Xid; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; @@ -43,7 +48,7 @@ import java.util.Collection; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; -import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; @@ -267,8 +272,9 @@ public class TomcatXADataSourceTest { } }); ref.getMetaData(); - } catch (final Exception sql) { + } catch (final Exception e) { // we expect this + e.printStackTrace(); } } }); @@ -286,18 +292,110 @@ public class TomcatXADataSourceTest { } public static class BadDataSource extends JDBCXADataSource { - public BadDataSource() throws SQLException { + // no-op } @Override public XAConnection getXAConnection() throws SQLException { + return corrupt(super.getXAConnection()); + } + + @Override + public XAConnection getXAConnection(final String user, final String pwd) throws SQLException { + return corrupt(super.getXAConnection()); + } + + // this closes the underlying connection - which should cause enlist to fail + private XAConnection corrupt(final XAConnection xaConnection) throws SQLException { + return new XAConnection() { + private final XAConnection delegate = xaConnection; + + @Override + public XAResource getXAResource() throws SQLException { + return new XAResource() { + @Override + public void commit(final Xid xid, final boolean b) throws XAException { + + } + + @Override + public void end(final Xid xid, final int i) throws XAException { + + } + + @Override + public void forget(final Xid xid) throws XAException { + + } + + @Override + public int getTransactionTimeout() throws XAException { + return 0; + } + + @Override + public boolean isSameRM(final XAResource xaResource) throws XAException { + return false; + } + + @Override + public int prepare(final Xid xid) throws XAException { + return 0; + } + + @Override + public Xid[] recover(final int i) throws XAException { + return new Xid[0]; + } + + @Override + public void rollback(final Xid xid) throws XAException { + + } + + @Override + public boolean setTransactionTimeout(final int i) throws XAException { + return false; + } + + @Override + public void start(final Xid xid, final int i) throws XAException { + throw new XAException("preventing this from being enlisted"); + } + }; + } + + @Override + public Connection getConnection() throws SQLException { + return delegate.getConnection(); + } + + @Override + public void close() throws SQLException { + delegate.close(); + } + + @Override + public void addConnectionEventListener(final ConnectionEventListener listener) { + delegate.addConnectionEventListener(listener); + } + + @Override + public void removeConnectionEventListener(final ConnectionEventListener listener) { + delegate.removeConnectionEventListener(listener); + } + + @Override + public void addStatementEventListener(final StatementEventListener listener) { + delegate.addStatementEventListener(listener); + } - // this closes the underlying connection - which should cause enlist to fail - final XAConnection xaConnection = super.getXAConnection(); - final Connection connection = xaConnection.getConnection(); - connection.close(); - return xaConnection; + @Override + public void removeStatementEventListener(final StatementEventListener listener) { + delegate.removeStatementEventListener(listener); + } + }; } } }