In previous posts explaining the enterprise integration patterns with example Mule configuration I have covered Content-Enricher and Content-based Routing patterns, today I’ll talking about the “Message Filter” pattern.
How can a component avoid receiving uninteresting messages?
Use a special kind of Message Router, a Message Filter, to eliminate undesired messages from a channel based on a set of criteria.
The Message Filter has a single input channel and a single output channel. If the message matches the criteria specified by the Message Filter, the message from the input channel is routed to the output channel. If the message content does not match the criteria, the message is discarded.
Mule Message Filters
Mule has a slightly lower-level concept of a filter: that it evaluates to true or false based on criteria configured on the filter. These filters are used in a few different places, but all, implement the base Filter interface:
- Transport-specific Filters: Some inbound endpoints allow the use of transport-specific filters which are used to determine whether an incoming message should even be created. There are only a few examples of this type of filter. One example is that the file and ftp transports allow the use of a filename filter on inbound endpoints. File whose names do not match the filter are ignored.
- Filters used for Routing: Filters are also used by some Message Routers. For example, the Content-Based Router that I talked about last time uses filters to determine whether a message should be routed to a specific destination.
- Message Filters: These filters are used within a flow to determine whether to continue processing or discard messages.
In this blog post we’ll focus on the last of these uses, which corresponds directly to this enterprise integration pattern.
While Message Filters in Mule directly implement the pattern as defined above, in Mule 3 they also have some additional functionality allowing you to optionally define where unaccepted messages should go (by default they are dropped) and if an exception should be thrown (by default not exception is thrown).
With filters you can assert all sorts of conditions on the current message, such the message contents, the presence or value of message headers, and even the current attachments. Mule provides many filter implementations out of the box, the most powerful being the expression-filter which leverages Mule Expressions to allow filters that evaluate expressions such as XPATH, Groovy, and OGNL. There are also filters to test the payload, headers, attachments or exception type and of course you can also define custom filters. See Using Filters for more details.
The easiest way to configure a message filter in Mule is by simply using the various filter elements that are available directly within your endpoints or flows and they will automatically be used as message filters.
Note: Whether you configure them on your endpoints or in your Flow is just a matter of when the filter gets applied.
The following example show the use of an expression-filter that uses xpath to accept only messages with an order type of ‘book’. These messages are bridged from the JMS inQueue to outQueue; all others are discarded.
In this next example, the filter is instead configured on a globally defined endpoint. This filter discards all incoming http requests that don’t contain the HTTP header myHeader with a value of ‘true’. Message that do have this header with the correct value will continue to be processed and the custom component ‘org.my.CustomClass’ will be invoked.
The above examples show the shorthand approach to configuring a message filter, which uses the same elements used when configuring a filter for routers. There is also a slightly more verbose approach using the <message-filter/> element with a child filter element. The advantage of this it also allows you to extend the message filter pattern by optionally configuring the onUnaccepted and throwOnUnaccepted attributes. The following snippet show how this is used:
This example is the same as the very first one, but here instead of discarding unaccepted messages, we send them to another flow or message processor, referenced by name, to be processed. (The use of globally defined endpoints is not supported yet) If throwOnUnaccepted had been set to “true” instead of “false”, the filter, instead of simply discarding messages which are not accepted, would cause an exception to be thrown. This using <message-filter/> gives you three ways to handle unaccepted messages:
- Discard them (the default)
- Process them with another message processor
- Throw an exception
Filters can also be configured globally and reused. Their configuration is the same as when used in-line but they also need a name to be referenced by. The following snippet gives an example:
You’ll notice that simple filters are referenced using the filter element, which message-filters are referenced using the processor element.
I hope this post provided a good, concise explanation of this pattern along with all you need to begin using it in your Mule Flows. Next time I plan to cover message transformation. Please be sure to comment with questions on this post or to suggest future posts. If you aren’t already a Mule user then I recommend you download Mule and seeing how easy it is to build integration using Mule Flows and Integration Patterns.