3
votes

I have a JMSReceiver class which is listening on a MQ Queue. This class implements the MessageListener interface. I wish to implement the logic to retry a message for specified number of times by getting the message to rollback. To do so I have to catch the business exception and wrap it in a RuntimeException so that message gets rolled back to the MQ and gets replayed. i wish to implement this in better way.

Current Implementation

class JMSReceiver implements MessageListener{
public void onMessage(Message msg){
        logger.info("**********Message received in consumer");
         try {
             //Do some business which throws a business exception
         } catch (Exception e) {
            try {
                logger.info("####Redelivery count"+msg.getIntProperty("JMSXDeliveryCount"));
                if(msg.getIntProperty("JMSXDeliveryCount")<10){
                    logger.info("####MQ ISSUE: Redelivery attempted for message. Redelivery attempt: "+msg.getIntProperty("JMSXDeliveryCount"));
                    throw new RuntimeException("Redelivery Attempted"+e.getMessage());                      
                }else{
                    logger.info("####MQ ISSUE: Redelivery attempts exhausted for message");
                }
            } catch (JMSException e1) {                 
                e1.printStackTrace();
                logger.info("####MQ ISSUE: Exception occured while getting JMSXDeliveryCount");
             }
      }
     } 

Expected The above implementation works. It rollsback the message to MQ and the redelivery count increases. I even tried doing session.rollback() but when I do that the redelivery count does not increase and I can replay the message. Please advise a better way to implement this ?

1

1 Answers

2
votes

You can create JMS session with CLIENT_ACKNOWLEDGE as message acknowledge mode. And then in the onMessage() method, do not call msg.Acknowledge(). Not calling msg.Acknowledge() will ensure the same is delivered again.

session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

Note that calling Acknowledge() on one message will acknowledge all messages received since the last time the method was called.

Update

Session creation

    connection = cf.createConnection("user","password");
    System.out.println("Connection created.");
    session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    System.out.println("Session created.");

OnMessage() method - Message is being acknowledged on 6th attempt.

    consumer.setMessageListener(new MessageListener() {
      public void onMessage(Message msg) {
        try {
            // Display the message that just arrived
            System.out.println(msg);

            if(msg.getIntProperty("JMSXDeliveryCount") > 5){
                msg.acknowledge();
            }
        } // end try
        catch (Exception e) {
          System.out.println("Exception caught in onMessage():\n" + e);
        }
        return;
      } // end onMessage()
    }); // end setMessageListener