HHH-9760 - TransactionImpl itself should not be throwing new TransactionExceptions
This commit is contained in:
parent
f8186e10c2
commit
88a6e4ba27
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() );
|
||||||
|
|
|
@ -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[] {
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue