Nick Houghton created CAMEL-10902:
-------------------------------------
Summary: TransactionErrorHandler treats all exceptions as a
rollback (different to Spring)
Key: CAMEL-10902
URL: https://issues.apache.org/jira/browse/CAMEL-10902
Project: Camel
Issue Type: Bug
Components: camel-spring
Affects Versions: 2.18.2
Reporter: Nick Houghton
Priority: Minor
It appears while debugging a JDBC transaction commit issue that the behaviour
of TransactionErrorHandler is different to the expected behaviour of the
underlying Spring TransactionTemplate classes. I'm not sure this is by design
or not?
The standard @Transactional annotation people are used to will only rollback a
transaction when a RuntimeException is caught, in all other cases it will
commit, this appears to be different to camels abstraction which will rollback
if there is any exchange.getException() || exchange.isRollback() set. Should
this be more consistent with the underlying Spring impl and be an instanceof
RuntimeException instead?
Currently:
{code}
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus
status) {
// wrapper exception to throw if the exchange failed
// IMPORTANT: Must be a runtime exception to let Spring regard
it as to do "rollback"
RuntimeException rce;
// and now let process the exchange by the error handler
processByErrorHandler(exchange);
// after handling and still an exception or marked as rollback
only then rollback
if (exchange.getException() != null ||
exchange.isRollbackOnly()) {
// wrap exception in transacted exception
if (exchange.getException() != null) {
rce =
ObjectHelper.wrapRuntimeCamelException(exchange.getException());
} else {
// create dummy exception to force spring transaction
manager to rollback
rce = new TransactionRollbackException();
}
if (!status.isRollbackOnly()) {
status.setRollbackOnly();
}
// throw runtime exception to force rollback (which works
best to rollback with Spring transaction manager)
if (log.isTraceEnabled()) {
log.trace("Throwing runtime exception to force
transaction to rollback on {}", transactionTemplate.getName());
}
throw rce;
}
}
});
{code}
Could be:
{code}
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus
status) {
// wrapper exception to throw if the exchange failed
// IMPORTANT: Must be a runtime exception to let Spring regard
it as to do "rollback"
RuntimeException rce;
// and now let process the exchange by the error handler
processByErrorHandler(exchange);
// after handling and still an exception or marked as rollback
only then rollback
if (exchange.getException() instanceof RuntimeException ||
exchange.isRollbackOnly()) {
// wrap exception in transacted exception
if (exchange.getException() != null) {
rce =
ObjectHelper.wrapRuntimeCamelException(exchange.getException());
} else {
// create dummy exception to force spring transaction
manager to rollback
rce = new TransactionRollbackException();
}
if (!status.isRollbackOnly()) {
status.setRollbackOnly();
}
// throw runtime exception to force rollback (which works
best to rollback with Spring transaction manager)
if (log.isTraceEnabled()) {
log.trace("Throwing runtime exception to force
transaction to rollback on {}", transactionTemplate.getName());
}
throw rce;
}
}
});
{code}
This enable my desired behaviour where a subroute can throw an exception to
present an error to the user, but still have work committed if desired.
At the moment it seems like the only option for not rolling back a transaction
is to process the exception in the subroute itself, which is not what I want to
do rather than letting it bubble up to the calling route.
If not the given change, would it be possible to allow what drives a rollback
to be configurable? much like Spring 'rollbackFor' parameter.
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)