【问题标题】:Spring DefaultMessageListenerContainer, ActiveMQ and message redeliverySpring DefaultMessageListenerContainer、ActiveMQ 和消息重新传递
【发布时间】:2011-01-12 02:29:46
【问题描述】:

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

如果在我的 JavaBean 的 onMessage() 中出现 RuntimeException,则消息不会在 JMS 提供程序 (ActiveMQ) 中得到确认,它在队列中保持挂起状态。但它永远不会重新交付,我认为这是由于 Spring 从未调用 session.recover() 造成的,根据 ActiveMQ's documentation 的要求,这是重新交付发生所必需的。

谁能告诉我如何配置DefaultMessageListenerContainer 以在出现RuntimeExceptions 的情况下调用session.recover()

最好的问候,
马丁

【问题讨论】:

  • 我遇到了类似的问题。 SessionAwareListener 会抛出意外的运行时异常,但 DMLC 会在停止之前重试消息大约 32 次。不确定如何设置重试次数...?

标签: java spring exception-handling jms activemq


【解决方案1】:

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

  • “CLIENT_ACKNOWLEDGE”:侦听器执行成功后自动消息确认;发生异常时不重新投递。

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

更新:

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

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

【讨论】:

  • 谢谢,我知道这个可能的解决方案(对不起,没有写那个),但它为我使用的每个 bean 添加样板代码,并迫使我使用SessionAwareMessageListener(是 Spring 依赖项)而不是 javax.jms.MessageListener。老实说,我不希望直接在我的消息处理器中引入 Spring 依赖项。
猜你喜欢
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多