Reputation: 1356
I'm using Spring's JMS (v. 3.1.2) listener-container
with a JMS connectionFactory coming from WebSphere 7's JNDI settings. The application processes messages (put/get) correctly, but the backout settings set in the MQ Queue Manager don't seem to work.
To fail a message consumption, I use spring transactions with a setRollbackOnly()
, and it does increase the property "Backout count" as I can see that number increasing with the "WebSphere MQ Explorer" pointed to the remote queue.
Reading through a few IBM docs, it describes that the IBM MQ JMS client needs to move the bad message to the backout queue. Spring's listener-container
doesn't seem to be using the MQ client in a way that enables that behaviour. The backout count just keeps increasing, as if the requeue command wasn't working.
Is Spring JMS able to use that functionality? Is there anything that needs to be set in the listener-container
for it to be able to process the move to IBM MQ backout queues?
My configuration is as follows:
<tx:jta-transaction-manager/>
<jee:jndi-lookup id="connectionFactory"
jndi-name="java:comp/env/jms/myapp_queuefactory"/>
<jms:listener-container
connection-factory="connectionFactory"
transaction-manager="transactionManager">
<jms:listener destination="ONEQUEUE" ref="oneQueueListener" />
<jms:listener destination="ANOTHERQUEUE" ref="anotherQueueListener" />
<!-- many more -->
<jms:listener-container/>
The IBM MQ queue is set up with "Backout Requeue Queue" set to ONEQUEUE.BOQ
, and "Backout Threshold" to 5
.
My Spring message driven POJO java code is as follows:
@Transactional
public class MyQueueMDBean implements javax.jms.MessageListener {
public void onMessage(javax.jms.Message msg) {
try {
// some code that throws some exception ...
} catch (Exception e) {
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
}
}
}
The Stacktrace ERROR
After the message has been rolled back 5 times, the listener starts failing to connect, as output to the logs:
[org.springframework.jms.listener.DefaultMessageListenerContainer#3-14870] WARN org.springframework.jms.listener.DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'ONEQUEUE' - trying to recover. Cause: MQJMS1079: Unable to write message to dead letter queue.; nested exception is com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'.
It looks like something is going on with the permission to backout the message, or the actual backout queue is not being retrieved correctly, which was unexpected since the get/puts were working OK. Still looking for an answer whether this is a valid approach though.
Upvotes: 3
Views: 6652
Reputation: 7609
JMS Client will put poison messages to the backout queue defined on the queue's BackoutRequeueQueue (BOQNAME) after the number of roll backs exceeds that defined in the BackoutThreshold (BOTHRESH). This means that the user running the JMS application not only needs access to the application queue, it also needs access to put to the named backout queue too.
If the backout queue cannot be accessed or is not defined, the queue manager's dead letter queue (DEADQ attribute) will attempt to be used.
Failure to grant the user ID +put
access to the backout queue and/or the DLQ will result in a MQRC_NOT_AUTHORIZED (2035) reason code when a poison message meets the criteria to be requeued to the backout queue.
The 2035 will be reported by the JMS exceptions, and the exact missing authorities on the exact queue name for the exact user ID will be reported in the queue manager error log.
Related Reading
Upvotes: 5