A message selector allows a JMS consumer to be more selective about the messages that it receives from a particular topic or queue. A message selector uses message properties and headers as criteria in conditional expressions. These expressions use Boolean logic to declare which messages are delivered to a client. It is not possible for a message selector to filter messages on the basis of the content of the message body.
Note: Message Selectors are supported for single node for WSO2 MB from 3.1.0 onwards. Message Selectors DOES NOT work in cluster mode for MB 3.1.0.
They way selectors work depends on the destination type:
Note: Message Selectors are supported for single node for WSO2 MB from 3.1.0 onwards. Message Selectors DOES NOT work in cluster mode for MB 3.1.0.
They way selectors work depends on the destination type:
- Queues -
- Only messages that match the selector will be delivered to the subscriber.
- If there is at least one subscriber out of a few subscribers for a queue, message will be delivered to that subscriber.
- If there is more than one subscriber whose selector matches with messages, messages will be delivered in round robin manner between those subscribers.
- If there is no subscriber matching a message, that message will be placed in the Dead Letter Queue.
- Topics -
- Only messages that match the selector will be delivered to the subscriber.
- If no subscriber's selector matches with the message, message is dropped.
- We do not evaluate selectors when messages are received by the Broker. Messages will be written anyway if there are subscribers for that topic, and upon delivery selectors are evaluated.
- Durable Topics -
- Only messages that match the selector will be delivered to the durable topic subscriber.
- When keeping a copy of a message coming for a topic for the particular subscription ID, selectors are not evaluated. They are evaluated upon delivery only.
- If a message does not match with the selector for a particular durable topic subscription, it will be routed to Dead Letter Queue.
- If there is no subscriber matching for a message, if the message is for a durable queue or topic, message is routed to DLC.
- User has options to delete the messages selectively if they are unnecessary.
- If user wishes to create a new queue and route all unmatched messages to that queue, it is also possible.
- If user wishes to create a new subscriber with a matching selector for some or all messages routed to DLC, he can do that and route all messages to original queue again. Then, if there are newly created matching subscriptions, those messages will be delivered accordingly. Other messages will land on to DLC queue once again.
Example on how to use a selector JMS way
First create a subscriber with a selector
queue subscriber
topic subscriber
durable topic subscriber
When publishing messages you need to add JMS property 'releaseYear' and set the value as below (Following is the queue example).
QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); //Receive message Queue queue = (Queue) ctx.lookup(queueName); MessageConsumer queueReceiver = queueSession. createConsumer(queue, "releaseYear < 1980");
topic subscriber
TopicSession topicSession = topicConnection.createTopicSession(false, QueueSession.AUTO_ACKNOWLEDGE); Topic topic = topicSession.createTopic(topicName); javax.jms.TopicSubscriber topicSubscriber = topicSession. createSubscriber(topic, "releaseYear < 1980", false);
durable topic subscriber
TopicSession topicSession = topicConnection.createTopicSession(false, QueueSession.AUTO_ACKNOWLEDGE); Topic topic = topicSession.createTopic(topicName); javax.jms.TopicSubscriber topicSubscriber = topicSession. createDurableSubscriber(topic, "mySub4", "releaseYear < 1980", false);
When publishing messages you need to add JMS property 'releaseYear' and set the value as below (Following is the queue example).
javax.jms.QueueSender queueSender = queueSession.createSender(queue); int currentMsgCount = 0; while(currentMsgCount < this.messageCount) { TextMessage textMessage = queueSession. createTextMessage("test: (" + currentMsgCount + ")"); textMessage.setLongProperty("releaseYear", 1990); queueSender.send(textMessage); System.out.println("Sent message: " + currentMsgCount); currentMsgCount ++; }
Element | Description | Example Selector |
---|---|---|
Header Fields | Any headers except JMSDestination, JMSExpiration andJMSReplyTo | JMSPriority = 9 |
Properties | Message properties that follow Java identifier naming | releaseYear = 1982 |
String Literals | String literals in single quotes, duplicate to escape | title = 'Sam''s' |
Number Literals | Numbers in Java syntax (int and double) | releaseYear = 1982 |
Boolean Literals | TRUE and FALSE | isAvailable = TRUE |
( ) | Brackets | (releaseYear < 1980) OR (releaseYear > 1989) |
AND, OR, NOT | Logical operators | (releaseYear < 1980) AND NOT (title = 'Thriller') |
=, <>, <, <=, >, >= | Comparison operators | (releaseYear < 1980) AND (title <>'Thriller') |
LIKE | String comparison with wildcards '_' and '%' (more) | title LIKE 'Thrill%' |
IN | Find value in set of strings (more) | title IN ('Off the wall', 'Thriller', 'Bad') |
BETWEEN | Check whether number is in range (both numbers inclusive) (more) | releaseYear BETWEEN 1980 AND 1989 |
IS NULL, IS NOT NULL | Check whether value is null or not null. | releaseYear IS NOT NULL |
*, +, -, / | Arithmetic operators | releaseYear * 2 > 2000 - 20 |
Some more examples of message consumers with selectors:
Session session = ...
MessageConsumer consumer1 = session.createConsumer(queue,
"(releaseYear < 1980) OR (releaseYear > 1989)");
MessageConsumer consumer2 = session.createConsumer(queue,
"(releaseYear BETWEEN 1980 AND 1989) AND title LIKE 'Michael%'");
MessageConsumer consumer3 = session.createConsumer(queue,
"(releaseYear = 1982) OR (title = 'Thriller')");
MessageConsumer consumer4 = session.createDurableConsumer(queue,
"title IN ('Off the wall', 'Thriller', 'Bad')");