improve exception messages and logging related to tx management

along with some minor aesthetic code cleanups
This commit is contained in:
Gavin King 2024-11-20 10:50:01 +01:00
parent 47f1a1207a
commit 453f0ff074
11 changed files with 161 additions and 196 deletions

View File

@ -69,9 +69,13 @@ public interface Transaction extends EntityTransaction {
/** /**
* Attempt to mark the underlying transaction for rollback only. * Attempt to mark the underlying transaction for rollback only.
* <p>
* Unlike {@link #setRollbackOnly()}, which is specified by JPA
* to throw when the transaction is inactive, this operation may
* be called on an inactive transaction, in which case it has no
* effect.
*
* @see #setRollbackOnly()
*/ */
default void markRollbackOnly() { void markRollbackOnly();
setRollbackOnly();
}
} }

View File

@ -12,7 +12,6 @@ import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.internal.AbstractSharedSessionContract; import org.hibernate.internal.AbstractSharedSessionContract;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.resource.transaction.spi.TransactionCoordinator; import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionStatus; import org.hibernate.resource.transaction.spi.TransactionStatus;
@ -28,7 +27,7 @@ public class TransactionImpl implements TransactionImplementor {
private static final Logger LOG = CoreLogging.logger( TransactionImpl.class ); private static final Logger LOG = CoreLogging.logger( TransactionImpl.class );
private final TransactionCoordinator transactionCoordinator; private final TransactionCoordinator transactionCoordinator;
private final JpaCompliance jpaCompliance; private final boolean jpaCompliance;
private final AbstractSharedSessionContract session; private final AbstractSharedSessionContract session;
private TransactionDriver transactionDriverControl; private TransactionDriver transactionDriverControl;
@ -37,7 +36,9 @@ public class TransactionImpl implements TransactionImplementor {
TransactionCoordinator transactionCoordinator, TransactionCoordinator transactionCoordinator,
AbstractSharedSessionContract session) { AbstractSharedSessionContract session) {
this.transactionCoordinator = transactionCoordinator; this.transactionCoordinator = transactionCoordinator;
this.jpaCompliance = session.getFactory().getSessionFactoryOptions().getJpaCompliance(); this.jpaCompliance =
session.getFactory().getSessionFactoryOptions().getJpaCompliance()
.isJpaTransactionComplianceEnabled();
this.session = session; this.session = session;
if ( session.isOpen() && transactionCoordinator.isActive() ) { if ( session.isOpen() && transactionCoordinator.isActive() ) {
@ -47,11 +48,8 @@ public class TransactionImpl implements TransactionImplementor {
LOG.debug( "TransactionImpl created on closed Session/EntityManager" ); LOG.debug( "TransactionImpl created on closed Session/EntityManager" );
} }
if ( LOG.isDebugEnabled() ) { if ( LOG.isDebugEnabled() && jpaCompliance ) {
LOG.debugf( LOG.debugf( "TransactionImpl created in JPA compliant mode" );
"On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == %s",
jpaCompliance.isJpaTransactionComplianceEnabled()
);
} }
} }
@ -65,78 +63,66 @@ public class TransactionImpl implements TransactionImplementor {
transactionDriverControl = transactionCoordinator.getTransactionDriverControl(); transactionDriverControl = transactionCoordinator.getTransactionDriverControl();
} }
// per-JPA
if ( isActive() ) { if ( isActive() ) {
if ( jpaCompliance.isJpaTransactionComplianceEnabled() if ( jpaCompliance ) {
|| !transactionCoordinator.getTransactionCoordinatorBuilder().isJta() ) { throw new IllegalStateException( "Transaction already active (in JPA compliant mode)" );
throw new IllegalStateException( "Transaction already active" );
} }
else { else if ( !transactionCoordinator.getTransactionCoordinatorBuilder().isJta() ) {
return; throw new IllegalStateException( "Resource-local transaction already active" );
} }
} }
else {
LOG.debug( "begin" ); LOG.debug( "begin transaction" );
transactionDriverControl.begin();
this.transactionDriverControl.begin(); }
} }
@Override @Override
public void commit() { public void commit() {
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl
// the boolean passed to isActive indicates whether MARKED_ROLLBACK should
// be considered active
if ( !isActive( true ) ) { if ( !isActive( true ) ) {
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl // we have a transaction that is inactive and has not been marked for rollback only
// the boolean passed to isActive indicates whether MARKED_ROLLBACK should be
// considered active
//
// essentially here we have a transaction that is not active and
// has not been marked for rollback only
throw new IllegalStateException( "Transaction not successfully started" ); throw new IllegalStateException( "Transaction not successfully started" );
} }
else {
LOG.debug( "committing" ); LOG.debug( "committing transaction" );
try {
try { internalGetTransactionDriverControl().commit();
internalGetTransactionDriverControl().commit(); }
} catch (RuntimeException e) {
catch (RuntimeException e) { throw session.getExceptionConverter().convertCommitException( e );
throw session.getExceptionConverter().convertCommitException( e ); }
} }
} }
public TransactionDriver internalGetTransactionDriverControl() { public TransactionDriver internalGetTransactionDriverControl() {
// NOTE here to help be a more descriptive NullPointerException // NOTE here to help be a more descriptive NullPointerException
if ( this.transactionDriverControl == null ) { if ( transactionDriverControl == null ) {
throw new IllegalStateException( "Transaction was not properly begun/started" ); throw new IllegalStateException( "Transaction was not properly begun/started" );
} }
return this.transactionDriverControl; else {
return transactionDriverControl;
}
} }
@Override @Override
public void rollback() { public void rollback() {
if ( !isActive() ) { if ( !isActive() && jpaCompliance ) {
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) { throw new IllegalStateException( "rollback() called on inactive transaction (in JPA compliant mode)" );
throw new IllegalStateException(
"JPA compliance dictates throwing IllegalStateException when #rollback " +
"is called on non-active transaction"
);
}
} }
TransactionStatus status = getStatus(); final TransactionStatus status = getStatus();
if ( status == TransactionStatus.ROLLED_BACK || status == TransactionStatus.NOT_ACTIVE ) { if ( status == TransactionStatus.ROLLED_BACK || status == TransactionStatus.NOT_ACTIVE ) {
// Allow rollback() calls on completed transactions, just no-op. // allow rollback() on completed transaction as noop
LOG.debug( "rollback() called on an inactive transaction" ); LOG.debug( "rollback() called on an inactive transaction" );
return;
} }
else if ( !status.canRollback() ) {
if ( !status.canRollback() ) { throw new TransactionException( "Cannot roll back transaction in current status [" + status.name() + "]" );
throw new TransactionException( "Cannot rollback transaction in current status [" + status.name() + "]" );
} }
else if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
LOG.debug( "rolling back" ); LOG.debug( "rolling back transaction" );
if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {
internalGetTransactionDriverControl().rollback(); internalGetTransactionDriverControl().rollback();
} }
} }
@ -176,55 +162,50 @@ public class TransactionImpl implements TransactionImplementor {
@Override @Override
public void registerSynchronization(Synchronization synchronization) throws HibernateException { public void registerSynchronization(Synchronization synchronization) throws HibernateException {
this.transactionCoordinator.getLocalSynchronizations().registerSynchronization( synchronization ); transactionCoordinator.getLocalSynchronizations().registerSynchronization( synchronization );
} }
@Override @Override
public void setTimeout(int seconds) { public void setTimeout(int seconds) {
this.transactionCoordinator.setTimeOut( seconds ); transactionCoordinator.setTimeOut( seconds );
} }
@Override @Override
public void setTimeout(@Nullable Integer seconds) { public void setTimeout(@Nullable Integer seconds) {
this.transactionCoordinator.setTimeOut( seconds == null ? -1 : seconds ); transactionCoordinator.setTimeOut( seconds == null ? -1 : seconds );
} }
@Override @Override
public @Nullable Integer getTimeout() { public @Nullable Integer getTimeout() {
final int timeOut = this.transactionCoordinator.getTimeOut(); final int timeout = transactionCoordinator.getTimeOut();
if ( timeOut == -1 ) { return timeout == -1 ? null : timeout;
return null;
}
return timeOut;
} }
@Override @Override
public void markRollbackOnly() { public void markRollbackOnly() {
// this is the Hibernate-specific API, whereas #setRollbackOnly is the // this is the Hibernate-specific API, whereas setRollbackOnly is the
// JPA-defined API. In our opinion it is much more user-friendly to // JPA-defined API. In our opinion it is much more user-friendly to
// always allow user/integration to indicate that the transaction // always allow user/integration to indicate that the transaction
// should not be allowed to commit. // should not be allowed to commit.
// //
// However.. should only "do something" on an active transaction
if ( isActive() ) { if ( isActive() ) {
internalGetTransactionDriverControl().markRollbackOnly(); internalGetTransactionDriverControl().markRollbackOnly();
} }
// else noop for an inactive transaction
} }
@Override @Override
public void setRollbackOnly() { public void setRollbackOnly() {
if ( !isActive() ) { if ( !isActive() ) {
// Since this is the JPA-defined one, we make sure the txn is active first if ( jpaCompliance ) {
// so long as compliance (JpaCompliance) has not been defined to disable // This is the JPA-defined version of this operation,
// that check - making this active more like Hibernate's #markRollbackOnly // so we must check that the transaction is active
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) { throw new IllegalStateException( "setRollbackOnly() called on inactive transaction (in JPA compliant mode)" );
throw new IllegalStateException(
"JPA compliance dictates throwing IllegalStateException when #setRollbackOnly " +
"is called on non-active transaction"
);
} }
else { else {
LOG.debug( "#setRollbackOnly called on a not-active transaction" ); // JpaCompliance disables the check, so this method
// is equivalent our native markRollbackOnly()
LOG.debug( "setRollbackOnly() called on a inactive transaction" );
} }
} }
else { else {
@ -234,16 +215,12 @@ public class TransactionImpl implements TransactionImplementor {
@Override @Override
public boolean getRollbackOnly() { public boolean getRollbackOnly() {
if ( !isActive() ) { if ( jpaCompliance && !isActive() ) {
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) { throw new IllegalStateException( "getRollbackOnly() called on inactive transaction (in JPA compliant mode)" );
throw new IllegalStateException( }
"JPA compliance dictates throwing IllegalStateException when #getRollbackOnly " + else {
"is called on non-active transaction" return getStatus() == TransactionStatus.MARKED_ROLLBACK;
);
}
} }
return getStatus() == TransactionStatus.MARKED_ROLLBACK;
} }
protected boolean allowFailedCommitToPhysicallyRollback() { protected boolean allowFailedCommitToPhysicallyRollback() {

View File

@ -63,7 +63,7 @@ public class ExceptionConverterImpl implements ExceptionConverter {
catch (Exception re) { catch (Exception re) {
//swallow //swallow
} }
return new RollbackException( "Error while committing the transaction", return new RollbackException( "Error while committing the transaction [" + exception.getMessage() + "]",
exception instanceof HibernateException hibernateException exception instanceof HibernateException hibernateException
? convert( hibernateException ) ? convert( hibernateException )
: exception ); : exception );

View File

@ -358,18 +358,16 @@ public final class FastSessionServices {
private static CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) { private static CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE );
if ( cacheRetrieveMode == null ) { return cacheRetrieveMode == null
return (CacheRetrieveMode) settings.get( JAKARTA_SHARED_CACHE_RETRIEVE_MODE ); ? (CacheRetrieveMode) settings.get( JAKARTA_SHARED_CACHE_RETRIEVE_MODE )
} : cacheRetrieveMode;
return cacheRetrieveMode;
} }
private static CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) { private static CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE ); final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE );
if ( cacheStoreMode == null ) { return cacheStoreMode == null
return ( CacheStoreMode ) settings.get( JAKARTA_SHARED_CACHE_STORE_MODE ); ? (CacheStoreMode) settings.get( JAKARTA_SHARED_CACHE_STORE_MODE )
} : cacheStoreMode;
return cacheStoreMode;
} }
public JdbcValuesMappingProducerProvider getJdbcValuesMappingProducerProvider() { public JdbcValuesMappingProducerProvider getJdbcValuesMappingProducerProvider() {

View File

@ -169,15 +169,15 @@ public class MutableJpaComplianceImpl implements MutableJpaCompliance {
@Override @Override
public JpaCompliance immutableCopy() { public JpaCompliance immutableCopy() {
JpaComplianceImpl.JpaComplianceBuilder builder = new JpaComplianceImpl.JpaComplianceBuilder(); return new JpaComplianceImpl.JpaComplianceBuilder()
builder = builder.setProxyCompliance( proxyCompliance ) .setProxyCompliance( proxyCompliance )
.setOrderByMappingCompliance( orderByMappingCompliance ) .setOrderByMappingCompliance( orderByMappingCompliance )
.setGlobalGeneratorNameCompliance( generatorNameScopeCompliance ) .setGlobalGeneratorNameCompliance( generatorNameScopeCompliance )
.setQueryCompliance( queryCompliance ) .setQueryCompliance( queryCompliance )
.setTransactionCompliance( transactionCompliance ) .setTransactionCompliance( transactionCompliance )
.setClosedCompliance( closedCompliance ) .setClosedCompliance( closedCompliance )
.setCachingCompliance( cachingCompliance ) .setCachingCompliance( cachingCompliance )
.setLoadByIdCompliance( loadByIdCompliance ); .setLoadByIdCompliance( loadByIdCompliance )
return builder.createJpaCompliance(); .createJpaCompliance();
} }
} }

View File

@ -148,7 +148,6 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
transactionCoordinatorOwner.setTransactionTimeOut( timeOut ); transactionCoordinatorOwner.setTransactionTimeOut( timeOut );
} }
// report entering into a "transactional context" // report entering into a "transactional context"
transactionCoordinatorOwner.startTransactionBoundary(); transactionCoordinatorOwner.startTransactionBoundary();
@ -184,7 +183,6 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
log.tracef( "ResourceLocalTransactionCoordinatorImpl#afterCompletionCallback(%s)", successful ); log.tracef( "ResourceLocalTransactionCoordinatorImpl#afterCompletionCallback(%s)", successful );
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, false ); transactionCoordinatorOwner.afterTransactionCompletion( successful, false );
for ( TransactionObserver observer : observers() ) { for ( TransactionObserver observer : observers() ) {
observer.afterCompletion( successful, false ); observer.afterCompletion( successful, false );
@ -216,7 +214,6 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
private boolean rollbackOnly = false; private boolean rollbackOnly = false;
public TransactionDriverControlImpl(JdbcResourceTransaction jdbcResourceTransaction) { public TransactionDriverControlImpl(JdbcResourceTransaction jdbcResourceTransaction) {
super();
this.jdbcResourceTransaction = jdbcResourceTransaction; this.jdbcResourceTransaction = jdbcResourceTransaction;
} }
@ -227,7 +224,6 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
@Override @Override
public void begin() { public void begin() {
errorIfInvalid(); errorIfInvalid();
jdbcResourceTransaction.begin(); jdbcResourceTransaction.begin();
JdbcResourceLocalTransactionCoordinatorImpl.this.afterBeginCallback(); JdbcResourceLocalTransactionCoordinatorImpl.this.afterBeginCallback();
} }
@ -242,30 +238,13 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
public void commit() { public void commit() {
try { try {
if ( rollbackOnly ) { if ( rollbackOnly ) {
log.debug( "On commit, transaction was marked for roll-back only, rolling back" ); commitRollbackOnly();
}
try { else {
rollback(); JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback();
jdbcResourceTransaction.commit();
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) { JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true );
log.debug( "Throwing RollbackException on roll-back of transaction marked rollback-only on commit" );
throw new RollbackException( "Transaction was marked for rollback-only" );
}
return;
}
catch (RollbackException e) {
throw e;
}
catch (RuntimeException e) {
log.debug( "Encountered failure rolling back failed commit", e );
throw e;
}
} }
JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback();
jdbcResourceTransaction.commit();
JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true );
} }
catch (RollbackException e) { catch (RollbackException e) {
throw e; throw e;
@ -281,6 +260,23 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
} }
} }
private void commitRollbackOnly() {
log.debug( "On commit, transaction was marked for roll-back only, rolling back" );
try {
rollback();
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
throw new RollbackException( "Transaction was marked for rollback-only" );
}
}
catch (RollbackException e) {
throw e;
}
catch (RuntimeException e) {
log.debug( "Encountered failure rolling back failed commit", e );
throw e;
}
}
@Override @Override
public void rollback() { public void rollback() {
try { try {
@ -292,8 +288,6 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
finally { finally {
rollbackOnly = false; rollbackOnly = false;
} }
// no-op otherwise.
} }
@Override @Override
@ -305,12 +299,9 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
public void markRollbackOnly() { public void markRollbackOnly() {
if ( getStatus() != TransactionStatus.ROLLED_BACK ) { if ( getStatus() != TransactionStatus.ROLLED_BACK ) {
if ( log.isDebugEnabled() ) { if ( log.isDebugEnabled() ) {
log.debug( log.debug( "JDBC transaction marked for rollback-only (exception provided for stack trace)",
"JDBC transaction marked for rollback-only (exception provided for stack trace)", new Exception( "exception just for purpose of providing stack trace" ) );
new Exception( "exception just for purpose of providing stack trace" )
);
} }
rollbackOnly = true; rollbackOnly = true;
} }
} }

View File

@ -136,21 +136,15 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
@Override @Override
public void pulse() { public void pulse() {
if ( !autoJoinTransactions ) { if ( autoJoinTransactions && !synchronizationRegistered ) {
return; // Can we register a synchronization according to the JtaPlatform?
if ( !jtaPlatform.canRegisterSynchronization() ) {
log.trace( "JTA platform says we cannot currently register synchronization; skipping" );
}
else {
joinJtaTransaction();
}
} }
if ( synchronizationRegistered ) {
return;
}
// Can we register a synchronization according to the JtaPlatform?
if ( !jtaPlatform.canRegisterSynchronization() ) {
log.trace( "JTA platform says we cannot currently register synchronization; skipping" );
return;
}
joinJtaTransaction();
} }
/** /**
@ -158,33 +152,30 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
* RegisteredSynchronization with the JTA system * RegisteredSynchronization with the JTA system
*/ */
private void joinJtaTransaction() { private void joinJtaTransaction() {
if ( synchronizationRegistered ) { if ( !synchronizationRegistered ) {
return; jtaPlatform.registerSynchronization(
new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) );
getSynchronizationCallbackCoordinator().synchronizationRegistered();
synchronizationRegistered = true;
log.debug( "Hibernate RegisteredSynchronization successfully registered with JTA platform" );
// report entering into a "transactional context"
getTransactionCoordinatorOwner().startTransactionBoundary();
} }
jtaPlatform.registerSynchronization( new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) );
getSynchronizationCallbackCoordinator().synchronizationRegistered();
synchronizationRegistered = true;
log.debug( "Hibernate RegisteredSynchronization successfully registered with JTA platform" );
// report entering into a "transactional context"
getTransactionCoordinatorOwner().startTransactionBoundary();
} }
@Override @Override
public void explicitJoin() { public void explicitJoin() {
if ( synchronizationRegistered ) { if ( synchronizationRegistered ) {
log.debug( "JTA transaction was already joined (RegisteredSynchronization already registered)" ); log.debug( "JTA transaction was already joined (RegisteredSynchronization already registered)" );
return;
} }
else {
if ( getTransactionDriverControl().getStatus() != ACTIVE ) { if ( getTransactionDriverControl().getStatus() != ACTIVE ) {
throw new TransactionRequiredForJoinException( throw new TransactionRequiredForJoinException(
"Explicitly joining a JTA transaction requires a JTA transaction be currently active" "Explicitly joining a JTA transaction requires a JTA transaction be currently active"
); );
}
joinJtaTransaction();
} }
joinJtaTransaction();
} }
@Override @Override
@ -204,7 +195,7 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
} }
public TransactionCoordinatorOwner getTransactionCoordinatorOwner(){ public TransactionCoordinatorOwner getTransactionCoordinatorOwner(){
return this.transactionCoordinatorOwner; return transactionCoordinatorOwner;
} }
@Override @Override
@ -221,32 +212,36 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
} }
private TransactionDriverControlImpl makePhysicalTransactionDelegate() { private TransactionDriverControlImpl makePhysicalTransactionDelegate() {
JtaTransactionAdapter adapter; final JtaTransactionAdapter adapter =
preferUserTransactions
if ( preferUserTransactions ) { ? getTransactionAdapterPreferringUserTransaction()
adapter = makeUserTransactionAdapter(); : getTransactionAdapterPreferringTransactionManager();
if ( adapter == null ) {
log.debug( "Unable to access UserTransaction, attempting to use TransactionManager instead" );
adapter = makeTransactionManagerAdapter();
}
}
else {
adapter = makeTransactionManagerAdapter();
if ( adapter == null ) {
log.debug( "Unable to access TransactionManager, attempting to use UserTransaction instead" );
adapter = makeUserTransactionAdapter();
}
}
if ( adapter == null ) { if ( adapter == null ) {
throw new JtaPlatformInaccessibleException( throw new JtaPlatformInaccessibleException(
"Unable to access TransactionManager or UserTransaction to make physical transaction delegate" "Unable to access TransactionManager or UserTransaction to make physical transaction delegate"
); );
} }
else {
return new TransactionDriverControlImpl( adapter );
}
}
return new TransactionDriverControlImpl( adapter ); private JtaTransactionAdapter getTransactionAdapterPreferringTransactionManager() {
final JtaTransactionAdapter adapter = makeTransactionManagerAdapter();
if ( adapter == null ) {
log.debug( "Unable to access TransactionManager, attempting to use UserTransaction instead" );
return makeUserTransactionAdapter();
}
return adapter;
}
private JtaTransactionAdapter getTransactionAdapterPreferringUserTransaction() {
final JtaTransactionAdapter adapter = makeUserTransactionAdapter();
if ( adapter == null ) {
log.debug( "Unable to access UserTransaction, attempting to use TransactionManager instead" );
return makeTransactionManagerAdapter();
}
return adapter;
} }
private JtaTransactionAdapter makeUserTransactionAdapter() { private JtaTransactionAdapter makeUserTransactionAdapter() {
@ -254,6 +249,7 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
final UserTransaction userTransaction = jtaPlatform.retrieveUserTransaction(); final UserTransaction userTransaction = jtaPlatform.retrieveUserTransaction();
if ( userTransaction == null ) { if ( userTransaction == null ) {
log.debug( "JtaPlatform#retrieveUserTransaction returned null" ); log.debug( "JtaPlatform#retrieveUserTransaction returned null" );
return null;
} }
else { else {
return new JtaTransactionAdapterUserTransactionImpl( userTransaction ); return new JtaTransactionAdapterUserTransactionImpl( userTransaction );
@ -261,9 +257,8 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
} }
catch ( Exception exception ) { catch ( Exception exception ) {
log.debugf( "JtaPlatform#retrieveUserTransaction threw an exception [%s]", exception.getMessage() ); log.debugf( "JtaPlatform#retrieveUserTransaction threw an exception [%s]", exception.getMessage() );
return null;
} }
return null;
} }
private JtaTransactionAdapter makeTransactionManagerAdapter() { private JtaTransactionAdapter makeTransactionManagerAdapter() {
@ -271,6 +266,7 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
final TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager(); final TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
if ( transactionManager == null ) { if ( transactionManager == null ) {
log.debug( "JtaPlatform#retrieveTransactionManager returned null" ); log.debug( "JtaPlatform#retrieveTransactionManager returned null" );
return null;
} }
else { else {
return new JtaTransactionAdapterTransactionManagerImpl( transactionManager ); return new JtaTransactionAdapterTransactionManagerImpl( transactionManager );
@ -278,9 +274,8 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
} }
catch ( Exception exception ) { catch ( Exception exception ) {
log.debugf( "JtaPlatform#retrieveTransactionManager threw an exception [%s]", exception.getMessage() ); log.debugf( "JtaPlatform#retrieveTransactionManager threw an exception [%s]", exception.getMessage() );
return null;
} }
return null;
} }
@Override @Override
@ -399,7 +394,6 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
@Override @Override
public void begin() { public void begin() {
errorIfInvalid(); errorIfInvalid();
jtaTransactionAdapter.begin(); jtaTransactionAdapter.begin();
JtaTransactionCoordinatorImpl.this.joinJtaTransaction(); JtaTransactionCoordinatorImpl.this.joinJtaTransaction();
} }
@ -414,7 +408,6 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
public void commit() { public void commit() {
errorIfInvalid(); errorIfInvalid();
getTransactionCoordinatorOwner().flushBeforeTransactionCompletion(); getTransactionCoordinatorOwner().flushBeforeTransactionCompletion();
// we don't have to perform any before/after completion processing here. We leave that for // we don't have to perform any before/after completion processing here. We leave that for
// the Synchronization callbacks // the Synchronization callbacks
jtaTransactionAdapter.commit(); jtaTransactionAdapter.commit();
@ -423,7 +416,6 @@ public class JtaTransactionCoordinatorImpl implements TransactionCoordinator, Sy
@Override @Override
public void rollback() { public void rollback() {
errorIfInvalid(); errorIfInvalid();
// we don't have to perform any after completion processing here. We leave that for // we don't have to perform any after completion processing here. We leave that for
// the Synchronization callbacks // the Synchronization callbacks
jtaTransactionAdapter.rollback(); jtaTransactionAdapter.rollback();

View File

@ -40,6 +40,8 @@ public interface TransactionCoordinatorBuilder extends Service {
PhysicalConnectionHandlingMode getDefaultConnectionHandlingMode(); PhysicalConnectionHandlingMode getDefaultConnectionHandlingMode();
default DdlTransactionIsolator buildDdlTransactionIsolator(JdbcContext jdbcContext) { default DdlTransactionIsolator buildDdlTransactionIsolator(JdbcContext jdbcContext) {
return isJta() ? new DdlTransactionIsolatorJtaImpl( jdbcContext ) : new DdlTransactionIsolatorNonJtaImpl( jdbcContext ); return isJta()
? new DdlTransactionIsolatorJtaImpl( jdbcContext )
: new DdlTransactionIsolatorNonJtaImpl( jdbcContext );
} }
} }

View File

@ -31,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
/** /**
@ -73,7 +74,7 @@ public class TransactionCommitFailureTest {
em.getTransaction().commit(); em.getTransaction().commit();
} }
catch (RollbackException e) { catch (RollbackException e) {
assertEquals( COMMIT_FAILURE, e.getLocalizedMessage() ); assertTrue( e.getLocalizedMessage().startsWith( COMMIT_FAILURE ) );
} }
finally { finally {
if ( em.getTransaction() != null && em.getTransaction().isActive() ) { if ( em.getTransaction() != null && em.getTransaction().isActive() ) {

View File

@ -193,7 +193,7 @@ public class SchemaUpdateTask extends MatchingTask {
throw new BuildException( "File not found: " + e.getMessage(), e ); throw new BuildException( "File not found: " + e.getMessage(), e );
} }
catch (IOException e) { catch (IOException e) {
throw new BuildException( "IOException : " + e.getMessage(), e ); throw new BuildException( "IOException: " + e.getMessage(), e );
} }
catch (BuildException e) { catch (BuildException e) {
throw e; throw e;

View File

@ -135,7 +135,7 @@ public class SchemaValidatorTask extends MatchingTask {
throw new BuildException("File not found: " + e.getMessage(), e); throw new BuildException("File not found: " + e.getMessage(), e);
} }
catch (IOException e) { catch (IOException e) {
throw new BuildException("IOException : " + e.getMessage(), e); throw new BuildException("IOException: " + e.getMessage(), e);
} }
catch (BuildException e) { catch (BuildException e) {
throw e; throw e;