JMS TextMessage, JMS_BEA_SELECT message selector, transacted session and acknowledge modes

By : parxier
Source: Stackoverflow.com
Question!

My application is running under Tomcat with a number of Spring's DefaultMessageListenerContainer listening to a number of different JMS queues running under Oracle 11g Weblogic server.

DefaultMessageListenerContainer configuration is.. well.. default with sessionTransacted = false and sessionAcknowledgeMode = AUTO_ACKNOWLEDGE. The type of messages my application receives is javax.jms.TextMessage. The actual body of the message (message.getText()) is an XML string.

I was faced with a problem when a number of application instances (dev boxes, test boxes, etc) needed to be pointed to the same JMS server, so once message comes to the queue it is unknown which server will consume it (I believe the one that runs receive() method first). The problem is that any given application instance is only interested in messages dedicated to that particular application instance, so with a current configuration most of the messages get lost (consumed by other application instances and ignored in message processing business logic).

I have no control on JMS server implementation, but I can force it to set a particular XML element in the message body to an application instance specific value, so I can read it and decide what application instance should consume it.

The most natural way to do that would be setting messageSelector property on DefaultMessageListenerContainer so decision is made on JMS server which consumer should receive what message. I also learned about Weblogic specific JMS_BEA_SELECT message selector expression that works with XML message types. Unfortunately it doesn't seem to work with javax.jms.TextMessage messages with XML payload (or at least I couldn't make it to work). I was trying the following expression with no luck:

<property name="messageSelector" value="JMS_BEA_SELECT('xpath', '//Event/CorrelationID/text()') = 'MY_SELECTOR_TEST_3'"/>

According to this article the other options are:

  1. Use a transacted session, then rollback the session so the message will go back to the queue and can be consumed by other application instance.
  2. Use Session.CLIENT_ACKNOWLEDGE when creating a session, then recover the session so the message will go back to the queue and can be consumed by other application instance.

I understand that I need to set sessionTransacted and sessionAcknowledgeMode on DefaultMessageListenerContainer to non-default values (what values?) and then rollback the session in the message processor code (option 1) or don't call message.acknowledge() (option 2).

It looks like DefaultMessageListenerContainer controls message processing / session life cycle. How can I customise it?

By : parxier


Answers

Solution with rollbacks looks really weird. Setting message selector should be enough. I didn't work with BEA JMS implementation but i guess you can take care with regular "SELECT" and selecting from header .

<property name="messageSelector" value="CorrelationID='MY_SELECTOR_TEST_3'/>

Do you work on both side of communication points (server,client) to control correlation id?

By : magulla


This video can help you solving your question :)
By: admin