package org.csc.phynixx.xa.concurrent; /* * #%L * phynixx-xa * %% * Copyright (C) 2014 csc * %% * Licensed 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. * #L% */ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.xa.XAResource; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.csc.phynixx.common.TestUtils; import org.csc.phynixx.common.exceptions.DelegatedRuntimeException; import org.csc.phynixx.common.logger.IPhynixxLogger; import org.csc.phynixx.common.logger.PhynixxLogManager; import org.csc.phynixx.phynixx.testconnection.ITestConnection; import org.csc.phynixx.phynixx.testconnection.TestConnectionStatus; import org.csc.phynixx.phynixx.testconnection.TestConnectionStatusManager; import org.csc.phynixx.phynixx.testconnection.TestStatusStack; import org.csc.phynixx.watchdog.WatchdogRegistry; import org.csc.phynixx.xa.IPhynixxXAConnection; import org.csc.phynixx.xa.IPhynixxXAResource; import org.csc.phynixx.xa.PhynixxXAResource; import org.csc.phynixx.xa.TestXAResourceFactory; import org.csc.phynixx.xa.recovery.XidWrapper; import org.csc.phynixx.xa.transactionmanagers.ITransactionManagerProvider; import org.csc.phynixx.xa.transactionmanagers.JotmTransactionManagerProvider; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer; @RunWith(BlockJUnit4ClassRunner.class) public class JotmConcurrentIntegrationTest { { System.setProperty("log4j_level", "INFO"); } private static final IPhynixxLogger LOG = PhynixxLogManager.getLogger(JotmConcurrentIntegrationTest.class); private ITransactionManagerProvider transactionManagerProvider = //new BitronixTransactionManagerProvider(); // new JotmTransactionManagerProvider(); private TestXAResourceFactory factory1 = null; private TestXAResourceFactory factory2 = null; @Before public void setUp() throws Exception { // configuring the log-system (e.g. log4j) TestUtils.configureLogging(); TestConnectionStatusManager.clear(); this.transactionManagerProvider.start(); this.factory1 = new TestXAResourceFactory(1, "RF1", null, this.transactionManagerProvider.getTransactionManager()); this.factory2 = new TestXAResourceFactory(1, "RF2", null, this.transactionManagerProvider.getTransactionManager()); } @After public void tearDown() throws Exception { if (this.transactionManagerProvider != null) { this.transactionManagerProvider.stop(); } if (this.factory1 != null) { this.factory1.close(); this.factory1 = null; } if (this.factory2 != null) { this.factory2.close(); this.factory2 = null; } TestConnectionStatusManager.clear(); WatchdogRegistry.getTheRegistry().shutdown(); } private TransactionManager getTransactionManager() { return this.transactionManagerProvider.getTransactionManager(); } private Map<String, Exception> exceptions = new ConcurrentHashMap<String, Exception>(); private class SmallTask implements Callable<Void> { int id; public SmallTask(int id) { super(); this.id = id; } int rd=new Random().nextInt(27); @Override public Void call() throws Exception { try { LOG.info("Tasks "+id+" starts executing in Thread "+Thread.currentThread().getName()); JotmConcurrentIntegrationTest.this.testOnePhaseReadOnly(); sleep(rd*370); testTransactionMigration(); sleep(rd*190); testTwoPhaseReadOnly(); return null; } catch (Exception e) { JotmConcurrentIntegrationTest.this.exceptions.put(Thread.currentThread().getName(), e); throw new DelegatedRuntimeException(e); } finally { LOG.info("Tasks "+id+" executed in Thread "+Thread.currentThread().getName()); } } private void sleep(long msecs) { try { Thread.sleep(msecs); } catch(Exception e) {} } } @Test public void runSmallTask() throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); List<Callable<Void>> tasks= new ArrayList<Callable<Void>>(); int limit = 1; for (int i = 0; i < limit; i++) { tasks.add(new SmallTask(i)); } executorService.invokeAll(tasks); executorService.shutdown(); executorService.awaitTermination(100, TimeUnit.SECONDS); Set<PhynixxXAResource<ITestConnection>> unreleasedXAResources = factory1.getUnreleasedXAResources(); for (PhynixxXAResource<ITestConnection> phynixxXAResource : unreleasedXAResources) { LOG.warn("UInreleased XAResource "+phynixxXAResource); } Assert.assertEquals("Factory 1 has Unreleased XAResources ", 0,factory1.getUnreleasedXAResources().size()); Assert.assertEquals("Factory 2 has Unreleased XAResources ", 0,factory2.getUnreleasedXAResources().size()); if(!exceptions.isEmpty()) { for (Map.Entry<String,Exception> entry : exceptions.entrySet()) { entry.getValue().printStackTrace(); } throw exceptions.values().iterator().next(); } ; } /** * there 's just one XAResource enlisted in a resource but this resource * hasn't changed. The TM performs a 1-phase read-only commit * * @throws Exception */ public void testOnePhaseReadOnly() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); // u are just interfacing the proxy. // ... the real core connection is hidden by the proxy final Object conId; // for bitronix this.transactionManagerProvider.register(xaCon.getXAResource()); this.getTransactionManager().begin(); this.getTransactionManager().getTransaction(); // join the transaction conId = xaCon.getConnection().getConnectionId(); this.getTransactionManager().commit(); } /** * there 's just one XAResource enlisted in a resource and the TM performs a * 1-phase commit * * @throws Exception */ public void testOnePhaseCommit1() throws Exception { // get a XAResource IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); // u are just interfacing the proxy. this.getTransactionManager().begin(); // ... the real core connection is hidden by the proxy final Object conId; ITestConnection con = xaCon.getConnection(); conId = con.getConnectionId(); // act transactional and enlist the current resource con.act(1); this.getTransactionManager().commit(); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isPrepared()); TestCase.assertTrue(statusStack.isReleased()); // TestCase.assertTrue(factory1.isFreeConnection(con)); } /** * there 's just one XAResource enlisted in a resource and the TM performs a * 1-phase commit * * @throws Exception */ public void testTransactionMigration() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); this.transactionManagerProvider.register(xaCon.getXAResource()); // u are just interfacing the proxy. // ... the real core connection is hidden by the proxy ITestConnection con = xaCon.getConnection(); Object conId = con.getConnectionId(); try { this.getTransactionManager().begin(); // refresh transaction binding con = xaCon.getConnection(); // act transactional and enlist the current resource con.act(1); this.getTransactionManager().commit(); } finally { if (con != null) { con.close(); } } LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isPrepared()); } /** * two different XAResourceProgressState Factories ( == resourceManagers) * There are two XAResource created but only one resource is enlisted in the * transaction * * @throws Exception */ public void testTwoPhaseReadOnly() throws Exception { Object conId1 = null; ITestConnection con1 = null; ITestConnection con2 = null; Object conId2 = null; this.getTransactionManager().begin(); IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); con1 = xaCon1.getConnection(); conId1 = con1.getConnectionId(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory2.getXAConnection(); con2 = xaCon2.getConnection(); conId2 = con2.getConnectionId(); // act transactional and enlist the current resource con1.act(1); // no act on the second resource ... // .... con2.act(); this.getTransactionManager().commit(); LOG.info(TestConnectionStatusManager.toDebugString()); // conj1 has been changed an the XA protocol is performed TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon1)); // assert that the con2 // con2 has not been changed , so no rollback/prepare/commit was // performed statusStack = TestConnectionStatusManager.getStatusStack(conId2); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(!statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isPrepared()); TestCase.assertTrue(!statusStack.isRolledback()); TestCase.assertTrue(statusStack.isReleased()); // TestCase.assertTrue(factory2.isFreeConnection(coreCon2)); } /** * two XAResource of the same Factory are joining the same underlying * connection and the TZX is rolled back * * @throws Exception */ public void testJoinedRollback() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); // ResourceRegistrar.register(factory1.getXAResource()); // u are just interfacing the proxy. ITestConnection con1 = null; ITestConnection con2 = null; Object conId2 = null; // ... the real core connection is hidden by the proxy this.getTransactionManager().begin(); con1 = xaCon1.getConnection(); con2 = xaCon2.getConnection(); con1.act(1); con2.act(2); Object conId1 = con1.getConnectionId(); conId2 = con2.getConnectionId(); // same physical connection Assert.assertTrue("same physical connection", conId2 == conId1); // act transactional and enlist the current resource // conProxy.act(); this.getTransactionManager().rollback(); LOG.info(TestConnectionStatusManager.toDebugString()); // @RequiredTransaction was requested twice Assert.assertEquals( 2, TestConnectionStatusManager.getStatusStack(conId2).countStatus( TestConnectionStatus.REQUIRES_TRANSACTION)); Assert.assertEquals(1, TestConnectionStatusManager.getStatusStack(conId2).countStatus(TestConnectionStatus.ROLLEDBACK)); Assert.assertEquals(1, TestConnectionStatusManager.getStatusStack(conId2).countStatus(TestConnectionStatus.RELEASED)); } /** * two XAResource of the same Factory are joining the same underlying * connection and the TZX is rolled back * * @throws Exception */ public void testJoinedCommit() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); // u are just interfacing the proxy. ITestConnection con1 = null; ITestConnection con2 = null; Object conId2 = null; // ... the real core connection is hidden by the proxy this.getTransactionManager().begin(); con1 = xaCon1.getConnection(); con2 = xaCon2.getConnection(); con1.act(1); con2.act(2); Object conId1 = con1.getConnectionId(); conId2 = con2.getConnectionId(); // same physical connection Assert.assertTrue("same physical connection", conId2 == conId1); // act transactional and enlist the current resource // conProxy.act(); this.getTransactionManager().commit(); LOG.info(TestConnectionStatusManager.toDebugString()); // @RequiredTransaction was requested twice Assert.assertEquals( 2, TestConnectionStatusManager.getStatusStack(conId2).countStatus( TestConnectionStatus.REQUIRES_TRANSACTION)); // onePhase Commit ist performed , so no prepare Assert.assertEquals(0, TestConnectionStatusManager.getStatusStack(conId2).countStatus(TestConnectionStatus.PREPARED)); Assert.assertEquals(1, TestConnectionStatusManager.getStatusStack(conId2).countStatus(TestConnectionStatus.COMMITTED)); Assert.assertEquals(1, TestConnectionStatusManager.getStatusStack(conId2).countStatus(TestConnectionStatus.RELEASED)); } /** * there 's just one XAResource enlisted in a resource but the nothing has * to be committed. As the Transaction managers performs a 1 phase commit * the resource is committed correctly * * @throws Exception */ public void testExplicitEnlistment1() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); this.getTransactionManager().begin(); this.getTransactionManager().getTransaction().enlistResource(xaCon.getXAResource()); // u are just interfacing the proxy. ITestConnection con = xaCon.getConnection(); // ... the real core connection is hidden by the proxy Object conId = con.getConnectionId(); // act transactional and enlist the current resource // conProxy.act(); this.getTransactionManager().commit(); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(!statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isRolledback()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon)); } /** * there 's just one XAResource enlisted in a resource but the nothing has * to be committed. As the Transaction managers performs a 1 phase commit * the resource is committed correctly * * @throws Exception */ public void testExplicitEnlistment2() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); // ... the real core connection is hidden by the proxy this.getTransactionManager().begin(); this.getTransactionManager().getTransaction().enlistResource(xaCon.getXAResource()); // u are just interfacing the proxy. ITestConnection con = xaCon.getConnection(); // act transactional and enlist the current resource Object conId = con.getConnectionId(); con.act(2); this.getTransactionManager().commit(); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isRolledback()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon)); } /** * two different XAResourceProgressState Factories ( == resourceManagers) * * @throws Exception */ public void testTwoPhaseCommit() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory2.getXAConnection(); this.getTransactionManager().begin(); ITestConnection con = xaCon1.getConnection(); ITestConnection con1 = xaCon1.getConnection(); Object conId1 = con1.getConnectionId(); // same connection in same TX of same XAResource Assert.assertEquals(conId1, con.getConnectionId()); ITestConnection con2 = xaCon2.getConnection(); Object conId2 = con2.getConnectionId(); // act transactional and enlist the current resource con1.act(1); con2.act(1); Assert.assertTrue(conId1 != conId2); this.getTransactionManager().commit(); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon1)); statusStack = TestConnectionStatusManager.getStatusStack(conId2); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); // TestCase.assertTrue(factory2.isFreeConnection(coreCon2)); } /** * one XAResourceProgressState Factory ( == resourceManagers) but two * Connections. The connections are joined and the transaction ends up in a * one-phase-commit * * @throws Exception */ public void testOnePhaseCommitOneRM_1() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); this.getTransactionManager().begin(); ITestConnection con1 = xaCon1.getConnection(); Object conId1 = con1.getConnectionId(); ITestConnection con2 = xaCon2.getConnection(); Object conId2 = con2.getConnectionId(); Assert.assertTrue(conId1 == conId2); // act transactional and enlist the current resource con1.act(1); con2.act(1); // the two XAresources are joined and con2 is released // TestCase.assertTrue(factory1.isFreeConnection(coreCon2)); // Exception, da con1 con2 unterschiedliche Connections sind, die aber // via TMJOIN bei gleichem // RM zusammengefuehrt werden muessen // derzeit gibt es aber keinen meschanismus dafuer this.getTransactionManager().commit(); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); // one Phase commit -> no prepare TestCase.assertTrue(!statusStack.isPrepared()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon1)); } /** * @throws Exception */ public void testExplicitEnlistmentTwoPhaseCommitTwoRM() throws Exception { IPhynixxXAResource<ITestConnection> xares1 = factory1.getXAResource(); IPhynixxXAResource<ITestConnection> xares2 = factory2.getXAResource(); ITestConnection con1 = null; ITestConnection con2 = null; ITestConnection coreCon1 = null; ITestConnection coreCon2 = null; Object conId1 = null; Object conId2 = null; this.getTransactionManager().begin(); this.getTransactionManager().getTransaction().enlistResource(xares1); this.getTransactionManager().getTransaction().enlistResource(xares2); con1 = xares1.getXAConnection().getConnection(); // coreCon1 = (ITestConnection) ((IPhynixxManagedConnection) // con1).getConnection(); conId1 = con1.getConnectionId(); con2 = xares2.getXAConnection().getConnection(); // coreCon2 = (ITestConnection) ((IPhynixxManagedConnection) // con1).getConnection(); conId2 = con2.getConnectionId(); Assert.assertTrue(conId1 != conId2); // act transactional and enlist the current resource con1.act(1); con2.act(1); this.getTransactionManager().commit(); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); // TestCase.assertTrue(factory1.isFreeConnection(coreCon1)); statusStack = TestConnectionStatusManager.getStatusStack(conId2); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); // TestCase.assertTrue(factory2.isFreeConnection(coreCon2)); } /** * two different XAResourceProgressState Factories ( == resourceManagers) * There are two XAResource created and both resources are enlisted in the * TX but only one has anything to commit. * * @throws Exception */ public void testTwoPhaseCommitOneRM_3() throws Exception { IPhynixxXAResource<ITestConnection> xares1 = factory1.getXAResource(); IPhynixxXAResource<ITestConnection> xares2 = factory2.getXAResource(); this.getTransactionManager().begin(); this.getTransactionManager().getTransaction().enlistResource(xares1); this.getTransactionManager().getTransaction().enlistResource(xares2); ITestConnection con1 = xares1.getXAConnection().getConnection(); ITestConnection con2 = xares2.getXAConnection().getConnection(); Object conId1 = con1.getConnectionId(); Object conId2 = con2.getConnectionId(); // act transactional and enlist the current resource con1.act(1); this.getTransactionManager().commit(); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); TestCase.assertTrue(statusStack.isPrepared()); TestCase.assertTrue(statusStack.isReleased()); statusStack = TestConnectionStatusManager.getStatusStack(conId2); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(!statusStack.isCommitted()); TestCase.assertTrue(!statusStack.isPrepared()); TestCase.assertTrue(statusStack.isReleased()); } /** * one XAResourceProgressState Factory ( == resourceManagers) but 3 * Connections. The connections are joined and the transaction ends up in a * one-phase-commit * * @throws Exception */ public void testCommit3Connections1RM() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon3 = factory1.getXAConnection(); this.getTransactionManager().begin(); ITestConnection con1 = xaCon1.getConnection(); ITestConnection con2 = xaCon2.getConnection(); ITestConnection con3 = xaCon3.getConnection(); // act transactional and enlist the current resource con1.act(1); con2.act(1); con3.act(1); this.getTransactionManager().commit(); LOG.info(TestConnectionStatusManager.toDebugString()); Assert.assertTrue(con1.getConnectionId() == con2.getConnectionId()); Assert.assertTrue(con1.getConnectionId() == con3.getConnectionId()); TestStatusStack statusStack = TestConnectionStatusManager.getStatusStack(con3.getConnectionId()); TestCase.assertTrue(statusStack != null); TestCase.assertTrue(statusStack.isCommitted()); // one-phae commit -> no prepare TestCase.assertTrue(!statusStack.isPrepared()); TestCase.assertTrue(statusStack.isReleased()); } /** * one XAResourceProgressState Factory ( == resourceManagers) but two * Connections. The connections are joined and the transaction end sup in a * one-phase-commit * * @throws Exception */ public void testTwoPhaseCommitTwoRM_2() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); ITestConnection con1 = xaCon1.getConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); ITestConnection con2 = xaCon2.getConnection(); IPhynixxXAConnection<ITestConnection> xaCon3 = factory1.getXAConnection(); ITestConnection con3 = xaCon3.getConnection(); try { this.getTransactionManager().begin(); // act transactional and enlist the current resource con1.act(1); con2.act(1); con3.act(1); this.getTransactionManager().commit(); } finally { if (con1 != null) { con1.close(); } if (con2 != null) { con2.close(); } if (con3 != null) { con3.close(); } } } public void testSuspend() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon2 = factory1.getXAConnection(); IPhynixxXAConnection<ITestConnection> xaCon3 = factory1.getXAConnection(); EhCacheXAResourceProducer.registerXAResource("XXXX", factory1.getXAResource()); this.getTransactionManager().begin(); ITestConnection con1 = xaCon1.getConnection(); con1.act(1); Transaction tx = this.getTransactionManager().suspend(); this.getTransactionManager().begin(); ITestConnection con2 = xaCon3.getConnection(); con2.act(1); this.getTransactionManager().commit(); this.getTransactionManager().resume(tx); this.getTransactionManager().rollback(); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(con1.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isRolledback()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(con2.getConnectionId()); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isCommitted()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack2.isPrepared()); TestCase.assertTrue(statusStack2.isReleased()); } /** * * Suspending one XAConnection opens a second transactional branch and * therefore a second physical connection. * * remember: the connection are associated to a TX by the call of * xaConn.getConnection * * @throws Exception */ public void testSuspendOneXAConnection() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); this.getTransactionManager().begin(); ITestConnection outCon = xaCon.getConnection(); outCon.act(1); Transaction tx = this.getTransactionManager().suspend(); this.getTransactionManager().begin(); // associate connection to current transactional branch ITestConnection innerCon = xaCon.getConnection(); innerCon.act(1); this.getTransactionManager().commit(); this.getTransactionManager().resume(tx); this.getTransactionManager().rollback(); // different transactional branches Assert.assertTrue(outCon.getConnectionId() != innerCon.getConnectionId()); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(outCon.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isRolledback()); TestCase.assertFalse(statusStack1.isCommitted()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(innerCon.getConnectionId()); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isCommitted()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack2.isPrepared()); TestCase.assertFalse(statusStack2.isRolledback()); TestCase.assertTrue(statusStack2.isReleased()); } /** * a transaction context bound to TX1. TX 1 is suspended and n new TX2 is * started. Any modifications on the transactional context is attached to * TX1. * * Any rollback/commit on TZX2 doesn't effect the transactional context. * * @throws Exception */ public void testSuspendInvalidTransactionalContext() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); // stat TX1 this.getTransactionManager().begin(); ITestConnection con1 = xaCon1.getConnection(); con1.act(1); // suspend TX1 Transaction tx = this.getTransactionManager().suspend(); // start TX2 this.getTransactionManager().begin(); // con1 remains asociated to the suspended TX as xaCon.getConnection() // is not called con1.act(1); // commit on TX2 has no effect this.getTransactionManager().commit(); this.getTransactionManager().resume(tx); // rollback on TX1 effects con1 this.getTransactionManager().rollback(); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(con1.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isRolledback()); // connection is associated to the first TX, the second TX has no effect // on the transaction context TestCase.assertTrue(!statusStack1.isCommitted()); } /** * * Suspending one XAConnection opens a second transactional branch and * therefore a second physical connection. * * remember: the connection are associated to a TX by the call of * xaConn.getConnection * * @throws Exception */ public void testMixedLocalGlobalTransaction() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); // con1 on local transaction ITestConnection con1 = xaCon.getConnection(); con1.act(1); con1.act(2); con1.commit(); con1.close(); // con2 on global transaction this.getTransactionManager().begin(); ITestConnection con2 = xaCon.getConnection(); con2.act(1); this.getTransactionManager().rollback(); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(con1.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isCommitted()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(con2.getConnectionId()); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isRolledback()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack2.isPrepared()); TestCase.assertTrue(statusStack2.isReleased()); } /** * A local transaction is opened and transactional context is modified and * left open. * * Therefore no new Transaction (local or global) may be started on the * XAConnection * * * @throws Exception */ public void testMixedLocalGlobalTransactionNested1() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon1 = factory1.getXAConnection(); // con1 on local transaction ITestConnection con1 = xaCon1.getConnection(); con1.act(1); con1.act(2); // con2 on global transaction this.getTransactionManager().begin(); try { ITestConnection con2 = xaCon1.getConnection(); throw new AssertionFailedError("Nested Transactions are not permitted"); } catch (Exception e) { } } /** * * A local transaction is opened, transactional context is modified but * rolled back at least. Therefore the transactional context is closed and a * new global transaction can be start on this XAConncgtion * * @throws Exception */ public void testMixedLocalGlobalTransactionNested3() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); // con 1in lo´cal transaction. Transactional context has transactional // data ITestConnection con1 = xaCon.getConnection(); Object conId1 = con1.getConnectionId(); con1.act(1); con1.act(2); con1.commit(); // con1 on global transaction this.getTransactionManager().begin(); // con2 shared con1 on global transaction ITestConnection con2 = xaCon.getConnection(); Object conId2 = con2.getConnectionId(); con2.act(2); this.getTransactionManager().rollback(); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(conId1); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isRolledback()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(conId2); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isCommitted()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack2.isPrepared()); TestCase.assertTrue(statusStack2.isReleased()); } /** * * Suspending one XAConnection opens a second transactional branch and * therefore a second physical connection. * * remember: the connection are associated to a TX by the call of * xaConn.getConnection * * @throws Exception */ public void testMixedLocalGlobalTransactionAndSuspend() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); this.getTransactionManager().begin(); ITestConnection con0 = xaCon.getConnection(); con0.act(3); Transaction transaction = this.getTransactionManager().getTransaction(); this.getTransactionManager().suspend(); // con1 on local transaction ITestConnection con1 = xaCon.getConnection(); con1.act(1); con1.act(2); con1.commit(); con1.close(); // con2 on global transaction this.getTransactionManager().begin(); ITestConnection con2 = xaCon.getConnection(); con2.act(1); this.getTransactionManager().rollback(); this.getTransactionManager().resume(transaction); con0.act(2); this.getTransactionManager().rollback(); Assert.assertTrue(con0.getConnectionId() != con2.getConnectionId()); Assert.assertTrue(con1.getConnectionId() == con2.getConnectionId()); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(con1.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isCommitted()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(con2.getConnectionId()); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isRolledback()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack2.isPrepared()); TestCase.assertTrue(statusStack2.isReleased()); } /** * A XAConnection is bound to different transactions having different XIDs. * * @throws Exception */ public void testDifferentTransactionBranches() throws Exception { IPhynixxXAResource<ITestConnection> xares = factory1.getXAResource(); XidWrapper xid1 = new XidWrapper(10, new byte[] { 0x10 }, new byte[] { 0x10 }); XidWrapper xid2 = new XidWrapper(10, new byte[] { 0x20 }, new byte[] { 0x20 }); xares.start(xid1, XAResource.TMNOFLAGS); ITestConnection con1 = xares.getXAConnection().getConnection(); con1.act(1); xares.end(xid1, XAResource.TMSUCCESS); xares.commit(xid1, true); xares.start(xid2, XAResource.TMNOFLAGS); ITestConnection con2 = xares.getXAConnection().getConnection(); con2.act(1); xares.end(xid2, XAResource.TMSUCCESS); xares.rollback(xid2); LOG.info(TestConnectionStatusManager.toDebugString()); TestStatusStack statusStack1 = TestConnectionStatusManager.getStatusStack(con1.getConnectionId()); TestCase.assertTrue(statusStack1 != null); TestCase.assertTrue(statusStack1.isCommitted()); // one-phase commit -> no prepare TestCase.assertTrue(!statusStack1.isPrepared()); TestCase.assertTrue(statusStack1.isReleased()); TestStatusStack statusStack2 = TestConnectionStatusManager.getStatusStack(con2.getConnectionId()); TestCase.assertTrue(statusStack2.isRolledback()); TestCase.assertTrue(statusStack2 != null); TestCase.assertTrue(statusStack2.isReleased()); } /** * A XAConnection is bound to different transactions having different XIDs. * A second TX is started bust the first TX is already bound to a global * transaction. * * This is prohibited by the JTA spec. * * @throws Exception */ public void testDifferentTransactionBranches2() throws Exception { IPhynixxXAResource<ITestConnection> xares = factory1.getXAResource(); XidWrapper xid1 = new XidWrapper(10, new byte[] { 0x10 }, new byte[] { 0x10 }); XidWrapper xid2 = new XidWrapper(10, new byte[] { 0x20 }, new byte[] { 0x20 }); xares.start(xid1, XAResource.TMNOFLAGS); ITestConnection con1 = xares.getXAConnection().getConnection(); con1.act(1); try { xares.start(xid2, XAResource.TMNOFLAGS); throw new AssertionFailedError("A XAResource may no be associated to 2 active Transactions"); } catch (Exception e) { } } /** * two different XAResourceProgressState Factories ( == resourceManagers) * instanciate two connections * If one of connection is closed, the 'commit' has to fail and the * XAResources have to be rollbacked * * @throws Exception */ /** * public void testHeuristicRollback() throws Exception { * * int freeConnection1 = factory1.freeConnectionSize(); int freeConnection2 * = factory2.freeConnectionSize(); * * IPhynixxXAConnection<ITestConnection> xaCon1 = * factory1.getXAConnection(); ITestConnection con1 = (ITestConnection) * xaCon1.getConnection(); Object conId1 = con1.getConnectionId(); * * IPhynixxXAConnection<ITestConnection> xaCon2 = * factory2.getXAConnection(); ITestConnection con2 = (ITestConnection) * xaCon2.getConnection(); Object conId2 = con2.getConnectionId(); * * log.debug("Con1 with ID=" + conId1); log.debug("Con2 with ID=" + conId2); * * TestCase.assertEquals(freeConnection1 - 1, * factory1.freeConnectionSize()); TestCase.assertEquals(freeConnection2 - * 1, factory2.freeConnectionSize()); * * try { this.getTransactionManager().begin(); * * // act transactional and enlist the current resource con1.act(1); * con2.act(1); * * // con1 is closed and the TX is marked as rollback con1.close(); con1 = * null; * * try { this.getTransactionManager().commit(); throw new * AssertionFailedError("Exception expected"); } catch (RollbackException e) * { } } finally { if (con1 != null) { con1.close(); } if (con2 != null) { * con2.close(); } } * * * TestStatusStack statusStack = * TestConnectionStatusManager.getStatusStack(conId1); * TestCase.assertTrue(statusStack != null); * TestCase.assertTrue(!statusStack.isCommitted()); * TestCase.assertTrue(!statusStack.isPrepared()); // rollback has not been * performed explicitly TestCase.assertTrue(!statusStack.isRollbacked()); * //TestCase.assertTrue(statusStack.isReleased()); * * * statusStack = TestConnectionStatusManager.getStatusStack(conId2); * TestCase.assertTrue(statusStack != null); * TestCase.assertTrue(!statusStack.isCommitted()); * TestCase.assertTrue(!statusStack.isPrepared()); * * // con1 is not any longer available, threrefore no rollback * TestCase.assertTrue(statusStack.isRollbacked()); * //TestCase.assertTrue(statusStack.isReleased()); } **/ /** * scenario: transaction timeout is set to 2 secs. The commit has to * fail,when the XAResource expired * * @throws Exception */ public void testTimeoutNotSupported() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); ITestConnection con = xaCon.getConnection(); XAResource xaresource = xaCon.getXAResource(); try { xaresource.setTransactionTimeout(2); throw new AssertionFailedError("Timeout not supported"); } catch (Exception e) { } finally { if (con != null) { con.close(); } } } /** * scenario: transaction timeout is set to 2 secs. The commit has to * fail,when the XAResource expired * * @throws Exception */ public void testTimeout1() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); ITestConnection con = xaCon.getConnection(); XAResource xaresource = xaCon.getXAResource(); try { xaresource.setTransactionTimeout(10); throw new AssertionFailedError("Timeout not supported"); } catch (Exception e) { } try { this.getTransactionManager().begin(); // act transactional and enlist the current resource con.act(1); // sleeping 7 secs to provoke timeout TestUtils.sleep(10 * 1000); try { this.getTransactionManager().commit(); throw new AssertionFailedError("RollbackedException expected"); } catch (javax.transaction.RollbackException e) { } } finally { if (con != null) { con.close(); } } } /** * scenario: transaction timeout is set to 2 secs. The call of a method of * the connection has to fail, when the XAResource expired * * @throws Exception */ public void testTimeout2() throws Exception { IPhynixxXAConnection<ITestConnection> xaCon = factory1.getXAConnection(); ITestConnection con = xaCon.getConnection(); XAResource xaresource = xaCon.getXAResource(); try { xaresource.setTransactionTimeout(2); throw new AssertionFailedError("Timeout not supported"); } catch (Exception e) { } try { this.getTransactionManager().begin(); // act transactional and enlist the current resource con.act(1); // sleeping 7 secs to provoke timeout TestUtils.sleep(3 * 1000); con.act(1); try { this.getTransactionManager().commit(); throw new AssertionFailedError("RollbackedException expected"); } catch (javax.transaction.RollbackException e) { } } finally { if (con != null) { con.close(); } } } }