【问题标题】:JMS MQ Implement retry logic without throwing exceptionJMS MQ 实现重试逻辑而不抛出异常
【发布时间】:2015-02-11 23:01:51
【问题描述】:

我有一个正在侦听 MQ 队列的 JMSReceiver 类。此类实现 MessageListener 接口。我希望通过让消息回滚来实现重试消息指定次数的逻辑。为此,我必须捕获业务异常并将其包装在 RuntimeException 中,以便消息回滚到 MQ 并重播。我希望以更好的方式实现这一点。

当前实施

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");
             }
      }
     } 

预期 上述实现有效。它将消息回滚到 MQ 并且重新传递计数增加。我什至尝试过 session.rollback() 但是当我这样做时,重新发送计数不会增加,我可以重播消息。请建议一个更好的方法来实现这个?

【问题讨论】:

    标签: java jms ibm-mq


    【解决方案1】:

    您可以使用 CLIENT_ACKNOWLEDGE 作为消息确认模式创建 JMS 会话。然后在 onMessage() 方法中,不要调用 msg.Acknowledge()。不调用 msg.Acknowledge() 将确保再次传递相同的内容。

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

    请注意,对一条消息调用 Acknowledge() 将确认自上次调用该方法以来收到的所有消息。

    更新

    会话创建

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

    OnMessage() 方法 - 第 6 次尝试确认消息。

        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
    

    【讨论】:

    • 我有那个代码并且抛出异常的代码在确认之前。因此,如果出现异常,则永远不会调用 message.acknowledge。消息仍然没有回滚。我不得不把这个运行时异常让消息回滚
    • 我认为您需要检查会话创建代码。我已经更新了我使用的 sn-p。消息正在重新发送到我的应用程序
    • 嗨,Shashi,我检查了我的代码,我们正在使用多线程,所以如果其他线程确认消息,则所有消息都在消息得到确认之前。抛出运行时异常以使消息回滚可能会产生什么不良影响?
    • 还有什么选项可以只确认当前消息吗?
    • 您似乎正在跨多个线程共享 JMS 会话。 JMS 规范说会话不应该被共享。 IBM MQ JMS 实现确认当前和之前收到的所有消息。
    猜你喜欢
    • 2012-10-20
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 2012-01-24
    相关资源
    最近更新 更多