2

DefaultMessageListenderContainer在 WebSphere MQ v7.1 上使用 Spring 侦听输入队列来实现 Spring MDP。如果有错误消息进入(导致RuntimeException),当前发生的情况是,事务被回滚,并且消息被放回队列中。然而,MDP 进入了一个无限循环。

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

编辑:

问题2:有没有办法停止或暂停监听器容器以停止进一步处理消息?

4

3 回答 3

2

处理此问题的常用方法是有一个错误队列,当您看到错误消息时将其放入错误队列。
某些系统会为您处理此问题,例如 IBM MQ 系列。你只需要配置错误队列和你想要多少次重试,它就会把它放在那里。
然后管理员将查看这些队列并对队列中的消息采取适当的措施(即修复并重新提交它们)

于 2012-03-12T17:58:23.567 回答
1

其实,System.exit()太残忍了,而且……行不通。失败消息的重试在代理 (WMQ) 端处理,因此在您重新启动应用程序后将重新传递消息。

您描述的问题称为,应在代理端处理。似乎在 WMQ 手册中的处理有害消息和WebSphere Application Server 如何处理有害消息中进行了描述。

于 2012-03-12T17:58:39.397 回答
0

我通过以下方式解决了这个问题,不确定这是否是最好的方法,但它确实有效。

  1. MDP 实现 ApplicationContextAware;我还维护了一个侦听器状态(带有 OPEN、CLOSE、ERROR 值的枚举)MDP 代码片段如下:
//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();  
}
  1. 在加载spring上下文的java main中,我这样做:
    //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);
    }
于 2012-03-16T15:41:33.580 回答