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.

image

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.