OK - we have a working solution. Someone should document this at
http://camel.apache.org/transactional-client.html and
http://camel.apache.org/spring-testing.html since we have had many days of
trouble.

The crux is the source here:
https://github.com/rajivj2/example2/blob/master/src/test/java/com/example/NotificationRouterIT.java

Essentially in our case the test runner is a Spring integration test that
seeds data then tests a route that consumes a JMS message and processes it
in a database.

First problem is that database access requires a transaction. We annotate
our Processor classes @Transactional (remembering not to do so within the
DAO, a common error) and crucially avoid annotating our test method
@Transactional. Instead, the test method creates a TransactionTemplate from
Spring, handing it the injected TransactionManager and execute the data
seeding operation. Finally, send a test message and assert that the sun
still shines.

If the test method itself is annotated @Transactional, as Minh infers, the
seed data is held in memory until the test method completes. We were
expecting Camel, using the shared TransactionManager, to see this data but
instead is either hangs because of a separate transaction context, or just
doesn't see anything if no transaction is used. Programming the transaction
using the TransactionTemplate lets us commit the seed data before the end
of the test, allowing Camel's transaction context to see database data
written already.

Improvements and corrections welcome.


On 22 September 2014 15:17, Minh Tran <darth.minhs...@gmail.com> wrote:

> The reason for the hang is because Spring unit test transaction is
> separate to the camel transaction. The camel transaction is blocked waiting
> because the spring has uncommitted changes to the same table it is trying
> to read from.
>
> Either
> 1. commit the spring transaction first, drop the @Transactional and use a
> TransactionTemplate to do this OR
> 2. Somehow get the spring and camel to participate in the same transaction
> during the unit test. If they share the same transaction manager and camel
> transaction is set to PROPAGATION_REQUIRED which is the default, this
> should just work. This assumes your unit test and camel execution is
> running under the same thread though. If not then stick to the first method.
>
> On 22 Sep 2014, at 11:51 pm, James Green <james.mk.gr...@gmail.com> wrote:
>
> > We have a Spring project that has a unit test annotated @Transactional.
> > This uses a DAO to save a sample Entity before invoking a Camel route
> that
> > accepts a JMS message and sends it to some Processors.
> >
> > The problem we have is when the test itself is annotated @Transactional.
> > The route stops having received the message and begin performing a
> database
> > query - it literally hangs performing the SELECT. Naturally after 20s the
> > time-out is hit.
> >
> > If we remove @Transactional from the test the route continues but finds
> > nothing in the database as the initial Entity save had no effect (it
> > appears).
> >
> > So we're clearly missing something here - how should we seed test data if
> > @Transactional hangs and without it the data is not committed?
> >
> > Thanks,
> >
> > James
>
>

Reply via email to