我的应用程序在 Tomcat 下运行,多个 Spring 的 DefaultMessageListenerContainer
监听在 Oracle 11g Weblogic 服务器下运行的多个不同的 JMS 队列。
DefaultMessageListenerContainer
配置是..嗯..默认为 sessionTransacted = false
和 sessionAcknowledgeMode = AUTO_ACKNOWLEDGE
。我的应用程序收到的消息类型是 javax.jms.TextMessage
。消息的实际主体 (message.getText()
) 是一个 XML 字符串。
当多个应用程序实例(开发盒、测试盒等)需要指向同一个 JMS 服务器时,我遇到了一个问题,因此一旦消息进入队列,就不知道哪个服务器将使用它(我相信首先运行 receive()
方法的那个)。问题是任何给定的应用程序实例只对专用于该特定应用程序实例的消息感兴趣,因此在当前配置下,大多数消息都会丢失(由其他应用程序实例使用并在消息处理业务逻辑中被忽略)。
我无法控制 JMS 服务器的实现,但我可以强制它在消息正文中将特定的 XML 元素设置为应用程序实例特定的值,这样我就可以读取它并决定哪个应用程序实例应该使用它。
最自然的方法是在 DefaultMessageListenerContainer
上设置 messageSelector
属性,以便在 JMS 服务器上做出哪个消费者应该接收什么消息的决定。我还了解了与 XML 消息类型一起使用的 Weblogic 特定 JMS_BEA_SELECT
消息选择器表达式。不幸的是,它似乎不适用于带有 XML 有效负载的 javax.jms.TextMessage
消息(或者至少我无法让它工作)。我正在尝试以下表达式但没有运气:
<property name="messageSelector" value="JMS_BEA_SELECT('xpath', '//Event/CorrelationID/text()') = 'MY_SELECTOR_TEST_3'"/>
根据 this article其他选项是:
- 使用事务处理 session ,然后回滚 session ,以便消息返回队列并可供其他应用程序实例使用。
- 在创建 session 时使用 Session.CLIENT_ACKNOWLEDGE,然后恢复 session ,以便消息返回队列并可供其他应用程序实例使用。
我知道我需要将 DefaultMessageListenerContainer
上的 sessionTransacted
和 sessionAcknowledgeMode
设置为非默认值(什么值?),然后回滚消息处理器代码中的 session (选项 1)或不调用 message.acknowledge()
(选项 2)。
看起来 DefaultMessageListenerContainer
控制消息处理/ session 生命周期。如何自定义它?
最佳答案
带有回滚的解决方案看起来很奇怪。 设置消息选择器应该就足够了。我没有使用 BEA JMS 实现,但我想您可以注意常规的“SELECT”并从 header 中选择。
<property name="messageSelector" value="CorrelationID='MY_SELECTOR_TEST_3'/>
您是否在通信点(服务器、客户端)的两端工作以控制关联 ID?
关于java - JMS TextMessage、JMS_BEA_SELECT 消息选择器、事务处理 session 和确认模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7102641/