Reputation: 17
I have a DB-based channel and a simple integration flow like following:
return IntegrationFlows.from("messageChannel")
.handle(messageHandler, "process", consumer ->
consumer.poller(poller -> poller
.fixedDelay(3000)
.transactional()
.transactionSynchronizationFactory(messageStoreSynchronizationFactory)
.taskExecutor(taskExecutor)
.receiveTimeout(1000)
.maxMessagesPerPoll(10)))
.get();
As a part of message processing (messageHandler.process
) I need to open nested transactions to reach out to other databases. The problem is that any unhandled exception that might be thrown from a nested transaction sets my parent transaction to rollback-only
which puts my message back to the channel. That creates a loop that blocks the channel until an issue with a nested transaction is fixed.
In theory, I should catch and handle exceptions within a nested transaction and never propagate to the parent one but it's hard to enforce that with my current project architecture.
Removing .transactional()
from the poller removes parent transaction out of the picture and "fixes" the issue but then it never calls transaction synchronization factory (which makes sense).
Is there a way to allow the nested transaction to throw an exception and still process the message?
Upvotes: 0
Views: 678
Reputation: 174504
You can either add a .gateway()
mid-flow and handle the exception via it's errorChannel
or you can add an ExpressionEvaluatingRequestHandlerAdvice
(or custom advice) to the handler's endpoint to handle the exception there.
See Adding Behavior to Endpoints.
Upvotes: 1