- Apache Camel Developer's Cookbook
- Scott Cranton Jakub Korab
- 648字
- 2025-02-24 23:14:00
Dynamic Routing – making routing decisions at runtime
When you need to route to a sequence of endpoints, and that list may change based on the response from any of those endpoints, a Dynamic Router can be a good solution. Similar to a Routing Slip, where a list of endpoints to route to is created and executed, the Dynamic Router can alter the next endpoint to route to, based on the results of previous endpoints via a feedback loop.

This recipe will show you how to efficiently route a message to endpoints by calling your code to make the routing decisions at runtime.
Getting ready
The Java code for this recipe is located in the org.camelcookbook.routing.dynamicrouter
package. The Spring XML files are located under src/main/resources/META-INF/spring
and prefixed with dynamicRouter
.
How to do it...
There are two steps for a Dynamic Router: create a route consumer and optionally transform the message in preparation for dynamic routing, and call the Dynamic Router Expression (most commonly a Java method through the Method Expression Language).
- Create a route and optionally transform the message in preparation for the initial call to the Dynamic Router Expression. The
dynamicRouter
takes an Expression that will most often be a call to a Java method. It must returnnull
to indicate that routing is finished.In the XML DSL, this logic is written as:
<route> <from uri="direct:start"/> <dynamicRouter> <method ref="myDynamicRouter" method="routeMe"/> </dynamicRouter> </route>
In the Java DSL, the same thing is expressed as:
from("direct:start") .dynamicRouter(method(MyDynamicRouter.class, "routeMe"));
- Create the Dynamic Router. In this example, we're calling a Java method, and we're using Camel's Bean Injection capabilities to pass parts of the exchange to the Java method versus the entire exchange for cleaner code.
public String routeMe(String body, @Properties Map<String, Object> properties) { // store a property with the message exchange // this will drive the routing decisions of this // Dynamic Router implementation int invoked = 0; // property will be null on first call Object current = properties.get("invoked"); if (current != null) { invoked = Integer.valueOf(current.toString()); } invoked++; properties.put("invoked", invoked); if (invoked == 1) { return "mock:a"; } else if (invoked == 2) { return "mock:b,mock:c"; } else if (invoked == 3) { return "direct:other"; } else if (invoked == 4) { return "mock:result"; } // no more, so return null return null; }
How it works...
The Dynamic Router uses an Expression to do the routing. This Expression will be called repeatedly, once after Camel calls the endpoint URIs returned from the last Expression invocation. When routing is finished, the Expression must return null
.
In the Dynamic Router EIP, this Expression keeps getting called until this condition is met, so it is very important to test that your Expression ultimately returns null
, otherwise your route will loop infinitely.
If the Expression returns a list of endpoint URIs, these will be called in sequence. The Expression may separate the URIs with a delimiter, which, by default, is a comma (,
). The separator can be changed using the uriDelimiter
attribute of the dynamicRouter
DSL statement.
There's more...
As it is so common for the Dynamic Router to be a Java method, we can use Camel's Bean Injection capabilities to put everything into the Java class using Java Annotations. The @DynamicRouter
annotation provides the same information to Camel as the dynamicRouter
statement within a Camel route. See Chapter 3, Routing to Your Code, for more details on Camel's strong integration with your Java code.
The @Consume
annotation tells Camel to create a new route consuming on the provided endpoint URI; there is no need to provide a separate route definition.
@Consume(uri = "direct:dynamicRouteAnnotated") @DynamicRouter(delimiter = ",") public String routeMe(String body, @Properties Map<String, Object> properties) { // ... }
See also
- Dynamic Router: http://camel.apache.org/dynamic-router.html
- Bean Injection: http://camel.apache.org/bean-integration.html
- Bean Binding: http://camel.apache.org/bean-binding.html
- Expression: http://camel.apache.org/expression.html