HHH-9760 - TransactionImpl itself should not be throwing new TransactionExceptions

This commit is contained in:
Steve Ebersole 2015-05-08 13:03:42 -05:00
parent f8186e10c2
commit 88a6e4ba27
26 changed files with 142 additions and 126 deletions

View File

@ -506,9 +506,9 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
} }
@Override @Override
public void afterTransactionCompletion(boolean successful) { public void afterTransactionCompletion(boolean successful, boolean delayed) {
afterTransaction(); afterTransaction();
owner.afterTransactionCompletion( successful ); owner.afterTransactionCompletion( successful, delayed );
} }
@Override @Override
@ -541,7 +541,7 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
* JDK deserialization hook * JDK deserialization hook
* *
* @param ois The stream into which to write our state * @param ois The stream into which to write our state
* @param JdbcSessionOwner The Jdbc Session owner which owns the JdbcCoordinatorImpl to be deserialized. * @param owner The Jdbc Session owner which owns the JdbcCoordinatorImpl to be deserialized.
* *
* @return The deserialized JdbcCoordinatorImpl * @return The deserialized JdbcCoordinatorImpl
* *

View File

@ -80,9 +80,6 @@ public class TransactionImpl implements Transaction {
try { try {
this.transactionDriverControl.commit(); this.transactionDriverControl.commit();
} }
catch (Exception e) {
throw new TransactionException( "commit failed", e );
}
finally { finally {
invalidate(); invalidate();
} }
@ -100,9 +97,6 @@ public class TransactionImpl implements Transaction {
try { try {
this.transactionDriverControl.rollback(); this.transactionDriverControl.rollback();
} }
catch (Exception e) {
throw new TransactionException( "rollback failed", e );
}
finally { finally {
invalidate(); invalidate();
} }

View File

@ -47,6 +47,6 @@ public interface TransactionObserver {
* *
* @param successful Was the transaction successful? * @param successful Was the transaction successful?
*/ */
public void afterCompletion(boolean successful); public void afterCompletion(boolean successful, boolean delayed);
} }

View File

@ -335,9 +335,9 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
} }
@Override @Override
public void afterCompletion(boolean successful) { public void afterCompletion(boolean successful, boolean delayed) {
afterTransactionCompletion( successful ); afterTransactionCompletion( successful, delayed );
if ( isOpen() && autoCloseSessionEnabled ) { if ( !isClosed() && autoCloseSessionEnabled ) {
managedClose(); managedClose();
} }
} }
@ -2248,7 +2248,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
@Override @Override
public void beforeTransactionCompletion() { public void beforeTransactionCompletion() {
LOG.trace( "before transaction completion" ); LOG.tracef( "SessionImpl#beforeTransactionCompletion()" );
flushBeforeTransactionCompletion(); flushBeforeTransactionCompletion();
actionQueue.beforeTransactionCompletion(); actionQueue.beforeTransactionCompletion();
try { try {
@ -2260,9 +2260,8 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
} }
@Override @Override
public void afterTransactionCompletion(boolean successful) { public void afterTransactionCompletion(boolean successful, boolean delayed) {
LOG.tracef( "SessionImpl#afterTransactionCompletion(successful=%s, delayed=%s)", successful, delayed );
LOG.trace( "after transaction completion" );
persistenceContext.afterTransactionCompletion(); persistenceContext.afterTransactionCompletion();
actionQueue.afterTransactionCompletion( successful ); actionQueue.afterTransactionCompletion( successful );
@ -2280,8 +2279,10 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
LOG.exceptionInAfterTransactionCompletionInterceptor( t ); LOG.exceptionInAfterTransactionCompletionInterceptor( t );
} }
if ( shouldAutoClose() && !isClosed() ) { if ( !delayed ) {
managedClose(); if ( shouldAutoClose() && !isClosed() ) {
managedClose();
}
} }
if ( autoClear ) { if ( autoClear ) {

View File

@ -774,9 +774,8 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
} }
@Override @Override
public void afterTransactionCompletion(boolean successful) { public void afterTransactionCompletion(boolean successful, boolean delayed) {
if ( shouldAutoClose() if ( shouldAutoClose() && !isClosed() ) {
&& !isClosed() ) {
managedClose(); managedClose();
} }
} }

View File

@ -55,8 +55,9 @@ public interface JdbcSessionOwner {
* An after-completion callback to the owner. * An after-completion callback to the owner.
* *
* @param successful Was the transaction successful? * @param successful Was the transaction successful?
* @param delayed Is this a delayed after transaction completion call (aka after a timeout)?
*/ */
public void afterTransactionCompletion(boolean successful); public void afterTransactionCompletion(boolean successful, boolean delayed);
public void flushBeforeTransactionCompletion(); public void flushBeforeTransactionCompletion();
} }

View File

@ -171,9 +171,9 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
final int statusToSend = successful ? Status.STATUS_COMMITTED : Status.STATUS_UNKNOWN; final int statusToSend = successful ? Status.STATUS_COMMITTED : Status.STATUS_UNKNOWN;
synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( statusToSend ); synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( statusToSend );
transactionCoordinatorOwner.afterTransactionCompletion( successful ); transactionCoordinatorOwner.afterTransactionCompletion( successful, false );
for ( TransactionObserver observer : observers ) { for ( TransactionObserver observer : observers ) {
observer.afterCompletion( successful ); observer.afterCompletion( successful, false );
} }
invalidateDelegate(); invalidateDelegate();
} }

View File

@ -304,7 +304,8 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
public void beforeCompletion() { public void beforeCompletion() {
try { try {
transactionCoordinatorOwner.beforeTransactionCompletion(); transactionCoordinatorOwner.beforeTransactionCompletion();
}catch (Exception e){ }
catch (Exception e) {
physicalTransactionDelegate.markRollbackOnly(); physicalTransactionDelegate.markRollbackOnly();
} }
synchronizationRegistry.notifySynchronizationsBeforeTransactionCompletion(); synchronizationRegistry.notifySynchronizationsBeforeTransactionCompletion();
@ -315,19 +316,26 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
} }
@Override @Override
public void afterCompletion(boolean successful) { public void afterCompletion(boolean successful, boolean delayed) {
if ( !transactionCoordinatorOwner.isActive() ) {
return;
}
final int statusToSend = successful ? Status.STATUS_COMMITTED : Status.STATUS_UNKNOWN; final int statusToSend = successful ? Status.STATUS_COMMITTED : Status.STATUS_UNKNOWN;
synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( statusToSend ); synchronizationRegistry.notifySynchronizationsAfterTransactionCompletion( statusToSend );
transactionCoordinatorOwner.afterTransactionCompletion( successful ); // afterCompletionAction.doAction( this, statusToSend );
transactionCoordinatorOwner.afterTransactionCompletion( successful, delayed );
for ( TransactionObserver observer : observers ) { for ( TransactionObserver observer : observers ) {
observer.afterCompletion( successful ); observer.afterCompletion( successful, delayed );
} }
if ( physicalTransactionDelegate != null ) { if ( physicalTransactionDelegate != null ) {
physicalTransactionDelegate.invalidate(); physicalTransactionDelegate.invalidate();
} }
physicalTransactionDelegate = null; physicalTransactionDelegate = null;
synchronizationRegistered = false; synchronizationRegistered = false;
} }

View File

@ -68,13 +68,17 @@ public class SynchronizationCallbackCoordinatorNonTrackingImpl implements Synchr
@Override @Override
public void afterCompletion(int status) { public void afterCompletion(int status) {
doAfterCompletion( JtaStatusHelper.isCommitted( status ) ); log.tracef( "Synchronization coordinator: afterCompletion(status=%s)", status );
doAfterCompletion( JtaStatusHelper.isCommitted( status ), false );
} }
protected void doAfterCompletion(boolean successful) { protected void doAfterCompletion(boolean successful, boolean delayed) {
log.tracef( "Synchronization coordinator: doAfterCompletion(successful=%s, delayed=%s)", successful, delayed );
try { try {
target.afterCompletion( successful ); target.afterCompletion( successful, delayed );
}finally { }
finally {
reset(); reset();
} }
} }

View File

@ -39,13 +39,11 @@ import static org.hibernate.internal.CoreLogging.messageLogger;
public class SynchronizationCallbackCoordinatorTrackingImpl extends SynchronizationCallbackCoordinatorNonTrackingImpl { public class SynchronizationCallbackCoordinatorTrackingImpl extends SynchronizationCallbackCoordinatorNonTrackingImpl {
private static final CoreMessageLogger log = messageLogger( SynchronizationCallbackCoordinatorTrackingImpl.class ); private static final CoreMessageLogger log = messageLogger( SynchronizationCallbackCoordinatorTrackingImpl.class );
// magic number :( private volatile long registrationThreadId;
private static final long NO_THREAD_ID = Long.MIN_VALUE;
private volatile long registrationThreadId = NO_THREAD_ID;
private volatile boolean delayedCompletionHandling; private volatile boolean delayedCompletionHandling;
public SynchronizationCallbackCoordinatorTrackingImpl(SynchronizationCallbackTarget target) { public SynchronizationCallbackCoordinatorTrackingImpl(SynchronizationCallbackTarget target) {
// super ctor calls reset() followed by pulse()
super( target ); super( target );
} }
@ -57,13 +55,16 @@ public class SynchronizationCallbackCoordinatorTrackingImpl extends Synchronizat
// 2) after "after completion" handling is finished. // 2) after "after completion" handling is finished.
// //
// Here we use that to "clear out" all 'delayed after-completion" state. The registrationThreadId will // Here we use that to "clear out" all 'delayed after-completion" state. The registrationThreadId will
// "lazily" be re-populated on the next synchronizationRegistered call to allow for the potential of the next Session transaction // "lazily" be re-populated on the next synchronizationRegistered call to allow for the potential of the
// occurring on a different thread (though that transaction would need to completely operate on that thread). // next Session transaction occurring on a different thread (though that transaction would need to completely
// operate on that thread).
delayedCompletionHandling = false; delayedCompletionHandling = false;
} }
@Override @Override
public void afterCompletion(int status) { public void afterCompletion(int status) {
log.tracef( "Synchronization coordinator: afterCompletion(status=%s)", status );
// The whole concept of "tracking" comes down to this code block.. // The whole concept of "tracking" comes down to this code block..
// Essentially we need to see if we can process the callback immediately. So here we check whether the // Essentially we need to see if we can process the callback immediately. So here we check whether the
// current call is happening on the same thread as the thread under which we registered the Synchronization. // current call is happening on the same thread as the thread under which we registered the Synchronization.
@ -79,30 +80,29 @@ public class SynchronizationCallbackCoordinatorTrackingImpl extends Synchronizat
// check for it in SessionImpl. See HHH-7910. // check for it in SessionImpl. See HHH-7910.
delayedCompletionHandling = true; delayedCompletionHandling = true;
// todo : update code to use message logger log.rollbackFromBackgroundThread( status );
//log.rollbackFromBackgroundThread( status );
log.warn( "Rollback from background thread (update code to use message logger)" );
return; return;
} }
} }
// otherwise, do the callback immediately // otherwise, do the callback immediately
doAfterCompletion( JtaStatusHelper.isCommitted( status ) ); doAfterCompletion( JtaStatusHelper.isCommitted( status ), false );
} }
@Override @Override
public void synchronizationRegistered() { public void synchronizationRegistered() {
if ( registrationThreadId == NO_THREAD_ID ) { registrationThreadId = Thread.currentThread().getId();
registrationThreadId = Thread.currentThread().getId();
}
} }
@Override @Override
public void processAnyDelayedAfterCompletion() { public void processAnyDelayedAfterCompletion() {
if ( delayedCompletionHandling ) { if ( delayedCompletionHandling ) {
// false here because, as discussed above, the delayed logic should only ever occur during rollback
delayedCompletionHandling = false; delayedCompletionHandling = false;
doAfterCompletion( false );
// false here (rather than how we used to keep and check the status) because as discussed above
// the delayed logic should only ever occur during rollback
doAfterCompletion( false, true );
// NOTE : doAfterCompletion calls reset // NOTE : doAfterCompletion calls reset
throw new HibernateException( "Transaction was rolled back in a different thread!" ); throw new HibernateException( "Transaction was rolled back in a different thread!" );
} }

View File

@ -52,7 +52,7 @@ package org.hibernate.resource.transaction.backend.jta.internal.synchronization;
public interface SynchronizationCallbackTarget { public interface SynchronizationCallbackTarget {
/** /**
* Is the callback target still active? Generally this is checked by the caller prior to calling * Is the callback target still active? Generally this is checked by the caller prior to calling
* {@link #beforeCompletion()} or {@link #afterCompletion(boolean)} * {@link #beforeCompletion} or {@link #afterCompletion}
* *
* @return {@code true} indicates the target is active; {@code false} indicates it is not. * @return {@code true} indicates the target is active; {@code false} indicates it is not.
*/ */
@ -72,5 +72,5 @@ public interface SynchronizationCallbackTarget {
* *
* @see javax.transaction.Synchronization#afterCompletion * @see javax.transaction.Synchronization#afterCompletion
*/ */
void afterCompletion(boolean successful); void afterCompletion(boolean successful, boolean delayed);
} }

View File

@ -59,8 +59,9 @@ public interface TransactionCoordinatorOwner {
* An after-completion callback from the coordinator to its owner. * An after-completion callback from the coordinator to its owner.
* *
* @param successful Was the transaction successful? * @param successful Was the transaction successful?
* @param delayed Is this a delayed after transaction completion call (aka after a timeout)?
*/ */
public void afterTransactionCompletion(boolean successful); public void afterTransactionCompletion(boolean successful, boolean delayed);
public JdbcSessionOwner getJdbcSessionOwner(); public JdbcSessionOwner getJdbcSessionOwner();

View File

@ -291,8 +291,8 @@ public class EntityTest extends BaseNonConfigCoreFunctionalTestCase {
tx.commit(); tx.commit();
fail( "Optimistic locking should work" ); fail( "Optimistic locking should work" );
} }
catch (TransactionException e) { catch (StaleStateException expected) {
assertTrue( e.getCause() instanceof StaleStateException ); // expected exception
} }
finally { finally {
if ( tx != null ) { if ( tx != null ) {

View File

@ -120,7 +120,7 @@ public class ImmutableTest extends BaseCoreFunctionalTestCase {
fail(); fail();
} }
catch (HibernateException e) { catch (HibernateException e) {
assertTrue(e.getCause().getMessage().contains("changed an immutable collection instance")); assertTrue(e.getMessage().contains("changed an immutable collection instance"));
log.debug("success"); log.debug("success");
} }
s.close(); s.close();
@ -137,7 +137,7 @@ public class ImmutableTest extends BaseCoreFunctionalTestCase {
tx.commit(); tx.commit();
fail(); fail();
} catch (HibernateException e) { } catch (HibernateException e) {
assertTrue(e.getCause().getMessage().contains("changed an immutable collection instance")); assertTrue(e.getMessage().contains("changed an immutable collection instance"));
log.debug("success"); log.debug("success");
} }
s.close(); s.close();

View File

@ -195,8 +195,8 @@ public class MultiPathCascadeTest extends BaseCoreFunctionalTestCase {
s.getTransaction().commit(); s.getTransaction().commit();
fail( "should have thrown TransientObjectException" ); fail( "should have thrown TransientObjectException" );
} }
catch (TransactionException e) { catch (TransientObjectException expected) {
assertTrue( e.getCause() instanceof TransientObjectException ); // expected
} }
finally { finally {
s.getTransaction().rollback(); s.getTransaction().rollback();
@ -244,8 +244,8 @@ public class MultiPathCascadeTest extends BaseCoreFunctionalTestCase {
s.getTransaction().commit(); s.getTransaction().commit();
fail( "should have thrown TransientObjectException" ); fail( "should have thrown TransientObjectException" );
} }
catch (TransactionException e) { catch (TransientObjectException expected) {
assertTrue( e.getCause() instanceof TransientObjectException ); // expected
} }
finally { finally {
s.getTransaction().rollback(); s.getTransaction().rollback();
@ -293,8 +293,8 @@ public class MultiPathCascadeTest extends BaseCoreFunctionalTestCase {
s.getTransaction().commit(); s.getTransaction().commit();
fail( "should have thrown TransientObjectException" ); fail( "should have thrown TransientObjectException" );
} }
catch (TransactionException e) { catch (TransientObjectException expected) {
assertTrue( e.getCause() instanceof TransientObjectException ); // expected
} }
finally { finally {
s.getTransaction().rollback(); s.getTransaction().rollback();

View File

@ -33,15 +33,18 @@ public class JournalingTransactionObserver implements TransactionObserver {
private int beforeCompletions = 0; private int beforeCompletions = 0;
private int afterCompletions = 0; private int afterCompletions = 0;
@Override
public void afterBegin() { public void afterBegin() {
begins++; begins++;
} }
@Override
public void beforeCompletion() { public void beforeCompletion() {
beforeCompletions++; beforeCompletions++;
} }
public void afterCompletion(boolean successful) { @Override
public void afterCompletion(boolean successful, boolean delayed) {
afterCompletions++; afterCompletions++;
} }

View File

@ -935,11 +935,11 @@ public abstract class AbstractEntityWithManyToManyTest extends BaseCoreFunctiona
t.commit(); t.commit();
assertFalse( isContractVersioned ); assertFalse( isContractVersioned );
} }
catch (TransactionException e){ catch (StaleStateException ex) {
t.rollback(); t.rollback();
assertTrue( isContractVersioned ); assertTrue( isContractVersioned );
if ( ! sessionFactory().getSettings().isJdbcBatchVersionedData() ) { if ( ! sessionFactory().getSessionFactoryOptions().isJdbcBatchVersionedData() ) {
assertTrue( StaleObjectStateException.class.isInstance( e.getCause() ) ); assertTrue( StaleObjectStateException.class.isInstance( ex ) );
} }
} }
s.close(); s.close();

View File

@ -1162,11 +1162,11 @@ public abstract class AbstractEntityWithOneToManyTest extends BaseCoreFunctional
t.commit(); t.commit();
assertFalse( isContractVersioned ); assertFalse( isContractVersioned );
} }
catch (TransactionException ex) { catch (StaleStateException ex) {
t.rollback(); t.rollback();
assertTrue( isContractVersioned ); assertTrue( isContractVersioned );
if ( ! sessionFactory().getSettings().isJdbcBatchVersionedData() ) { if ( ! sessionFactory().getSessionFactoryOptions().isJdbcBatchVersionedData() ) {
assertTrue( StaleObjectStateException.class.isInstance( ex.getCause() ) ); assertTrue( StaleObjectStateException.class.isInstance( ex ) );
} }
} }
s.close(); s.close();

View File

@ -157,17 +157,11 @@ public class InterceptorTest extends BaseCoreFunctionalTestCase {
fail( "Transaction should have timed out" ); fail( "Transaction should have timed out" );
} }
catch (TransactionException e) { catch (TransactionException e) {
// Insure that the Exception is "transaction timeout expired" assertTrue(
String exceptionActual = e.getCause().toString(); "Transaction failed for the wrong reason. Expecting transaction timeout, but found [" +
String exceptionExpected = "org.hibernate.TransactionException: transaction timeout expired"; e.getMessage() + "]" ,
if ( !exceptionActual.contains( exceptionExpected ) ) { e.getMessage().contains( "transaction timeout expired" )
String msg = String.format( );
"Transaction failed for the wrong reason. Expected [%s] but received [%s]",
exceptionExpected, exceptionActual
);
fail( msg );
}
} }
} }

View File

@ -70,9 +70,8 @@ public class CascadeTest extends AbstractJPATest {
s.getTransaction().commit(); s.getTransaction().commit();
fail( "expecting TransientObjectException on flush" ); fail( "expecting TransientObjectException on flush" );
} }
catch (TransactionException te) { catch (TransientObjectException toe) {
assertTrue( te.getCause() instanceof TransientObjectException ); log.trace( "handled expected exception", toe );
log.trace( "handled expected exception", te );
s.getTransaction().rollback(); s.getTransaction().rollback();
} }
finally { finally {

View File

@ -26,18 +26,16 @@ package org.hibernate.test.ops;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import org.junit.Test;
import org.hibernate.PersistentObjectException; import org.hibernate.PersistentObjectException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.TransactionException;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
/** /**
@ -148,9 +146,8 @@ public class CreateTest extends AbstractOperationTestCase {
tx.commit(); tx.commit();
fail( "Expecting constraint failure" ); fail( "Expecting constraint failure" );
} }
catch (TransactionException te) { catch (ConstraintViolationException te) {
//verify that an exception is thrown! //verify that an exception is thrown!
assertTrue( te.getCause() instanceof ConstraintViolationException);
} }
tx.rollback(); tx.rollback();
s.close(); s.close();
@ -165,9 +162,8 @@ public class CreateTest extends AbstractOperationTestCase {
tx.commit(); tx.commit();
assertFalse(true); assertFalse(true);
} }
catch (TransactionException te) { catch (ConstraintViolationException te) {
//verify that an exception is thrown! //verify that an exception is thrown!
assertTrue( te.getCause() instanceof ConstraintViolationException);
} }
tx.rollback(); tx.rollback();
s.close(); s.close();

View File

@ -109,7 +109,7 @@ public class TransactionCoordinatorOwnerTestingImpl
} }
@Override @Override
public void afterTransactionCompletion(boolean successful) { public void afterTransactionCompletion(boolean successful, boolean delayed) {
log.debug( "#afterTransactionCompletion called" ); log.debug( "#afterTransactionCompletion called" );
if ( successful ) { if ( successful ) {
successfulCompletionCount++; successfulCompletionCount++;

View File

@ -90,7 +90,7 @@ public class TransactionCoordinatorOwnerTestingImpl implements TransactionCoordi
} }
@Override @Override
public void afterTransactionCompletion(boolean successful) { public void afterTransactionCompletion(boolean successful, boolean delayed) {
log.debug( "#afterTransactionCompletion called" ); log.debug( "#afterTransactionCompletion called" );
if ( successful ) { if ( successful ) {
successfulCompletionCount++; successfulCompletionCount++;

View File

@ -78,9 +78,8 @@ public class BeanValidationTest extends BaseEntityManagerFunctionalTestCase {
} }
catch ( RollbackException e ) { catch ( RollbackException e ) {
final Throwable cve = e.getCause(); final Throwable cve = e.getCause();
assertTrue( cve instanceof PersistenceException ); assertTrue( cve instanceof ConstraintViolationException );
assertTrue( cve.getCause() instanceof ConstraintViolationException ); assertEquals( 1, ( (ConstraintViolationException) cve ).getConstraintViolations().size() );
assertEquals( 1, ( (ConstraintViolationException) cve.getCause() ).getConstraintViolations().size() );
} }
em.close(); em.close();
} }

View File

@ -36,6 +36,7 @@ import org.hibernate.TransientPropertyValueException;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected; import org.hibernate.testing.FailureExpected;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -257,10 +258,8 @@ public class MultiCircleJpaCascadeTest extends BaseEntityManagerFunctionalTestCa
// because e is not in the process of being saved yet. // because e is not in the process of being saved yet.
// when HHH-6999 is fixed, this test should be changed to // when HHH-6999 is fixed, this test should be changed to
// check for g and f.g // check for g and f.g
assertTrue( ise.getCause() instanceof TransactionException ); //noinspection ThrowableResultOfMethodCallIgnored
Throwable cause = ise.getCause().getCause(); TransientPropertyValueException tpve = assertTyping( TransientPropertyValueException.class, ise.getCause() );
assertTrue( cause instanceof TransientPropertyValueException );
TransientPropertyValueException tpve = ( TransientPropertyValueException ) cause;
assertEquals( E.class.getName(), tpve.getTransientEntityName() ); assertEquals( E.class.getName(), tpve.getTransientEntityName() );
assertEquals( D.class.getName(), tpve.getPropertyOwnerEntityName() ); assertEquals( D.class.getName(), tpve.getPropertyOwnerEntityName() );
assertEquals( "e", tpve.getPropertyName() ); assertEquals( "e", tpve.getPropertyName() );

View File

@ -50,9 +50,9 @@ import static org.junit.Assert.fail;
public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManagerFunctionalTestCase { public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
protected void addConfigOptions(Map options) { protected void addConfigOptions(Map options) {
super.addConfigOptions(options); super.addConfigOptions( options );
TestingJtaBootstrap.prepare(options); TestingJtaBootstrap.prepare( options );
options.put(AvailableSettings.TRANSACTION_TYPE, "JTA"); options.put( AvailableSettings.TRANSACTION_TYPE, "JTA" );
} }
@Test @Test
@ -85,25 +85,32 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
em.joinTransaction(); em.joinTransaction();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().setRollbackOnly(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().setRollbackOnly();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
} catch (javax.persistence.PersistenceException e) { }
if (e.getCause() instanceof HibernateException && catch (javax.persistence.PersistenceException e) {
e.getCause().getMessage().equals("Transaction was rolled back in a different thread!")) { if ( e.getCause() instanceof HibernateException &&
e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) {
/** /**
* Save the exception for the main test thread to fail * Save the exception for the main test thread to fail
*/ */
e.printStackTrace(); // show the error first e.printStackTrace(); // show the error first
transactionRolledBackInDifferentThreadException[0] = (HibernateException) e.getCause(); transactionRolledBackInDifferentThreadException[0] = (HibernateException) e.getCause();
} }
} catch (RollbackException ignored) { }
catch (RollbackException ignored) {
// expected to see RollbackException: ARJUNA016053: Could not commit transaction. // expected to see RollbackException: ARJUNA016053: Could not commit transaction.
} catch (Throwable throwable) { }
catch (Throwable throwable) {
throwable.printStackTrace(); throwable.printStackTrace();
} finally { }
finally {
try { try {
if (TestingJtaPlatformImpl.INSTANCE.getTransactionManager().getStatus() != Status.STATUS_NO_TRANSACTION) if ( TestingJtaPlatformImpl.INSTANCE.getTransactionManager()
.getStatus() != Status.STATUS_NO_TRANSACTION ) {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
} catch (SystemException ignore) { }
}
catch (SystemException ignore) {
} }
} }
@ -123,45 +130,56 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
*/ */
em.joinTransaction(); em.joinTransaction();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
} catch (javax.persistence.PersistenceException e) { }
if (e.getCause() instanceof HibernateException && catch (javax.persistence.PersistenceException e) {
e.getCause().getMessage().equals("Transaction was rolled back in a different thread!")) { if ( e.getCause() instanceof HibernateException &&
e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) {
/** /**
* Save the exception for the main test thread to fail * Save the exception for the main test thread to fail
*/ */
e.printStackTrace(); // show the error first e.printStackTrace(); // show the error first
transactionRolledBackInDifferentThreadException[1] = (HibernateException) e.getCause(); transactionRolledBackInDifferentThreadException[1] = (HibernateException) e.getCause();
} }
} catch (Throwable throwable) { }
catch (Throwable throwable) {
throwable.printStackTrace(); throwable.printStackTrace();
} finally { }
finally {
try { try {
if (TestingJtaPlatformImpl.INSTANCE.getTransactionManager().getStatus() != Status.STATUS_NO_TRANSACTION) if ( TestingJtaPlatformImpl.INSTANCE.getTransactionManager()
.getStatus() != Status.STATUS_NO_TRANSACTION ) {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
} catch (SystemException ignore) { }
}
catch (SystemException ignore) {
} }
} }
} }
}; };
Thread thread = new Thread(run1, "test thread1"); Thread thread = new Thread( run1, "test thread1" );
thread.start(); thread.start();
thread.join(); thread.join();
Thread thread2 = new Thread(run2, "test thread2"); Thread thread2 = new Thread( run2, "test thread2" );
thread2.start(); thread2.start();
thread2.join(); thread2.join();
// show failure for exception caught in run2.run() // show failure for exception caught in run2.run()
if (transactionRolledBackInDifferentThreadException[0] != null if ( transactionRolledBackInDifferentThreadException[0] != null
|| transactionRolledBackInDifferentThreadException[1] != null) || transactionRolledBackInDifferentThreadException[1] != null )
{ {
fail("failure in test thread 1 = " + fail(
(transactionRolledBackInDifferentThreadException[0] != null ? transactionRolledBackInDifferentThreadException[0].getMessage() : "(none)") "failure in test thread 1 = " +
+ ", failure in test thread 2 = " + ( transactionRolledBackInDifferentThreadException[0] != null ?
(transactionRolledBackInDifferentThreadException[1] != null ? transactionRolledBackInDifferentThreadException[1].getMessage() : "(none)") transactionRolledBackInDifferentThreadException[0].getMessage() :
"(none)" )
+ ", failure in test thread 2 = " +
( transactionRolledBackInDifferentThreadException[1] != null ?
transactionRolledBackInDifferentThreadException[1].getMessage() :
"(none)" )
); );
} }
@ -171,7 +189,7 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
@Override @Override
public Class[] getAnnotatedClasses() { public Class[] getAnnotatedClasses() {
return new Class[]{ return new Class[] {
}; };
} }