WebSphereUowTransactionManager logs overridden application exceptions

Issue: SPR-16102
This commit is contained in:
Juergen Hoeller 2017-10-24 13:14:22 +02:00
parent bf6025303b
commit efe943df72
3 changed files with 51 additions and 42 deletions

View File

@ -306,6 +306,8 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
} }
else { else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try { try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
@ -325,7 +327,8 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
} }
else { else {
// A normal return value: will lead to a commit. // A normal return value: will lead to a commit.
return new ThrowableHolder(ex); throwableHolder.throwable = ex;
return null;
} }
} }
finally { finally {
@ -333,17 +336,28 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
} }
}); });
// Check result: It might indicate a Throwable to rethrow. // Check result state: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) { if (throwableHolder.throwable != null) {
throw ((ThrowableHolder) result).getThrowable(); throw throwableHolder.throwable;
}
else {
return result;
} }
return result;
} }
catch (ThrowableHolderException ex) { catch (ThrowableHolderException ex) {
throw ex.getCause(); throw ex.getCause();
} }
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
} }
} }
@ -540,14 +554,10 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
ex2.initApplicationException(ex); ex2.initApplicationException(ex);
throw ex2; throw ex2;
} }
catch (RuntimeException ex2) { catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex); logger.error("Application exception overridden by rollback exception", ex);
throw ex2; throw ex2;
} }
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
} }
else { else {
// We don't roll back on this exception. // We don't roll back on this exception.
@ -560,14 +570,10 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
ex2.initApplicationException(ex); ex2.initApplicationException(ex);
throw ex2; throw ex2;
} }
catch (RuntimeException ex2) { catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex); logger.error("Application exception overridden by commit exception", ex);
throw ex2; throw ex2;
} }
catch (Error err) {
logger.error("Application exception overridden by commit error", ex);
throw err;
}
} }
} }
} }
@ -679,20 +685,12 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
/** /**
* Internal holder class for a Throwable, used as a return value * Internal holder class for a Throwable in a callback transaction model.
* from a TransactionCallback (to be subsequently unwrapped again).
*/ */
private static class ThrowableHolder { private static class ThrowableHolder {
private final Throwable throwable; @Nullable
public Throwable throwable;
public ThrowableHolder(Throwable throwable) {
this.throwable = throwable;
}
public final Throwable getThrowable() {
return this.throwable;
}
} }

View File

@ -261,7 +261,8 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
"Transaction propagation 'nested' not supported for WebSphere UOW transactions"); "Transaction propagation 'nested' not supported for WebSphere UOW transactions");
} }
if (pb == TransactionDefinition.PROPAGATION_SUPPORTS || if (pb == TransactionDefinition.PROPAGATION_SUPPORTS ||
pb == TransactionDefinition.PROPAGATION_REQUIRED || pb == TransactionDefinition.PROPAGATION_MANDATORY) { pb == TransactionDefinition.PROPAGATION_REQUIRED ||
pb == TransactionDefinition.PROPAGATION_MANDATORY) {
joinTx = true; joinTx = true;
newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
} }
@ -279,7 +280,8 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
"Transaction propagation 'mandatory' but no existing transaction found"); "Transaction propagation 'mandatory' but no existing transaction found");
} }
if (pb == TransactionDefinition.PROPAGATION_SUPPORTS || if (pb == TransactionDefinition.PROPAGATION_SUPPORTS ||
pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED || pb == TransactionDefinition.PROPAGATION_NEVER) { pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED ||
pb == TransactionDefinition.PROPAGATION_NEVER) {
uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION; uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION;
newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
} }
@ -293,6 +295,7 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
} }
SuspendedResourcesHolder suspendedResources = (!joinTx ? suspend(null) : null); SuspendedResourcesHolder suspendedResources = (!joinTx ? suspend(null) : null);
UOWActionAdapter<T> action = null;
try { try {
if (definition.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) { if (definition.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) {
uowManager.setUOWTimeout(uowType, definition.getTimeout()); uowManager.setUOWTimeout(uowType, definition.getTimeout());
@ -300,7 +303,7 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
if (debug) { if (debug) {
logger.debug("Invoking WebSphere UOW action: type=" + uowType + ", join=" + joinTx); logger.debug("Invoking WebSphere UOW action: type=" + uowType + ", join=" + joinTx);
} }
UOWActionAdapter<T> action = new UOWActionAdapter<>( action = new UOWActionAdapter<>(
definition, callback, (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION), !joinTx, newSynch, debug); definition, callback, (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION), !joinTx, newSynch, debug);
uowManager.runUnderUOW(uowType, joinTx, action); uowManager.runUnderUOW(uowType, joinTx, action);
if (debug) { if (debug) {
@ -308,11 +311,15 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
} }
return action.getResult(); return action.getResult();
} }
catch (UOWException ex) { catch (UOWException | UOWActionException ex) {
throw new TransactionSystemException("UOWManager transaction processing failed", ex); TransactionSystemException tse =
} new TransactionSystemException("UOWManager transaction processing failed", ex);
catch (UOWActionException ex) { Throwable appEx = action.getException();
throw new TransactionSystemException("UOWManager threw unexpected UOWActionException", ex); if (appEx != null) {
logger.error("Application exception overridden by rollback exception", appEx);
tse.initApplicationException(appEx);
}
throw tse;
} }
finally { finally {
if (suspendedResources != null) { if (suspendedResources != null) {
@ -368,12 +375,15 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
} }
catch (Throwable ex) { catch (Throwable ex) {
this.exception = ex; this.exception = ex;
if (status.isDebug()) {
logger.debug("Rolling back on application exception from transaction callback", ex);
}
uowManager.setRollbackOnly(); uowManager.setRollbackOnly();
} }
finally { finally {
if (status.isLocalRollbackOnly()) { if (status.isLocalRollbackOnly()) {
if (status.isDebug()) { if (status.isDebug()) {
logger.debug("Transactional code has requested rollback"); logger.debug("Transaction callback has explicitly requested rollback");
} }
uowManager.setRollbackOnly(); uowManager.setRollbackOnly();
} }
@ -396,6 +406,11 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
return this.result; return this.result;
} }
@Nullable
public Throwable getException() {
return this.exception;
}
@Override @Override
public boolean isRollbackOnly() { public boolean isRollbackOnly() {
return obtainUOWManager().getRollbackOnly(); return obtainUOWManager().getRollbackOnly();

View File

@ -172,14 +172,10 @@ public class TransactionTemplate extends DefaultTransactionDefinition
ex2.initApplicationException(ex); ex2.initApplicationException(ex);
throw ex2; throw ex2;
} }
catch (RuntimeException ex2) { catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex); logger.error("Application exception overridden by rollback exception", ex);
throw ex2; throw ex2;
} }
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
} }
} }