ActiveMQ: dead letter queue maintains the order of my messages

I use ActiveMQ as a message delivery broker. These posts are for writing in dabatas. Sometimes the database is unavailable or inaccessible. In this case, I want to cancel my message in order to repeat this message later, and I want to continue reading other messages.

This code works fine, except for one point: the rollback message blocks me from reading the others:

private Connection getConnection() throws JMSException { RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy(); redeliveryPolicy.setMaximumRedeliveries(3); // will retry 3 times to dequeue rollbacked messages redeliveryPolicy.setInitialRedeliveryDelay(5 *1000); // will wait 5s to read that message ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url); Connection connection = connectionFactory.createConnection(); ((ActiveMQConnection)connection).setUseAsyncSend(true); ((ActiveMQConnection)connection).setDispatchAsync(true); ((ActiveMQConnection)connection).setRedeliveryPolicy(redeliveryPolicy); ((ActiveMQConnection)connection).setStatsEnabled(true); connection.setClientID("myClientID"); return connection; } 

I create a session as follows:

 session = connection.createSession(true, Session.SESSION_TRANSACTED); 

Rollback can be easily asked:

 session.rollback(); 

Suppose I have 3 messages in my queue:

 1: ok 2: KO (will need to be treated again : the message I want to rollback) 3: ok 4: ok 

My consumer will do (linear sequence):

 commit 1 rollback 2 wait 5s rollback 2 wait 5s rollback 2 put 2 in dead letter queue (ActiveMQ.DLQ) commit 3 commit 4 

But I want:

 commit 1 rollback 2 commit 3 commit 4 wait 5s rollback 2 wait 5s rollback 2 wait 5s put 2 in dead letter queue (ActiveMQ.DLQ) 

So, how can I set my Consumer to a later delay in my rollback messages?

+6
java jms activemq
source share
3 answers

This is actually the expected behavior because message retries are handled by the client, not the broker. So, since you have 1 connected session and your retry policy is set for 3 repetitions before DLQ, then the whole repetition process blocks this particular thread.

So, my first question is that if the database failure fails, could you expect all the other DB inserts to fail for the same reason?

If not, a way around this is to set the retry policy for this queue as 0 attempts, with a specific DLQ, so that messages immediately fire and enter DLQ. Then do another process that pulls out DLQ every 5 seconds and processes and / or puts it back in the main queue for processing.

+8
source share

Are you using <strictOrderDispatchPolicy /> in your ActiveMQ XML configuration file? I am not sure if this will affect the order of messages for re-delivery or not. If you use strict order dispatch, try commenting on this policy to see if this behavior will change.

Bruce

0
source share

I had the same problem, I did not find a solution here, so I decided to publish it here after I found it for people struggling with the same. This is fixed before version 5.6, when you set the nonBlockingRedelivery property to true in the factory connection:

 <property name="nonBlockingRedelivery" value="true" /> 
0
source share

All Articles