Search code examples
transactionsapache-camelactivemq-classicapache-servicemix

How do camel transactions deal with hardware failure


I am investigating camel transactions run within ServiceMix (v4.4.2). Below is my route:

from(WEBSERVICE_CAMEL_ENDPOINT).to("jms:queue:a");

from("jms:queue:a")
.transacted("PROPAGATION_REQUIRED")
    .process(new Processor() {
        @Override
        public void process(Exchange arg0) throws Exception {                
            System.exit(1); // A
        }
    })
;

Below are the relevant beans:

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://localhost:61616" />
</bean>

<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
    <property name="transacted" value="true" />
    <property name="transactionManager" ref="txManager" />
    <property name="useMessageIDAsCorrelationID" value="true" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>

<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="txManager" />
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" />
</bean>

When I run this and call the web service, ServiceMix is shutdown. When I restart ServiceMix the message has been moved to the dead letter queue (ActiveMQ.DLQ). I see the same behaviour if I put a breakpoint at point A and shutdown ServiceMix manually and by using the Task Manager.

When is this done and how?


Solution

  • First things first, you are mixing a transactional protocol with a non transactional. That's fine as long as you are aware of where you have transactionallity.

    When you run your first route from(WEBSERVICE_CAMEL_ENDPOINT).to("jms:queue:a"); Camel will try to put your message from the WS to the Queue A in ActiveMQ. If that succeeds (SMX is not alive while this is in progress), ActiveMQ has put the message to persistent disk on Queue A. So far, no transactions.

    Then you second route will trigger. Camel will read the message from the queue wihtin a transaction. The message will get flagged for deletion inside ActiveMQ. The transaction will commit if the route is processed fully ok without any exceptions. Only when Camel commit the message, it will be deleted from ActiveMQ. In your case, you're ending the route abnormally and hence, the transaction is not commited, hence the message is not deleted from the Queue.

    In the case the transaction is rolled back (or simply not commited), ActiveMQ redelivery policies will handle if the message is put back to the queue "a" or put to a dead letter queue.

    Read more here. http://activemq.apache.org/message-redelivery-and-dlq-handling.html