/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.resource.transaction.jta; import javax.transaction.Status; import javax.transaction.SystemException; import javax.transaction.TransactionManager; import org.hibernate.TransactionException; import org.hibernate.resource.transaction.TransactionRequiredForJoinException; import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl; import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl; import org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorTrackingImpl; import org.hibernate.resource.transaction.spi.TransactionStatus; import org.hibernate.test.resource.common.SynchronizationCollectorImpl; import org.hibernate.test.resource.common.SynchronizationErrorImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Steve Ebersole */ public abstract class AbstractBasicJtaTestScenarios { private final TransactionCoordinatorOwnerTestingImpl owner = new TransactionCoordinatorOwnerTestingImpl(); private JtaTransactionCoordinatorBuilderImpl transactionCoordinatorBuilder = new JtaTransactionCoordinatorBuilderImpl(); protected abstract boolean preferUserTransactions(); public JtaTransactionCoordinatorImpl buildTransactionCoordinator(boolean autoJoin) { return new JtaTransactionCoordinatorImpl( transactionCoordinatorBuilder, owner, autoJoin, JtaPlatformStandardTestingImpl.INSTANCE, preferUserTransactions(), false ); } @Before @After public void resetJtaPlatform() throws SystemException { // make sure the JTA platform is reset back to no active transactions before and after each test JtaPlatformStandardTestingImpl.INSTANCE.reset(); } @Test public void basicBmtUsageTest() throws Exception { final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( true ); // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); // begin the transaction transactionCoordinator.getTransactionDriverControl().begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction transactionCoordinator.getTransactionDriverControl().commit(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test public void rollbackBmtUsageTest() throws Exception { final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( true ); // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); // begin the transaction transactionCoordinator.getTransactionDriverControl().begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // rollback the transaction transactionCoordinator.getTransactionDriverControl().rollback(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 0, localSync.getBeforeCompletionCount() ); assertEquals( 0, localSync.getSuccessfulCompletionCount() ); assertEquals( 1, localSync.getFailedCompletionCount() ); } @Test public void basicCmtUsageTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // begin the transaction tm.begin(); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( true ); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); // NOTE : because of auto-join assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction tm.commit(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test public void basicCmtUsageWithPulseTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( true ); // begin the transaction tm.begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); transactionCoordinator.pulse(); // NOTE : because of auto-join assertTrue( transactionCoordinator.isSynchronizationRegistered() ); transactionCoordinator.pulse(); assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction tm.commit(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test public void rollbackCmtUsageTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // begin the transaction tm.begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( true ); // NOTE : because of auto-join assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // rollback the transaction tm.rollback(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 0, localSync.getBeforeCompletionCount() ); assertEquals( 0, localSync.getSuccessfulCompletionCount() ); assertEquals( 1, localSync.getFailedCompletionCount() ); } @Test public void explicitJoiningTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( false ); // begin the transaction tm.begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); // no auto-join now assertFalse( transactionCoordinator.isSynchronizationRegistered() ); transactionCoordinator.explicitJoin(); assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction tm.commit(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test public void jpaExplicitJoiningTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // begin the transaction tm.begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( false ); // no auto-join now assertFalse( transactionCoordinator.isSynchronizationRegistered() ); transactionCoordinator.explicitJoin(); assertTrue( transactionCoordinator.isSynchronizationRegistered() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction tm.commit(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test public void assureMultipleJoinCallsNoOp() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // begin the transaction tm.begin(); assertEquals( Status.STATUS_ACTIVE, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( false ); // no auto-join now assertFalse( transactionCoordinator.isJoined() ); transactionCoordinator.explicitJoin(); assertTrue( transactionCoordinator.isJoined() ); transactionCoordinator.explicitJoin(); transactionCoordinator.explicitJoin(); transactionCoordinator.explicitJoin(); transactionCoordinator.explicitJoin(); assertTrue( transactionCoordinator.isJoined() ); // create and add a local Synchronization SynchronizationCollectorImpl localSync = new SynchronizationCollectorImpl(); transactionCoordinator.getLocalSynchronizations().registerSynchronization( localSync ); // commit the transaction tm.commit(); // post conditions assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isSynchronizationRegistered() ); assertEquals( 1, localSync.getBeforeCompletionCount() ); assertEquals( 1, localSync.getSuccessfulCompletionCount() ); assertEquals( 0, localSync.getFailedCompletionCount() ); } @Test @SuppressWarnings("EmptyCatchBlock") public void explicitJoinOutsideTxnTest() throws Exception { // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); final JtaTransactionCoordinatorImpl transactionCoordinator = buildTransactionCoordinator( false ); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // try to force a join, should fail... try { transactionCoordinator.explicitJoin(); fail( "Expecting explicitJoin() call outside of transaction to fail" ); } catch (TransactionRequiredForJoinException expected) { } } @Test public void basicThreadCheckingUsage() throws Exception { JtaTransactionCoordinatorImpl transactionCoordinator = new JtaTransactionCoordinatorImpl( transactionCoordinatorBuilder, owner, true, JtaPlatformStandardTestingImpl.INSTANCE, preferUserTransactions(), true ); // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); // begin the transaction tm.begin(); transactionCoordinator.explicitJoin(); assertEquals( SynchronizationCallbackCoordinatorTrackingImpl.class, transactionCoordinator.getSynchronizationCallbackCoordinator().getClass() ); tm.commit(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertFalse( transactionCoordinator.isJoined() ); tm.begin(); transactionCoordinator.explicitJoin(); assertEquals( SynchronizationCallbackCoordinatorTrackingImpl.class, transactionCoordinator.getSynchronizationCallbackCoordinator().getClass() ); tm.rollback(); } @Test @SuppressWarnings("EmptyCatchBlock") public void testMarkRollbackOnly() throws Exception { JtaTransactionCoordinatorImpl transactionCoordinator = new JtaTransactionCoordinatorImpl( transactionCoordinatorBuilder, owner, true, JtaPlatformStandardTestingImpl.INSTANCE, preferUserTransactions(), true ); // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertEquals( TransactionStatus.NOT_ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); transactionCoordinator.getTransactionDriverControl().begin(); assertEquals( TransactionStatus.ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); transactionCoordinator.getTransactionDriverControl().markRollbackOnly(); assertEquals( TransactionStatus.MARKED_ROLLBACK, transactionCoordinator.getTransactionDriverControl().getStatus() ); try { transactionCoordinator.getTransactionDriverControl().commit(); } catch (TransactionException expected) { } finally { assertEquals( TransactionStatus.NOT_ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); } } @Test @SuppressWarnings("EmptyCatchBlock") public void testSynchronizationFailure() throws Exception { JtaTransactionCoordinatorImpl transactionCoordinator = new JtaTransactionCoordinatorImpl( transactionCoordinatorBuilder, owner, true, JtaPlatformStandardTestingImpl.INSTANCE, preferUserTransactions(), true ); // pre conditions final TransactionManager tm = JtaPlatformStandardTestingImpl.INSTANCE.transactionManager(); assertEquals( Status.STATUS_NO_TRANSACTION, tm.getStatus() ); assertEquals( TransactionStatus.NOT_ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); transactionCoordinator.getLocalSynchronizations().registerSynchronization( SynchronizationErrorImpl.forBefore() ); transactionCoordinator.getTransactionDriverControl().begin(); assertEquals( TransactionStatus.ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); try { transactionCoordinator.getTransactionDriverControl().commit(); } catch (Exception expected) { } finally { assertEquals( TransactionStatus.NOT_ACTIVE, transactionCoordinator.getTransactionDriverControl().getStatus() ); } } }