Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring MDP-如何在收到错误消息时关闭它_Java_Spring_Message Queue_Ibm Mq_Spring Jms_Poison Message - Fatal编程技术网

Java Spring MDP-如何在收到错误消息时关闭它

Java Spring MDP-如何在收到错误消息时关闭它,java,spring,message-queue,ibm-mq,spring-jms,poison-message,Java,Spring,Message Queue,Ibm Mq,Spring Jms,Poison Message,我使用SpringDefaultMessageListenderContainer在WebSphereMQV7.1上监听输入队列,实现了一个Spring MDP。如果传入错误消息(导致RuntimeException),则当前发生的情况是回滚事务,并将消息放回队列。然而,MDP进入了一个无限循环 问题1:根据我的要求,我希望能够在看到错误消息时立即关闭处理。不需要重试。如果消息侦听器看到错误消息(与原始的System.exit()或类似方法相反),是否可以优雅地关闭消息侦听器?我绝对不喜欢进入无

我使用Spring
DefaultMessageListenderContainer
在WebSphereMQV7.1上监听输入队列,实现了一个Spring MDP。如果传入错误消息(导致
RuntimeException
),则当前发生的情况是回滚事务,并将消息放回队列。然而,MDP进入了一个无限循环

问题1:根据我的要求,我希望能够在看到错误消息时立即关闭处理。不需要重试。如果消息侦听器看到错误消息(与原始的
System.exit()
或类似方法相反),是否可以优雅地关闭消息侦听器?我绝对不喜欢进入无限循环

编辑:


问题2:是否有方法停止或挂起侦听器容器以停止对消息的进一步处理?

通常的处理方法是使用错误队列,并在看到错误消息时将其放入错误队列。
有些系统为您处理此问题,例如IBM MQ系列。您只需配置错误队列以及它将在那里重试多少次。

然后管理员将查看这些队列,并对队列中的消息采取适当的操作(即修复并重新提交它们)

实际上,
System.exit()
太残忍了,而且。。。不行。失败消息的重试是在代理(WMQ)端处理的,因此一旦重新启动应用程序,消息将被重新传递


您描述的问题被调用,应该在代理端处理。这似乎在WMQ手册和中有描述。

我用以下方式解决了问题,不确定这是否是最好的方法,但它仍然有效

  • MDP实现ApplicationContextAware;我还在下面维护一个侦听器状态(带有打开、关闭和错误值的枚举)MDP代码片段:
  • 在加载spring上下文的java main中,我执行以下操作:

  • 特别是,队列的
    BOQNAME
    属性应该包含回退队列的名称,
    BOQTHRESH
    应该包含一个值>0,该值表示重新查询消息之前的重试次数。应用程序必须能够访问目标队列上的
    PUT
    INQ
    。如果目标队列不可访问(可能已满或未授权),下一步将尝试系统DLQ。如果
    BOTHRESH
    设置为零,则不会发生自动重新排队。我知道这是标准方式,在大多数情况下建议这样做。但是,在我的情况下,我必须停止处理进一步的消息。毒药消息保留在输入队列中。我不希望侦听器日志继续增长…或者我需要一个通知机制,有人会手动停止侦听器。侦听器是作为linux进程启动的java独立主进程。
    //context
    private ConfigurableApplicationContext applicationContext;
    
    //listener state
    private ListenerState listenerState = ListenerState.OPEN;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }
    //onMessage method
    public void processMessages(....) {
      try {
        process(...);
      } catch (Throwable t) {
        listenerState = ListenerState.ERROR;           
        throw new RuntimeException(...);            
      }    
    }
    
    @Override
    public void stopContext() {        
      applicationContext.stop();  
    }
    
        //check for errors for exit
        Listener listener = (Listener)context.getBean("listener");
        listenerContainer listenerContainer =
                (ListenerContainer)context.getBean("listenerContainer");
    
        try {
            while(true) {
                Thread.sleep(1000); //sleep for 1 sec
                if(!listener.getListenerState().equals(ListenerState.OPEN)) {
                    listener.stopContext();
                    listenerContainer.stop();
                    System.exit(1);
                }>             }            
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }