Aman
Aman

Reputation: 246

Rollback the message to Dead Letter Queue - Apache Camel

I have set up the Apache camel in which i consumes the message from one queue and do some kind of operation on it and then transfers it to other queue .

Now if the exception comes then i want that it should rollback and then after 6 attempts it to send to dead letter queue , Currently rollback happens 5-6 times but my message is not transferred to dead letter queue .

Here What happens --> Queue1-->(Consumes)-->Operation(Exception thrown)--> rollback --> again Queue1-->(Consumes) --> Operation(Exception thrown)-->rollback -->... this happens 5-6 times and then my message is lost

I dont know where my message is going and why it is getting lost , and from my Active MQ GUI i can see it is dequeued.

@Bean
public RedeliveryPolicy redeliveryPolicy() {
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
    redeliveryPolicy.setMaximumRedeliveries(2);
    redeliveryPolicy.setMaximumRedeliveryDelay(10000);
    redeliveryPolicy.setRedeliveryDelay(10000);
    return redeliveryPolicy;
}

---------------------Route extends SpringRouteBuilder-------------------

onException(MyException.class)
    .markRollbackOnly()
    .redeliveryPolicy(redeliveryPolicy)
    .useExponentialBackOff()
    .handled(true)

from("jms:queue:Queue1")
    .process(new Processor(){
       public void process(Exchange ex){
         throw new RuntimeException();
        }
    }).to("jms:queue:myQueue)

Upvotes: 2

Views: 2854

Answers (1)

burki
burki

Reputation: 7005

I assume there are multiple problems.

  1. markRollbackOnly stops the message. After this statement no further routing is done.

That is the reason why your RedeliveryPolicy and the rest of your onException route is completely ignored. You configure 2 redelivery attempts but you write it does 5 (the default redelivery of ActiveMQ).

To fix this, move markRollbackOnly to the end of your onException route

  1. If you consume transacted from your JMS broker the message must not get lost.

Since you lose it in case of an error, there is a problem with your transaction config. Configure the ActiveMQ component of Camel to use local JMS transactions when consuming.

@Bean(name = "activemq")
@ConditionalOnClass(ActiveMQComponent.class)
public ActiveMQComponent activeMQComponent(ConnectionFactory connectionFactory) {
    ActiveMQComponent activeMQComponent = new ActiveMQComponent();
    activeMQComponent.setConnectionFactory(connectionFactory);
    activeMQComponent.setTransacted(true);
    activeMQComponent.setLazyCreateTransactionManager(false);
    return activeMQComponent;
}

When this is in place, you can in fact remove the onException route because the redelivery is done by the JMS broker, so you have to configure the redelivery settings on your JMS connection. If the configured redelivery is exhausted and the message still produces a rollback, it is moved to the DLQ.

Be aware when using an additional onException route because this is pure Camel. The Camel error handler does NOT redeliver on route level, but on processor level. So if you configure both broker and Camel redelivery, it can multiply them.

Upvotes: 4

Related Questions