I am in the process of upgrading from Camel 2.12.x to 2.18.x.  I have a
unit test that verifies transacted routes work as expected.  The test used
to work but after upgrading Camel, it now fails.  The failure appears to be
related to encountering a route with "PROPAGATION_REQUIRES_NEW".

The test uses a mock platform transaction manager, and it verifies that
getTransaction() and commit() are only called once on that mock.  However,
after changing to Camel 2.13.4 or above (have tried the latest point
release of each major version up to 2.18.3), the test now fails because
getTransaction() and commit() are called twice on the platform transaction
manager mock.  In other words, Camel appears to be be creating two
transactions when it should only be creating one.  Note that this behavior
is not seen when using PROPAGATION_REQUIRED.

The route in the test looks like this:
EventDrivenConsumerRoute[direct-vm://rollbackAll.innerRoute -> Channel[
TransactionErrorHandler:PROPAGATION_REQUIRES_NEW[
Channel[sendTo(mock://result)]]]]>

In addition I see the following two identical log statements from the
output of the test (including the transactionKey 0x6775c0d1 in parens)
which seem to reinforce my summation of what's happening:
2018-01-10 19:25:36,804 DEBUG [main]
org.apache.camel.spring.spi.TransactionErrorHandler
- <Transaction begin (0x6775c0d1) redelivered(unknown) for (MessageId:
ID-hostname-39408-1515612165923-0-1 on ExchangeId: ID-hostname-39408-
1515612165923-0-4))>
...
2018-01-10 19:25:37,966 DEBUG [main]
org.apache.camel.spring.spi.TransactionErrorHandler
- <Transaction begin (0x6775c0d1) redelivered(unknown) for (MessageId:
ID-hostname-39408-1515612165923-0-1 on ExchangeId: ID-hostname-39408-
1515612165923-0-4))>

It is not feasible for me to post the test as it is on an isolated
machine/system.

When using the debugger in Eclipse to step through the test, I noticed in
TransactionErrorHandler#process(Exchange) line 98 (Camel version 2.18.3)
has this line that I believe was modified in version 2.13.4:
if(transactionTemplate.getPropagationBehavior() !=
TransactionDefinition.PROPAGATION_REQUIRES_NEW
&& exchange.getUnitOfWork().isTransactedBy(transactionKey)) {

I believe the issue is related to the above line.  This conditional block
determines if the code calls processByErrorHandler(Exchange) or
processInTransaction(Exchange).  In the case of the above documented route,
processInTransaction(Exchange) is called twice (I believe in error),
instead of calling processInTransaction(Exchange) first, and then
subsequently calling processByErrorHandler(Exchange).

If I'm correct, I can see how this bug could be overlooked because creating
an extra transaction doesn't really have any bad side effects except for
overhead/performance.

Thoughts?

Reply via email to