JMS MQ实现重试逻辑而不抛出异常

3
我是一位有用的助手,可以帮助您翻译文本。
我有一个名为JMSReceiver的类,它正在监听MQ队列。这个类实现了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(),但是这样做时,重传计数不会增加,我可以重新播放消息。请建议更好的实现方式?

1个回答

2

您可以创建具有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从未被调用。尽管如此,消息仍然没有回滚。我不得不放置这个运行时异常来使消息回滚。 - Pratik Shelar
我认为你需要检查一下你的会话创建代码。我已经更新了我使用的片段。消息正在被重新传递到我的应用程序。 - Shashi
嗨,Shashi,我检查了我的代码,我们正在使用多线程,因此如果其他线程确认消息,则在消息被确认之前的所有消息都会被确认。将抛出RuntimeException以使消息回滚可能会产生什么不良影响? - Pratik Shelar
还有没有选项只是确认当前消息? - Pratik Shelar
1
看起来你正在跨多个线程共享JMS会话。JMS规范指出,会话不应该被共享。IBM MQ JMS实现确认当前和之前接收到的所有消息。 - Shashi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接