Java Spring MDP-如何在收到错误消息时关闭它
我使用SpringJava 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()或类似方法相反),是否可以优雅地关闭消息侦听器?我绝对不喜欢进入无
DefaultMessageListenderContainer
在WebSphereMQV7.1上监听输入队列,实现了一个Spring MDP。如果传入错误消息(导致RuntimeException
),则当前发生的情况是回滚事务,并将消息放回队列。然而,MDP进入了一个无限循环
问题1:根据我的要求,我希望能够在看到错误消息时立即关闭处理。不需要重试。如果消息侦听器看到错误消息(与原始的System.exit()
或类似方法相反),是否可以优雅地关闭消息侦听器?我绝对不喜欢进入无限循环
编辑:
问题2:是否有方法停止或挂起侦听器容器以停止对消息的进一步处理?通常的处理方法是使用错误队列,并在看到错误消息时将其放入错误队列。
有些系统为您处理此问题,例如IBM MQ系列。您只需配置错误队列以及它将在那里重试多少次。
然后管理员将查看这些队列,并对队列中的消息采取适当的操作(即修复并重新提交它们)实际上,
System.exit()
太残忍了,而且。。。不行。失败消息的重试是在代理(WMQ)端处理的,因此一旦重新启动应用程序,消息将被重新传递
您描述的问题被调用,应该在代理端处理。这似乎在WMQ手册和中有描述。我用以下方式解决了问题,不确定这是否是最好的方法,但它仍然有效
特别是,队列的
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);
}