| = Filter Expressions |
| :idprefix: |
| :idseparator: - |
| :docinfo: shared |
| |
| {project-name-full} provides a powerful filter language based on a subset of the SQL 92 expression syntax. |
| |
| It is the same as the syntax used for JMS & Jakarta Messaging selectors, but the predefined identifiers are different. |
| For documentation on JMS selector syntax please see the JavaDoc for https://docs.oracle.com/javaee/7/api/javax/jms/Message.html[`javax.jms.Message`]. |
| For the corresponding Jakarta Messaging JavaDoc see https://jakarta.ee/specifications/messaging/3.0/apidocs/jakarta/jms/message[`jakarta.jms.Message`]. |
| |
| Filter expressions are used in several places: |
| |
| * Predefined Queues. |
| When pre-defining a queue, in `broker.xml` in either the core or jms configuration a filter expression can be defined for a queue. |
| Only messages that match the filter expression will enter the queue. |
| * Core bridges can be defined with an optional filter expression, only matching messages will be bridged (see xref:core-bridges.adoc#core-bridges[Core Bridges]). |
| * Diverts can be defined with an optional filter expression, only matching messages will be diverted (see xref:diverts.adoc#diverting-and-splitting-message-flows[Diverts]). |
| * Filters are also used programmatically when creating consumers, queues and in several places as described in xref:management.adoc#management[management]. |
| |
| There are some differences between JMS selector expressions and Core filter expressions. |
| Whereas JMS selector expressions operate on a JMS message, Core filter expressions operate on a core message. |
| |
| The following identifiers can be used in a core filter expressions to refer to attributes of the core message in an expression: |
| |
| AMQUserID:: |
| The ID set by the user when the message is sent. |
| This is analogous to the `JMSMessageID` for JMS-based clients. |
| |
| AMQAddress:: |
| The address to which the message was sent. |
| |
| AMQGroupID:: |
| The group ID used when sending the message. |
| |
| AMQPriority:: |
| To refer to the priority of a message. |
| Message priorities are integers with valid values from `0 - 9`. |
| `0` is the lowest priority and `9` is the highest. |
| e.g. `AMQPriority = 3 AND animal = 'aardvark'` |
| |
| AMQExpiration:: |
| To refer to the expiration time of a message. |
| The value is a long integer. |
| |
| AMQDurable:: |
| To refer to whether a message is durable or not. |
| The value is a string with valid values: `DURABLE` or `NON_DURABLE`. |
| |
| AMQTimestamp:: |
| The timestamp of when the message was created. |
| The value is a long integer. |
| |
| AMQSize:: |
| The size of a message in bytes. |
| The value is an integer. |
| |
| Any other identifiers used in core filter expressions will be assumed to be properties of the message. |
| |
| The JMS and Jakarta Messaging specs state that a String property should not get converted to a numeric when used in a selector. |
| So for example, if a message has the `age` property set to `String` `21` then the following selector should not match it: `age > 18`. |
| STOMP clients, for example, can only send messages with string properties, which is a bit limiting. |
| Therefore, if you want your filter expressions to auto-convert `String` properties to the appropriate number type, just prefix it with `convert_string_expressions:`. |
| If you changed the filter expression in the previous example to be `convert_string_expressions:age > 18`, then it would match the aforementioned message. |
| |
| The JMS and Jakarta Messaging specs also state that property identifiers (and therefore the identifiers which are valid for use in a filter expression) are an: |
| |
| ____ |
| unlimited-length sequence of letters and digits, the first of which must be a 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`. |
| ____ |
| |
| This constraint means that hyphens (i.e. `-`) cannot be used. |
| However, this constraint can be overcome by using the `hyphenated_props:` prefix. |
| For example, if a message had the `foo-bar` property set to `0` then the filter expression `hyphenated_props:foo-bar = 0` would match it. |
| |
| == XPath |
| |
| Special https://en.wikipedia.org/wiki/XPath[XPath] filters which operate on the _body_ of a message are also available. |
| The body must be XML. |
| To use an XPath filter use this syntax: |
| |
| ---- |
| XPATH '<xpath-expression>' |
| ---- |
| |
| XPath filters are supported with and between producers and consumers using the following protocols: |
| |
| * OpenWire JMS |
| * Core (and Core JMS) |
| * STOMP |
| * AMQP |
| |
| Since XPath applies to the body of the message and requires parsing of XML *it may be significantly slower* than normal filters. |
| |
| Large messages are *not* supported. |
| |
| The XML parser used for XPath is configured with these default "features": |
| |
| * `+http://xml.org/sax/features/external-general-entities+`: `false` |
| * `+http://xml.org/sax/features/external-parameter-entities+`: `false` |
| * `+http://apache.org/xml/features/disallow-doctype-decl+`: `true` |
| |
| However, in order to deal with any implementation-specific issues the features can be customized by using system properties starting with the `org.apache.activemq.documentBuilderFactory.feature:` prefix, e.g.: |
| |
| ---- |
| -Dorg.apache.activemq.documentBuilderFactory.feature:http://xml.org/sax/features/external-general-entities=true |
| ---- |