|
|

[an error occurred while processing this directive]
|
 |
 |
The message-driven bean (MDB) -introduced by EJB 2.0-has an interesting and useful feature called selectors that allows the bean to be selective in the messages it responds to. This article discusses the features of the MDB selector and examines some basic sample code.
 |
What selectors do |
 |
 |
 |
In the most basic usage, J2EE application assemblers and deployers set MDBs up to listen to JMS topics (or queues), depending on whether a publisher/subscriber (or point-to-point) architecture is being used. The MDB acts as a MessageListener. That means that if a message is produced on the JMS destination topic or queue the MDB is listening on, the MDB's onMessage() callback method is invoked and your code is executed.
Sometimes you as application designer may want to have a message bean respond only to selected messages on that destination. Say for example you have a production line that produces three types of shirts-polo, tee, and jersey. Your application uses the pub/sub architecture and publishes a message on a topic called Production every time a case of shirts is ready for shipment. You have a message listener, and you want it to take action only when polo shirts are produced. One way to do this would be to create a different topic for each type of shirt. But this could quickly become difficult to manage as your selection of shirts increases. A better solution would be to use message selectors.
|
 |
 |
how to use selectors |
 |
 |
 |
Adding the selector and its properties
To use message selectors for this task, you as application assembler would add a piece of selection code to the deployment descriptor. The selector is a conditional expression that follows the ANSI-92 SQL syntax-it would follow a WHERE clause in a standard SQL statement. (You can find a detailed description of the ANSI-92 conditional expression syntax in Chapter 3.8 of the JMS specification, available at (http://java.sun.com/products/jms/docs.html.)
NOTE: In this example you set up the MDB's selector in the deployment descriptor. Depending on the application server you are using, you may alternatively be able to append to this selector in the vendor-specific deployment document. See your server documentation.
The message selector field uses the message property or header name on the left of the expression, and its value on the right. In this example, using a clause of the form shirtType = 'polo', the MDB only reacts to a message that has a property named shirtType with a value of polo.
Selectors use the names of message headers or properties as identifiers in their selection clauses. Headers have fixed names and are established by the JMS specification. As a programmer you establish properties programmatically in your producer clients.
In your shirt production company you have a publisher client that will publish a message with a string property named shirtType. The property can have a value-for example, polo, tee, or jersey. It also has boolean properties named male and female. The set logic of these two boolean properties is as follows:
| Shirt gender / property | Male | Female |
| Male | True | False |
| Female | False | True |
| Unisex | True | True |
You set the properties in your publisher client as follows:
// Reports the production of a case of unisex polo shirts
message.setStringProperty("shirtType", "polo");
message.setBooleanProperty("male", true);
message.setBooleanProperty("female", true);
// Priority header is set through the publish method
topicPublisher.publish(
message,
topicPublisher.getDeliveryMode(), // Set to default
6, // Set priority to 6
topicPublisher. getTimeToLive() // Set to default);
);
// Reports the production of a case of male polo shirts
message.setStringProperty("shirtType", "polo");
message.setBooleanProperty("male", true);
message.setBooleanProperty("female", false);
// Priority header is set through the publish method
topicPublisher.publish(
message,
topicPublisher.getDeliveryMode(), // Set to default
4, // Set priority to 4
topicPublisher. getTimeToLive() // Set to default);
);
// Reports the production of a case of male tee shirts
message.setStringProperty("shirtType", "tee");
message.setBooleanProperty("male", true);
message.setBooleanProperty("female", false);
// Priority header is set through the publish method
topicPublisher.publish(
message,
topicPublisher.getDeliveryMode(), // Set to default
9, // Set priority to 9
topicPublisher. getTimeToLive() // Set to default);
);
Modifying the XML file
Your MDB is interested in shirts that are polo shirts. So as application assembler you make an appropriate entry in the ejb-jar.xml file using the expression shirtType = 'polo'. The ejb-jar.xml entry would be:
<message-driven>
<ejb-name>MBShirt</ejb-name>
<ejb-class>com.mike.shirtBeans.MBShirtBean</ejb-class>
<transaction-type>Container</transaction-type>
<message-selector>shirtType = 'polo'</message-selector>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>Durable</subscription-durability>
</message-driven-destination>
</message-driven>
Adding more restrictions
As deployer, you could decide to further restrict the MDB-say to listen only for high-priority, men's polo shirts-and possibly use the vendor-specified deployment file to do this. (Again, check your application server documentation for details on this or other similar functionality.) The entry in a SilverStream eXtend Application Server 4.0 EJB 2.0 deployment plan would be:
<selectorAddon> AND JMSPriority > 8 AND male = true </selectorAddon>
TIP: The > and < must be entered as > or < for the XML to parse.
This would produce a filter with the behavior shirtType = 'polo' AND JMSPriority > 8 AND male = true. The MDB would only respond to messages with a shirtType equal to polo and a gender equal to male and a priority header with a value greater than 8.
|
 |
 |
summary |
 |
 |
 |
|
MDB message selectors are simple tools that allow your MDBs to filter the messages they respond to. This powerful feature gives you great flexibility in applying MDBs with your applications.
td>
|
 |
 |
notes on the code |
 |
 |
 |
Selector expression syntax
The following is a partial summary of selector expression syntax:
| Element | Valid values |
| Identifiers |
- Property or header field reference (such as JMSPriority, myProperty1, and so on)
- Cannot be NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, IS
|
| Operators | AND, OR, LIKE, BETWEEN, =, <>, <, >, <=, >=, IS NULL, IS NOT NULL |
| Literals |
- Boolean literals are TRUE and FALSE
- Exact number literals have no decimal point (for example, +25, -399, 40, and so on)
- Approximate number literals can use scientific notation or decimal (for example, -21.4E4, 5E2, +34.4928, and so on)
|
| Examples |
- shirtType IN ('polo', 'tee', 'sweater')
- (JMSPriority > 4 AND shirtType LIKE '%polo%') OR shirtType = 'tee'
- JMSPriority BETWEEN 4 and 7
|
Headers and properties
These are the headers you can use for JMS selection:
| Header | May be NULL |
| JMSDeliveryMode | |
| JMSPriority | |
| JMSMessageID | X |
| JMSTimestamp | |
| JMSCorrelationID | X |
| JMSType | X |
| JMSDeliveryMode | |
Property setter methods
These are the property setter methods you can use:
| Method | Setter method |
| java.lang.String | setStringProperty(String name, String value) |
| boolean | setBooleanProperty(String name, boolean value) |
| int | setIntProperty(String name, int value) |
| short | setShortProperty(String name, short value) |
| float | setFloatProperty(String name, float value) |
| double | setDoubleProperty(String name, double value) |
| long | setLongProperty(String name, long value) |
| byte | setByteProperty(String name, byte value) |
|
 |
|
 |
 |
 |