Spring DefaultMessageListenerContainer,ActiveMQ和消息重新传递

时间:2010-02-02 10:35:41

标签: java spring exception-handling jms activemq

如果我使用DefaultMessageListenerContainerSpring来接收JMS消息,即使我将sessionAcknowledgeMode设置为2,也不会重新传递JMS消息。

如果我的JavaBean的RuntimeException中有onMessage(),则在JMS提供程序(ActiveMQ)内未确认该消息,它在队列中保持挂起状态。但它永远不会被重新传递,我认为这是因为Spring永远不会调用session.recover()这一事实,根据ActiveMQ's documentation的要求,需要重新发送。

anybode能否提示我如何配置DefaultMessageListenerContainer以便在RuntimeExceptions的情况下调用session.recover()

最好的问候,
马丁

1 个答案:

答案 0 :(得分:3)

您表示您正在使用sessionAcknowledgeMode 2,即Session.CLIENT_ACKNOWLEDGE。以下声明直接取自AbstractMessageListenerContainer Javadocs

  • “CLIENT_ACKNOWLEDGE”:成功侦听器执行后自动确认消息;如果抛出异常,则无法重新开始。

所以问题不在于Spring DMLC,而是在抛出运行时异常时调用Session.recover()的能力。您是否可以在侦听器的onMessage()方法中使用try / catch通过自己调用Session.recover()来处理运行时异常?

更新

你对样板代码提出了一个很好的观点。它被洒在很多地方,并且需要重构。你不可能抽象出这样的代码吗?这是一种常见的解决方案。使用包含具有适当处理的try / catch的方法创建抽象父类应该可以解决问题。然后只需扩展父类以根据需要实现尽可能多的自定义处理器。您甚至可以使用Spring应用程序上下文以适当的方式将处理器连接在一起。

我从来没有遇到过将特定于Spring的代码添加到应用程序的问题,因为它可以在任何地方运行。当我开始使用Spring时,这对我来说非常重要。它不是特定于任何单个应用程序服务器或servlet容器,因此如果我将com.ibm或com.oracle导入到我的源代码中,我就不会像使用Spring一样编写自己的角落。实际上,我已经将Spring JMS API与一个MOM一起使用并切换到另一个MOM,而不更改除JMS连接工厂定义之外的任何内容。