Spring DefaultMessageListenerContainer、ActiveMQ 和消息重新传递
如果我使用 Spring
的 >DefaultMessageListenerContainer
接收 JMS 消息,我没有收到 JMS消息重新传递,即使我将 sessionAcknowledgeMode
设置为 2。
如果在我的 JavaBean 的 onMessage()
内出现 RuntimeException
,则该消息不会在 JMS 提供程序 (ActiveMQ) 内确认,它在队列中保持待处理状态。但它永远不会重新传递,我认为这是由于 Spring 从未调用 session.recover()
造成的,根据 ActiveMQ 的文档 是进行重新传递所必需的。
任何人都可以给我一个提示,如何配置 DefaultMessageListenerContainer
以在发生 RuntimeExceptions 时调用 session.recover()
吗?
谨致问候,
马丁
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您表明您正在使用 sessionAcknowledgeMode 2,即 Session.CLIENT_ACKNOWLEDGE。以下语句直接取自 AbstractMessageListenerContainer Javadocs:
所以问题不在于 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 连接工厂定义之外,没有更改任何其他内容。
You indicate that you're using sessionAcknowledgeMode 2 which is Session.CLIENT_ACKNOWLEDGE. The following statement is taken directly from the AbstractMessageListenerContainer Javadocs:
So the problem is not with the Spring DMLC and it's ability to call Session.recover() when a runtime exception is thrown. Is it possible for you to use a try/catch in your listener's onMessage() method to handle runtime exceptions by calling Session.recover() yourself?
Update:
You make a good point about the boilerplate code. It gets sprinkled in many places and begs to be refactored. Is it not possible for you to abstract such code? This is a common solution. Creating an abstract parent class with a method that contains the try/catch with the appropriate processing should do the trick. Then just extend the parent class to implement as many custom processors as necessary. You can even then wire together the processors in an appropriate manner using your Spring app context.
I've never had a problem adding Spring-specific code to an application because it runs anywhere. This was important for me way back when I began using the Spring. It's not specific to any single app server or servlet container so it's not like I'm coding myself into a corner with Spring the way I am if I import com.ibm or com.oracle into my source code. In fact, I've used the Spring JMS APIs with one MOM and switched to another MOM without changing anything other than the JMS connection factory definition.