Camel's choice() and when() - with examples
Apache Camel contains a powerful feature called the Content Based Router. This allows you to process messages differently based on their content. In this article I’m going to show you how to use the Content Based Router and show you the different options available for writing your conditions. Along the way there’s also some some example code.
The Basics
When you need to conditionally route a message based on some fact, you can use the choice
and when
constructs.
These are quite similar to the if/else
construct in Java. However, in Camel, the equivalent words are when
and otherwise
.
A typical if/else block in Java might look something like this:
if (condition) {
// ... do something ...
} else if (condition) {
// ... do something else ...
} else {
// otherwise do this
}
But in Camel’s Java DSL, it would look something like this:
from(anEndpoint)
.choice()
.when(someCondition).to(firstEndpoint)
.when(anotherCondition).to(secondEndpoint)
.otherwise()
.to(thirdEndpoint)
.end();
Notice how:
-
We start the block with
choice()
- this tells Camel that the following lines will contain some conditions to evaluate. -
Each
when()
method indicates a new condition to be evaluated, similar to anif
in core Java -
The method
otherwise()
defines what to do when none of the previouswhen()
conditions equaltrue
. -
The block ends with a
.end()
.
How to build a when condition in Camel
You have many different options available to you when writing your when()
condition. In Camel, this is called building a predicate. You can use several languages to build your predicate, but the most common ones are:
-
Simple language, Camel’s own language for building simple string comparisons
-
Header, for building a condition based on the value of a Header on the Exchange
-
Bean language, when you want to use the result of a Java method call
-
XPath or JSONPath, when you want to search in an XML document or JSON document
(For a complete list of the languages supported, see the languages entry in the Camel documentation.)
Example Camel predicates
Here are some examples of Predicates in Camel, along with their meaning:
Example predicate | What it does |
---|---|
.when(body().contains("Hello, world!")) |
When the Body of the message contains the string "Hello, world!" |
.when().simple("${body} == 'Disco'") |
Using the Simple language to test when the Body of the message is exactly "Disco" |
.when(header("country").isEqualTo("GB")) |
When a Header with the name country equals "GB" |
.when(header("CamelFileName") .isEqualTo("disco.txt")) |
Using the File component, check that the name of the received file is disco.txt |
.when(header("CamelFileName").endsWith(".xml")) |
Using the File component, using PredicateBuilder.endsWith() to check that the name of the file received ends with .xml |
.when(header("country").regex("US|FR|DE")) |
Using Camel’s regex method, check that the value of the Header with the name country is one of US , FR or DE . |
.when(xpath("/customer/@status = 'gold'")) |
Using Camel’s XPath support, check that the value of the status attribute on the customer element is equal to gold |
Adding actions to your when() condition
Each when()
condition basically builds a mini-pipeline. You can follow a when()
with to()
, to tell Camel to route the message to an endpoint, based on a certain condition.
For example, the code fragment below will route a message to an ActiveMQ queue called hello
if it contains the text Hello, world!
:
.when(body().contains("Hello, world!")).to("activemq:queue:hello")
You can also stack multiple Camel DSL functions in your mini-pipeline, in the same way as you would write multiple statements in an if
block in Java.
Here’s an example of using multiple statements in a when()
condition. It changes the body of the message using the setBody()
method, before writing it out to a folder on disk, using the File component:
.when(body().contains("Hello, world!"))
.setBody(simple("Goodbye, world!"))
.to("file:customers/out/goodbye")
Using ‘otherwise’ to specify your ‘else’ block
Once you’ve defined all of your when()
conditions and actions, you might want to define an action that should be taken if your message does not match the previous conditions.
Just like an else
statement, Camel’s otherwise
allows you to do this. For example, you might want to log the message, or move it to a Dead Letter Queue.
.otherwise().to("activemq:queue:unprocessed")
Putting it all together
Now let’s put everything we’ve learned in this article into an example that shows how you might typically use choice()
and when()
in your Camel routes.
from("file:src/data?noop=true")
.to("log:ordersReceived")
.choice()
// If the customer has a type="business"
.when(xpath("/order/customer/@type = 'business'"))
.log("Business order received")
.to("file:out/business")
// If the customer has a type="personal"
.when(xpath("/order/customer/@type = 'personal'"))
.log("Personal order received")
.to("file:out/personal")
.otherwise()
.log("Other order received")
.to("file:out/others")
.end();
In the example above:
-
The route begins with an instruction to use the File component to read files from a location on disk (
src/data
) -
Information about the file received is written to the log, using the logger name
ordersReceived
. -
An XPath test is applied to the incoming file to check if it is a business customer order. If so, the file is moved to the
out/business
folder. -
A second test checks if the order is from a personal customer. If so, the file is moved to the
out/personal
folder. -
Finally, if neither of the above two conditions evaluate to
true
, the file is moved to theout/others
folder.
Has this helped you understand how to use when
, choice
and otherwise
in your Camel routes? Please post your feedback in the comments below!