У меня есть маршрут
from("direct:my-route")
.routeId("id")
.process(log(...))
.transacted() // Begin transaction
.bean(...)
.bean(...)
.process(...)
.bean(...)
.to("direct:end"); // End transaction
, который, как вы видите, находится в процессе транзакции.Все операции, выполняемые внутри Beans
или Processors
с использованием JdbcTemplate
, обрабатываются.
У нас есть пользовательский ErrorHandler
, который расширяет DeadLetterChannel
, и я заметил, что когда генерируется исключение, транзакция все равно совершается.
Внутри TransactionTemplate#execute
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallbac
}
this.transactionManager.commit(status); <--- after doInTransaction
return result;
После вызова action.doInTransaction(status);
поток кода просто переходит в this.transactionManager.commit(status)
, даже когда я выбрасываюRuntimeException
.
Вызов action.doInTransaction(status)
переходит на TransactionErrorHandler
, в частности этот фрагмент кода
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()) {
...
processByErrorHandler
, просто установите исключение Exchange
на null
, поэтому он не переброшен.
Извините за это "запутанное" вступление.У меня вопрос, как я могу явно откатить транзакцию в случае исключения?Какая стратегия лучше здесь?