我使用Spring DefaultMessageListenderContainer
实现了一个Spring MDP,它监听WebSphere MQ v7.1上的输入队列。如果有错误消息进入(导致RuntimeException
),则当前发生的是,事务被回滚,并且消息被放回队列中。然而,MDP进入无限循环。
问题1:根据我的要求,我希望能够在看到错误消息时关闭处理。无需重试。是否可以正常关闭消息侦听器,以防它看到错误消息(而不是粗略的System.exit()
或那种方法)?我绝对不喜欢它进入无限循环。
修改
问题2:有没有办法停止或暂停监听器容器以停止进一步处理消息?
答案 0 :(得分:2)
处理此问题的常用方法是设置错误队列,并在看到错误消息时将其放入错误队列。
有些系统会为您处理此问题,例如IBM MQ Series。您只需要配置错误队列以及您希望将它放在那里的重试次数。
然后,管理员将查看这些队列并对队列中的消息采取适当的操作(即修复并重新提交)
答案 1 :(得分:1)
实际上,System.exit()
太残酷了......不行。在代理(WMQ)端处理失败消息的重试,以便在重新启动应用程序时重新传递消息。
您描述的问题称为poison-message,应在代理方处理。它似乎在WMQ手册和Handling poison messages中的How WebSphere Application Server handles poison messages中进行了描述。
答案 2 :(得分:0)
我用以下方式解决了这个问题,不确定这是否是最好的方法,但它有效。
//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); }