Choice
The Content Based Router from the EIP patterns allows you to route messages to the correct destination based on the contents of the message exchanges.
Choice options
The Choice eip supports 2 options, which are listed below.
Name | Description | Default | Type |
---|---|---|---|
when |
Sets the when nodes. |
List |
|
otherwise |
Sets the otherwise node. |
OtherwiseDefinition |
|
description |
Sets the description of this node. |
DescriptionDefinition |
Example
The Camel Simple language is great to use with the Choice EIP when routing is based on the content of the message, such as checking message headers.
from("direct:a")
.choice()
.when(simple("${header.foo} == 'bar'"))
.to("direct:b")
.when(simple("${header.foo} == 'cheese'"))
.to("direct:c")
.otherwise()
.to("direct:d");
And the same example using XML DSL:
<route>
<from uri="direct:a"/>
<choice>
<when>
<simple>${header.foo} == 'bar'</simple>
<to uri="direct:b"/>
</when>
<when>
<simple>${header.foo} == 'cheese'</simple>
<to uri="direct:c"/>
</when>
<otherwise>
<to uri="direct:d"/>
</otherwise>
</choice>
</route>
Why can I not use otherwise in Java DSL
When using the Choice EIP in the Java DSL you may have a situation where the compiler will not accept
when()
or otherwise()
statements.
For example as shown in the route below where we use the Load Balancer EIP inside the Choice EIP in the first when:
Code will not compile
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar")
.otherwise()
.to("mock:result");
Well the first issue is that the Load Balancer EIP uses the additional routing to know what to use in the load balancing. In this example that would be the:
.to("mock:foo").to("mock:bar")
To indicate when the balancing stops, you should use .end()
to denote
the end. So the route is updates as follows:
Code will still not compile
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar").end()
.otherwise()
.to("mock:result");
However, the code will still not compile.
The reason is we have stretched how far we can take the good old Java language in terms of
DSL. In a more dynamic or modern language such as Kotlin or Groovy
you would be able to let it be stack based, so the .end()
will pop the last type of the
stack, and you would return to the scope of the Choice EIP.
That’s not doable in Java. So we need to help Java a bit, which you do by
using .endChoice()
, which tells Camel to "pop the stack" and return
to the scope of the Choice EIP.
Code compiles
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar").endChoice()
.otherwise()
.to("mock:result");
You only need to use .endChoice()
when using certain
EIPs which often have additional
methods to configure or as part of the EIP itself. For example the
Split EIP has a sub-route which denotes the
routing of each splitted message. You would also have to use
.endChoice()
to indicate the end of the sub-route and to return
to the Choice EIP.
Still problems
If there are still problems, then you can split your route into multiple routes, and link them together using the Direct component.
There can be some combinations of EIPs that can hit limits in how far we can take the fluent builder DSL with generics you can do in Java programming language.