Message selectors in JMS

Messages can contain application-defined property values. An application can use message selectors to have a JMS provider filter messages.

A message contains a built-in facility to support application-defined property values. In effect, this provides a mechanism to add application-specific header fields to a message. Properties allow an application, using message selectors, to have a JMS provider select or filter messages on its behalf, using application-specific criteria. Application-defined properties must obey the following rules:

  • Property names must obey the rules for a message selector identifier.
  • Property values can be Boolean, byte, short, int, long, float, double, and String.
  • The JMSX and JMS_ name prefixes are reserved.

Property values are set before sending a message. When a client receives a message, the message properties are read-only. If a client attempts to set properties at this point, a MessageNotWriteableException is thrown. If clearProperties is called, the properties can now be both read from, and written to.

A property value might duplicate a value in a message body. JMS does not define a policy for what might be made into a property. However, application developers must be aware that JMS providers probably handle data in a message body more efficiently than data in message properties. For best performance, applications must use message properties only when they need to customize a message header. The primary reason for doing this is to support customized message selection.

A JMS message selector allows a client to specify the messages that it is interested in by using the message header. Only messages with headers that match the selector are delivered.

Message selectors cannot refer to message body values.

A message selector matches a message when the selector evaluates to true when the message header field and property values are substituted for their corresponding identifiers in the selector.

A message selector is a String, with syntax that is based on a subset of the SQL92 conditional expression syntax. The order in which a message selector is evaluated is from left to right within a precedence level. We can use parentheses to change this order. Predefined selector literals and operator names are written here in uppercase; however, they are not case-sensitive.


Contents of a message selector

A message selector can contain:

  • Literals

    • A string literal is enclosed in quotation marks. A doubled quotation mark represents a quotation mark. Examples are 'literal' and 'literal''s'. Like Java string literals, these use the Unicode character encoding.
    • An exact numeric literal is a numeric value without a decimal point, such as 57, -957, and +62. Numbers in the range of Java long are supported.
    • An approximate numeric literal is a numeric value in scientific notation, such as 7E3 or -57.9E2, or a numeric value with a decimal, such as 7., -95.7, or +6.2. Numbers in the range of Java double are supported.
    • The Boolean literals TRUE and FALSE.

  • Identifiers:

    • An identifier is an unlimited length sequence of Java letters and Java digits, the first of which must be a Java letter. A letter is any character for which the method Character.isJavaLetter returns true. This includes _ and $. A letter or digit is any character for which the method Character.isJavaLetterOrDigit returns true.
    • Identifiers cannot be the names NULL, TRUE, or FALSE.
    • Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, or IS.
    • Identifiers are either header field references or property references.
    • Identifiers are case sensitive.
    • Message header field references are restricted to:

      • JMSDeliveryMode
      • JMSPriority
      • JMSMessageID
      • JMSTimestamp
      • JMSCorrelationID
      • JMSType

      JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType values can be null, and if so, are treated as a NULL value.

    • Any name beginning with JMSX is a JMS-defined property name.
    • Any name beginning with JMS_ is a provider-specific property name.
    • Any name that does not begin with JMS is an application-specific property name. If there is a reference to a property that does not exist in a message, its value is NULL. If it does exist, its value is the corresponding property value.

  • White space is the same as it is defined for Java: space, horizontal tab, form feed, and line terminator.
  • Expressions:

    • A selector is a conditional expression. A selector that evaluates to true matches; a selector that evaluates to false or unknown does not match.
    • Arithmetic expressions are composed of themselves, arithmetic operations, identifiers (with a value that is treated as a numeric literal), and numeric literals.
    • Conditional expressions are composed of themselves, comparison operations, and logical operations.

  • Standard bracketing (), to set the order in which expressions are evaluated, is supported.
  • Logical operators in precedence order: NOT, AND, OR.
  • Comparison operators: =, >, >=, <, <=, <> (not equal).

    • Only values of the same type can be compared. One exception is that it is valid to compare exact numeric values and approximate numeric values. (The type conversion required is defined by the rules of Java numeric promotion.) If there is an attempt to compare different types, the selector is always false.
    • String and Boolean comparison is restricted to = and <>. Two strings are equal only if they contain the same sequence of characters.

  • Arithmetic operators in precedence order:

    • +, - unary.
    • *, /, multiplication, and division.
    • +, -, addition, and subtraction.
    • Arithmetic operations on a NULL value are not supported. If they are attempted, the complete selector is always false.
    • Arithmetic operations must use Java numeric promotion.

  • arithmetic-expr1 [NOT] BETWEEN arithmetic-expr2 and arithmetic-expr3 comparison operator:

    • Age BETWEEN 15 and 19 is equivalent to age >= 15 AND age <= 19.
    • Age NOT BETWEEN 15 and 19 is equivalent to age < 15 OR age> 19.
    • If any of the expressions of a BETWEEN operation are NULL, the value of the operation is false. If any of the expressions of a NOT BETWEEN operation are NULL, the value of the operation is true.

  • identifier [NOT] IN (string-literal1, string-literal2,...) comparison operator where identifier has a String or NULL value.

    • Country IN ('UK', 'US', 'France') is true for 'UK' and false for 'Peru'. It is equivalent to the expression (Country = 'UK') OR (Country = 'US') OR (Country = 'France').
    • Country NOT IN ('UK', 'US', 'France') is false for 'UK' and true for 'Peru'. It is equivalent to the expression NOT ((Country = 'UK') OR (Country = 'US') OR (Country = 'France')).
    • If the identifier of an IN or NOT IN operation is NULL, the value of the operation is unknown.

  • identifier [NOT] LIKE pattern-value [ESCAPE escape-character] comparison operator, where identifier has a string value. pattern-value is a string literal, where _ stands for any single character and % stands for any sequence of characters (including the empty sequence). All other characters stand for themselves. The optional escape-character is a single character string literal, with a character that is used to escape the special meaning of the _ and % in pattern-value.

    • phone LIKE '12%3' is true for 123 and 12993 and false for 1234.
    • word LIKE 'l_se' is true for "lose" and false for "loose".
    • underscored LIKE '\_%' ESCAPE '\' is true for "_foo" and false for "bar".
    • phone NOT LIKE '12%3' is false for 123 and 12993 and true for 1234.
    • If the identifier of a LIKE or NOT LIKE operation is NULL, the value of the operation is unknown.

  • identifier IS NULL comparison operator tests for a null header field value, or a missing property value.

    • prop_name IS NULL.

  • identifier IS NOT NULL comparison operator tests for the existence of a non-null header field value or a property value.

    • prop_name IS NOT NULL.


Example of a message selector

The following message selector selects messages with a message type of car, color of blue, and weight greater than 2500 lbs:
"JMSType = 'car' AND color = 'blue' AND weight > 2500"


NULL property values

As noted in the preceding list, property values can be NULL. The evaluation of selector expressions that contain NULL values is defined by SQL 92 NULL semantics. The following list gives a brief description of these semantics:

  • SQL treats a NULL value as unknown.
  • Comparison or arithmetic with an unknown value always yields an unknown value.
  • The IS NULL operator converts an unknown value into a TRUE value.
  • The IS NOT NULL operator converts an unknown value into a FALSE value.


Special behavior of JMSMessageID and JMSCorrelationID

The IBM MQ classes for JMS contain optimizations when selecting messages from a queue based on either JMSMessageID or JMSCorrelationID.

If an application specifies a selector of the form:

  • JMSMessageID='ID:message_id'

where message_id is a String containing a standard IBM MQ message identifier, then the IBM MQ classes for JMS use the MatchOption MQMO_MATCH_MSG_ID to get the message with the specified message identifier. For example, to get a message with the message identifier 414D51207061756C745639314C545320C57C1A5F25ECE602 from a queue, an application should use the following message selector:

JMSMessageID='ID:414D51207061756C745639314C545320C57C1A5F25ECE602'
Similarly, if the application specifies a selector that has the format:

  • JMSCorrelationID ='ID:correlation_id'

where correlation_id is a String containing a standard IBM MQ correlation identifier, the IBM MQ classes for JMS use the MatchOption MQMO_MATCH_CORREL_ID to get the message with the specified correlation identifier from the queue. In the following example, a message selector is used to get a message that has a correlation identifier of 414D51207061756C745639314C545320846E5B5F25B1CC02:

JMSCorrelationID='ID:414D51207061756C745639314C545320846E5B5F25B1CC02'
If a message selector contains a value of all zeros for either the message_id or correlation_id, then it matches any message on the queue. For example, if an application is using the selector:
JMSMessageID='ID:000000000000000000000000000000000000000000000000'
then any message on the queue is considered a match and returned to the application.

For more information about the MQMO_MATCH_MSG_ID and MQMO_MATCH_CORREL_ID MatchOptions, see MatchOptions (MQLONG).


Restrictions

Although SQL supports fixed decimal comparison and arithmetic, JMS message selectors do not. This is why exact numeric literals are restricted to those without a decimal. It is also why there are numerics with a decimal as an alternative representation for an approximate numeric value.

SQL comments are not supported.

Parent topic: JMS messages