当前位置: 首页 > 知识库问答 >
问题:

IBM MQ provider for JMS:如何自动回滚消息?

海信鸥
2023-03-14

应用程序中的工作版本

  • IBM AllClient版本:'com.ibm.mq:com.ibm.mq.AllClient:9.1.1.0'
  • org.springframework:spring-jms:4.3.9.发布
  • javax.jms:javax.jms-api:2.0.1

我的要求是,如果由于消费者不可用(例如DB不可用)而导致消息处理失败,则消息保留在队列中或放回队列中(如果可能的话)。这是因为消息的顺序很重要,必须按照接收消息的相同顺序来消费消息。Java应用程序是单线程的。

@Override
public void onMessage(Message message)
{
   try{
      if(message instanceOf Textmessage)
      {
      }
   
      :

      : 
      throw new Exception("Test");// Just to test the retry
    }
    catch(Exception ex)
    {
            try
            {
                int temp = message.getIntProperty("JMSXDeliveryCount");
                throw new RuntimeException("Redlivery attempted ");
                // At this point, I am expecting JMS to put the message back into the queue.
                // But it is actually put into the Bakout queue.
            }
            catch(JMSException ef)
            {
                String temp = ef.getMessage();
            }

    }
}
    <property name="sessionTransacted" value="true" />

如果将消息放回队列中不可行,那么如何浏览消息、处理它,如果成功,如何拉出消息(这样它就被消费了,不再在队列中)?IBM provider for JMS支持此场景吗?

IBM MQ本地队列具有bothresh(1)

共有1个答案

嵇弘新
2023-03-14

若要保留消息顺序,一种方法可能是作为回滚策略的一部分暂时停止消息侦听器。查看DefaultMessageListenerContainer的Spring Boot文档,有一个Stop(Runnable callback)方法。我已经尝试在回滚中使用它,如下所示。

为了确保我的侦听器是单线程的,我在DefaultJMSListenerContainerFactory上设置了ContainerFactory.setConcurrency(“1”)

在我的侦听器中,我设置了ID

@JmsListener(destination = "DEV.QUEUE.2", containerFactory = "listenerTwoFactory", concurrency="1", id="listenerTwo")
JmsListenerEndpointRegistry reg = context.getBean(JmsListenerEndpointRegistry.class);
DefaultMessageListenerContainer mlc = (DefaultMessageListenerContainer) reg.getListenerContainer("listenerTwo");
retryCount = Integer.parseInt(msg.getStringProperty("JMSXDeliveryCount"));
if (retryCount < 5) {
    throw new Exception("Rollback test "+retryCount);
}
//catch processing here and decide to rollback
mlc.stop(new ContainerTimedRestart(mlc,delay));
System.out.println("#### "+getClass().getName()+" Unable to process message.");
throw new Exception();
public class ContainerTimedRestart implements Runnable {

  //Container instance to restart.
  private DefaultMessageListenerContainer theMlc;

  //Default delay before restart in mills.
  private long theDelay = 5000L;

  //Basic constructor for testing.
  public ContainerTimedRestart(DefaultMessageListenerContainer mlc, long delay) {
    theMlc = mlc;
    theDelay = delay;
  }

  public void run(){
    //Validate container instance.

    try {
      System.out.println("#### "+getClass().getName()+"Waiting for "+theDelay+" millis.");
      Thread.sleep(theDelay);
      System.out.println("#### "+getClass().getName()+"Restarting container.");
      theMlc.start();
      System.out.println("#### "+getClass().getName()+"Container started!");
    } catch (InterruptedException ie) {
      ie.printStackTrace();

      //Further checks and ensure container is in correct state.
      //Report errors.
    }
  }
 类似资料:
  • 我正在处理一个分支,例如需要删除表X中的一列,我添加了一个更改,它对该特定分支有好处,然后我切换到另一个分支,该分支仍然需要该列,并且该更改需要回滚。db在不同的分支之间有很多变化,比如这样的变化。 我为每个分支添加一个新的changelog xml,并将其包含在主changelog xml中。显然,当我切换到另一个分支时,前一个分支的changlog xml不再在工作区中,并且liquibase

  • 问题内容: 我想运行自己的内部pypi服务器,以便在组织内分发鸡蛋。 我发现了一些项目,例如: http://pypi.python.org/pypi/EggBasket/ http://plone.org/products/plonesoftwarecenter 据我了解,pypi.python.org使用名为Cheese Shop的软件。 我的问题: 为什么我不能使用奶酪店本身?(我找不到它,

  • 问题内容: 将内容添加到ListView时,我希望它自动向下滚动。 我正在使用SwiftUI 和a 作为控制器。新数据将追加到列表中。 当我将新数据追加到消息列表时,我希望列表向下滚动。但是,我必须手动向下滚动。 问题答案: 更新:在iOS 14中,现在有一种本机方式可以执行此操作。我正在这样做 对于iOS 13及以下版本,您可以尝试: 我发现翻转视图对我来说似乎很好。这将在底部启动ScrollV

  • 它将打开WhatsApp,并将你带到特定的联系人,如果你已经保存,它将粘贴给定的文本,但它不会发送消息。 链接 他们正在访问通知以获取消息。我想知道他们是如何在没有打开应用程序的情况下在后台发送消息的。如果有人知道这个方法,请在这里分享。

  • 之前的步骤,演示了默认的BasicWxHandler的行为是怎样的,现在,我们要自定义一个WxHandler了 新建一个类,继承BasicWxHandler @IocBean(create="init", name="wxHandler") public class DefaultWxHandler extends BasicWxHandler { @Inject protected Prop

  • 问题内容: 我创建了一个带有JTextArea的JFrame。我想在每次追加后自动向下滚动文本区域。我应该如何处理? 我已经尝试过,但是什么都没有改变。 问题答案: 有两种方法(但必须将JTextArea放在JScrollPane中) a)设置插入符号(方法正确) 例如 b)从(从)移至最大值