Wednesday, March 4, 2009

JMS Redelivery Configuration

I recently had to help a client tune JMS redelivery on rollback. The application would post a message to a Queue with persistence, and a set of MDB's would pull these messages and tries to send them over to another point using Web Services, SMS, Email etc. However, if the sending fails, the requirement is to retry the operation by rolling back the read, so that the redelivery count could be used to discard messages on a threshold, or place them into a dead letter queue for manual action etc.

However, if a redelivery time is not specified, the messages keeps rollingback, and immidiately redelievred, which is of no use whatsoever! Though some JMS providers lets you easily configure this (e.g. WebLogic), I came across a JIRA for ActiveMQ, and a set of links that suggested incapability for JBoss.

It will also be impossible to write a MessageSelector, that is expected to pull only messages with say: (JMS_JBOSS_REDELIVERY_COUNT < 3) OR (JMSRedelivered IS FALSE)etc.

The correct trick, is to set the following properties, when placing the message on the Queue, and let the subscribers simply pull the messages out without any selectors etc..

message.setIntProperty("JMS_JBOSS_REDELIVERY_DELAY", 10000);
message.setIntProperty("JMS_JBOSS_REDELIVERY_LIMIT", 3);

The above correctly delays redeliveries to 10 seconds, with a maximum of 3 redeliveries, until the message is placed into the dead letter queue.