2
votes

Consider the following two test. The findOne() has no side effect, the delete() has a side effect on the underlying h2 database. My problem is the @Transactional does not rollback the changes for the delete() method.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:app-context.xml")
public class AccountProcessorTest extends BaseRouteTest {

      private static final String ACCOUNTS_ENDPOINT = "seda:bar";

      @Test
      @Transactional
      public void findOne() {

          final Map<String, Object> headers = new HashMap<String, Object>();
          headers.put("id", 1);
          headers.put(Exchange.HTTP_METHOD, "GET");

          final String response = template.requestBodyAndHeaders(ACCOUNTS_ENDPOINT, null, headers, String.class);
          assertEquals("Checking account",JsonPath.read(response, "name"));

      }

     @Test
     @Transactional
     public void delete() {

         final Map<String, Object> headers = new HashMap<String, Object>();
         headers.put("id", 1);
         headers.put(Exchange.HTTP_METHOD, "DELETE");

         final String response = template.requestBodyAndHeaders(ACCOUNTS_ENDPOINT, null, headers, String.class);
         assertEquals(200, JsonPath.read(response, "code"));

      }

 }

The BaseRouteTest is just a utility where I get a reference to the Camel ProducerTemplate

public class BaseRouteTest implements InitializingBean {

   @Autowired
   private ApplicationContext applicationContext;

   protected ProducerTemplate template;

   @Override
   public void afterPropertiesSet() throws Exception {
      template = getCamelContext().createProducerTemplate();
   }

   private CamelContext getCamelContext() {
      return applicationContext.getBean("foo", CamelContext.class);
   }

}

I have marked the route as transacted using the transacted tag.

<!-- camel-context -->
<camel:camelContext id="foo">
    <camel:route>
        <camel:from uri="seda:bar"/>
        <camel:transacted />
        <camel:process ref="accountProcessor"/>
    </camel:route>
</camel:camelContext>

My spring configuration file:

<context:component-scan base-package="com.backbase.progfun"/>

<!-- embedded datasource -->
<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:data/schema.ddl"/>
    <jdbc:script location="classpath:data/insert.sql"/>
</jdbc:embedded-database>

<!-- spring jdbc template -->
<bean class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource" />
</bean>

<!-- transaction management start -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- transaction management end -->

<!-- camel-context -->
<camel:camelContext id="foo">
    <camel:route>
        <camel:from uri="seda:bar"/>
        <camel:transacted />
        <camel:process ref="accountProcessor"/>
    </camel:route>
</camel:camelContext>

You can try it out quickly if you clone my github repo found here: https://github.com/altfatterz/camel-transaction

If you run the AccountProcessorTest it the findOne() test case fails because the side effect of delete() test case is not rolled back.

Any suggestion would be greatly appreciated.

Thank you.

1

1 Answers

1
votes

Transactions aren't carried across SEDA queues.

Therefore the transaction started by your test is a different transaction from the transaction in your route. So the changes made by your route won't be rolled back when the transaction started by your test is rolled back.