A message selector allows a JMS consumer to be more selective about the messages it receives from a particular destination (topic or queue). Message selectors use message properties and headers as criteria in conditional expressions. These conditional expressions use boolean logic to declare which messages should be delivered to a JMS consumer.
For example, in the chat client developed in Chapter 2, message selectors could be used to filter out messages from specific people. To accomplish this we would first declare a new property in the message that identifies the username of the JMS client publishing the message:
protected void writeMessage(String text) throws JMSException{
TextMessage message = session.createTextMessage( );
message.setText(text);
message.setStringProperty("username",username);
publisher.publish(message);
}
JMS clients can now use that property to filter messages. Message selectors are declared when the message consumer is created:
TopicSubscriber subscriber =
session.createSubscriber(chatTopic, " username != 'William' "
,false);
In this code, the message selector (shown in bold) tells the message
server to deliver to the consumer only those messages that do
not have a username
property
equal to 'William'
.
When a JMS consumer declares a message selector for a particular destination, the selector is applied only to messages delivered to that consumer. Every JMS client can have a different selector specified for each of its consumers.
The message selectors are based on a subset of the SQL-92 conditional expression syntax, which is used in the WHERE clauses of SQL statements. If you are familiar with SQL 92, the conditional expressions used in message selectors will be familiar to you. The syntax used for conditional expressions is covered in detail in Appendix D.
What happens to messages that are not selected for delivery to the consumer by its message selector? This depends on the message model used. In the pub/sub model, the message is simply not delivered to that consumer, but it is delivered to other consumers. This is true of both nondurable and durable subscriptions. In the p2p model, the messages remain in the queue, so other consumers of the queue can see them, but they are not visible to the consumer that used the message selector.
Here are three complex selectors
used in hypothetical environments. Although you will have to use your
imagination a little, the purpose of these examples is to convey the
power of the message selectors. When a selector is declared, the
identifier always refers to a property name or JMS header name in the
message. For example, the selector "'username !=
'William'
" assumes that there is a property in the message
named username
, which can be compared to the value
'William'
.
Due to some fraudulent claims, an automatic process is implemented that will audit all claims submitted by patients who are employees of the ACME manufacturing company with visits to chiropractors, psychologists, and dermatologists:
String selector = "PhysicianType IN ('Chiropractor', 'Psychologist', 'Dermatologist') "
+ "AND PatientGroupID LIKE 'ACME%'
"; TopicSubscriber subscriber = session.createSubscriber(topic, selector,false);
A supplier wants notification of requests for bids on specific inventory items at specific quantities:
String selector =
"InventoryID = 'S93740283-02' AND Quantity BETWEEN 1000 AND 13000
";
TopicSubscriber subscriber =
session.createSubscriber(topic, selector,false);
An online retailer wants to deliver a special catalog to any customer that orders more then $500.00 worth of merchandise where the average price per item ordered is greater than $75.00 and the customer resides in one of several states. The retailer creates a special application that subscribes to the order processing topic and processes catalog deliveries for only those customers that meet the defined criteria:
String selector = "TotalCharge > 500.00 AND ((TotalCharge / ItemCount) >= 75.00) "
+ "AND State IN ('MN', 'WI', 'MI', 'OH')
"; TopicSubscriber subscriber = session.createSubscriber(topic, selector,false);