IBM MQ is a message oriented middle-ware product, used to integrate heterogeneous applications through messaging. The applications may be running on different platforms. Out of many features that it provides, one of the very important feature of IBM MQ is the assured delivery of the messages to the destination. There can be number of scenarios where MQ may not be able to deliver messages to the destination queue, and all those are routed to the Dead Letter Queue(DLQ) defined for the queue manager. Before placing message to the DLQ, IBM MQ attaches Dead Letter Header(DLH) to each message which contains all the required information to identify why the message was placed in DLQ and what was the destination etc. This DLH plays very important role while handling the messages on DLQ.
IBM has provided dlqhandler utility(runmqdlq) to handle messages which are placed on the DLQ. With dlqhandler, you can take necessary action on the messages placed on the DLQ. A rule table can be created with required control data and rules and the same can be used as an input to the dlqhandler. If you need more information on dlqhandler rule table and how it works, please refer the below link.

DLQ Handler Rule Table

Before I discuss on how we should configure dlqhandler to make best use of it, let’s first discuss about the messages placed on the DLQ. The messages placed on the DLQ can be categorized in the below two categories.

i) Replayable Messages :: The messages which are placed on the DLQ due to some temporary issues like the destination queue is full or the destination queue is put disabled etc. These messages can be replayed without any further investigation.
ii) Non-Replayable Messages :: The messages which are placed on the DLQ due to issues which are not temporary in nature, eg incorrect destination, data conversion errors, mqrc_unknown_reason etc. These messages needs further investigation to identify the cause on why those were placed on the DLQ. Replaying these kind of messages with dlqhandler will not make any difference as those messages will again arrive on DLQ.

Replayable messages can be replayed by using dlqhandler.

dlqhandler can be setup in following two simple steps.

1) Creating dlqhandler rule file ::

First step is to create the rule file. There can be number of scenarios based on the design of MQ infrastructure at your organization, but I presenting two very common scenarios.

    Scenario A ::
    Single application using the queue manager, and it is required that all the replayable messages are continuously replayed to the original queue and non-replayable messages are placed on the designated queues for further investigation.

This is a very common requirement in most MQ infrastructure where replayable messages should be replayed as soon as possible. This can be achieved by defining the rule table like below.

Content of qrulefile.rul

******=====Retry every 30 seconds, and WAIT for messages =======*****
RETRYINT(30) WAIT(YES)

***** For reason queue full and put disabled *******
**** retry continuously to put the message on the original queue ****
REASON(MQRC_Q_FULL) ACTION(RETRY) RETRY(999999999)
REASON(MQRC_PUT_INHIBITED) ACTION(RETRY) RETRY(999999999)

**** For all other dlq messages, move those to designated queue *****

ACTION(FWD) FWDQ(APP.DESIG.DLQ) HEADER(YES)
******=========================================================*******

Scenario B ::
Multiple applications using the same queue manager. It is required that the replayable messages are replayed continuously to original queue, and, the non-replayable messages for each application are placed on the dedicated queue for that application.

Suppose, there are 3 applications viz. APP1, APP2 and APP3, using the same queue manager. Following are the queues for these applications and the dedicated queue to hold dlq messages for each application.

For APP1
APP1.Q1
APP1.Q2
DLQ :: APP1.ERROR.DLQ

For APP2
APP2.Q1
APP2.Q2
DLQ :: APP2.ERROR.DLQ

For APP3
APP3.Q1
APP3.Q2
DLQ :: APP3.ERROR.DLQ

We now have to write rules based on the DESTQ for each application. Below the example rule file for this scenario.

Content of qrulefile.rul

******=====Retry every 30 seconds, and WAIT for messages =======*****
RETRYINT(30) WAIT(YES)

***** For reason queue full and put disabled *******
**** retry continuously to put the message on the original queue ****
REASON(MQRC_Q_FULL) ACTION(RETRY) RETRY(999999999)
REASON(MQRC_PUT_INHIBITED) ACTION(RETRY) RETRY(999999999)

******* For APP1, forward messages to APP1.ERROR.DLQ ******
DESTQ(APP1.Q1) ACTION(FWD) FWDQ(APP1.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)
DESTQ(APP1.Q2) ACTION(FWD) FWDQ(APP1.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)

******* For APP2, forward messages to APP2.ERROR.DLQ ******
DESTQ(APP2.Q1) ACTION(FWD) FWDQ(APP2.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)
DESTQ(APP2.Q2) ACTION(FWD) FWDQ(APP2.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)

******* For APP3, forward messages to APP3.ERROR.DLQ ******
DESTQ(APP3.Q1) ACTION(FWD) FWDQ(APP3.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)
DESTQ(APP3.Q2) ACTION(FWD) FWDQ(APP3.ERROR.DLQ) FWDQM(”) HEADER(YES) RETRY(999999999)

**** For all other dlq messages, move those to designated queue *****

ACTION(FWD) FWDQ(NO.APP.ERROR.DLQ) HEADER(YES)
*********=========================================================******

2) Startup of dlqhandler ::

Once the rule file is created, you can configure dlqhandler startup in the following ways.
1) Manually starting the dlqhandler and keep it running.

runmqdlq QMGR_DLQ QMGR_NAME < qrulefile.rul

2) Configure dlqhandler as a service in the queue manager and set the CONTROL as you wish(MANUAL or QMGR)

DEFINE SERVICE(dlqhandler) +
SERVTYPE(SERVER) +
CONTROL(MANUAL) +
STARTCMD(‘/path/runmqdlq’) +
DESCR(‘dlqhandler service’) +
STARTARG(‘DEADQ QMGR < /path/qrulefile.rul’) +
STDOUT(‘/path/dlq.log’) +
STDERR(‘/path/dlq_error.log’) +

3) Configure triggering at DLQ to start dlq handler whenever first message arrives on the queue.
You can do it by simply following the steps on how to configure triggering on any queue. Please refer the following link for more information on triggering.

Starting WebSphere MQ applications using triggers

Once you setup triggering, dlqhandler will be started by triggering based on the condition that you set. You don’t need to have dlqhandler running all the time as it can be started again by triggering. Due to above reason, you don’t need WAIT(YES) in the rule file, you can change it to WAIT(NO).

3 comments on"Best use of dlq handler with MQ"

  1. […] Best use of dlq handler with MQ […]

  2. Please note that your DEFINE SERVICE will not operate correctly on Windows (I assume you created it on Linux?). Please see this post on mqseries.net for the problem and answer (http://mqseries.net/phpBB/viewtopic.php?p=324262). You need to create a simple .bat file to use to pass the parameters through since they include redirecting stdin.

    • SantoshKr July 12, 2017

      Thanks for your valuable comment on this blog MoragH !!!
      Yes, i have tested it on linux machine, and you are correct that the define service won’t work correctly on windows machines if you use redirection opr.

Leave a Reply