| [[DynamicRouter-DynamicRouter]] | 
 | = Dynamic Router | 
 | :page-source: core/camel-core-engine/src/main/docs/eips/dynamic-router.adoc | 
 |  | 
 | The | 
 | http://www.enterpriseintegrationpatterns.com/DynamicRouter.html[Dynamic | 
 | Router] from the EIP patterns | 
 | allows you to route messages while avoiding the dependency of the router | 
 | on all possible destinations while maintaining its efficiency. | 
 |  | 
 | image::eip/DynamicRouter.gif[image] | 
 |  | 
 | The `dynamicRouter` in the DSL is similar to | 
 | a dynamic Routing Slip which evaluates the slip | 
 | _on-the-fly_. | 
 |  | 
 | WARNING: *Beware* | 
 | You must ensure the expression used for the `dynamicRouter` such as a | 
 | bean, will return `null` to indicate the end. Otherwise the | 
 | `dynamicRouter` will keep repeating endlessly. | 
 |  | 
 | [[DynamicRouter-Options]] | 
 | == Options | 
 |  | 
 | [width="100%",cols="10%,10%,80%",options="header",] | 
 | |======================================================================= | 
 | |Name |Default Value |Description | 
 |  | 
 | |`uriDelimiter` |`,` |Delimiter used if the Expression returned multiple | 
 | endpoints. | 
 |  | 
 | |`ignoreInvalidEndpoints` |`false` |If an endpoint uri could not be resolved, should it be ignored. | 
 | Otherwise Camel will thrown an exception stating the endpoint uri is not | 
 | valid. | 
 |  | 
 | |`cacheSize` |`1000` |Allows to configure the cache size for the | 
 | `ProducerCache` which caches producers for reuse in the routing slip. | 
 | Will by default use the default cache size which is 1000. Setting the | 
 | value to -1 allows to turn off the cache all together. | 
 | |======================================================================= | 
 |  | 
 | [[DynamicRouter-DynamicRouterinCamel2.5onwards]] | 
 | == Dynamic Router in Camel 2.5 onwards | 
 |  | 
 | The Dynamic Router will set a | 
 | property (Exchange.SLIP_ENDPOINT) on the Exchange | 
 | which contains the current endpoint as it advanced though the slip. This | 
 | allows you to know how far we have processed in the slip. (It's a slip | 
 | because the Dynamic Router implementation is | 
 | based on top of Routing Slip). | 
 |  | 
 | [[DynamicRouter-JavaDSL]] | 
 | == Java DSL | 
 |  | 
 | In Java DSL you can use the `dynamicRouter` as shown below: | 
 |  | 
 | [source,java] | 
 | ---- | 
 | from("direct:start") | 
 |     // use a bean as the dynamic router | 
 |     .dynamicRouter(method(DynamicRouterTest.class, "slip")); | 
 | ---- | 
 |  | 
 | Which will leverage a xref:components::bean-component.adoc[Bean] to compute the slip | 
 | _on-the-fly_, which could be implemented as follows: | 
 |  | 
 | [source,java] | 
 | ---- | 
 | /** | 
 |  * Use this method to compute dynamic where we should route next. | 
 |  * | 
 |  * @param body the message body | 
 |  * @return endpoints to go, or <tt>null</tt> to indicate the end | 
 |  */ | 
 | public String slip(String body) { | 
 |     bodies.add(body); | 
 |     invoked++; | 
 |   | 
 |     if (invoked == 1) { | 
 |         return "mock:a"; | 
 |     } else if (invoked == 2) { | 
 |         return "mock:b,mock:c"; | 
 |     } else if (invoked == 3) { | 
 |         return "direct:foo"; | 
 |     } else if (invoked == 4) { | 
 |         return "mock:result"; | 
 |     } | 
 |   | 
 |     // no more so return null | 
 |     return null; | 
 | } | 
 | ---- | 
 |  | 
 | Mind that this example is only for show and tell. The current | 
 | implementation is not thread safe. You would have to store the state on | 
 | the Exchange, to ensure thread safety, as shown | 
 | below: | 
 |  | 
 | [source,java] | 
 | ---- | 
 | /** | 
 |  * Use this method to compute dynamic where we should route next. | 
 |  * | 
 |  * @param body the message body | 
 |  * @param properties the exchange properties where we can store state between invocations | 
 |  * @return endpoints to go, or <tt>null</tt> to indicate the end | 
 |  */ | 
 | public String slip(String body, @Properties Map<String, Object> properties) { | 
 |     bodies.add(body); | 
 |   | 
 |     // get the state from the exchange properties and keep track how many times | 
 |     // we have been invoked | 
 |     int invoked = 0; | 
 |     Object current = properties.get("invoked"); | 
 |     if (current != null) { | 
 |         invoked = Integer.valueOf(current.toString()); | 
 |     } | 
 |     invoked++; | 
 |     // and store the state back on the properties | 
 |     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:foo"; | 
 |     } else if (invoked == 4) { | 
 |         return "mock:result"; | 
 |     } | 
 |   | 
 |     // no more so return null | 
 |     return null; | 
 | } | 
 | ---- | 
 |  | 
 | You could also store state as message headers, but they are not | 
 | guaranteed to be preserved during routing, where as properties on the | 
 | Exchange are. Although there was a bug in the method | 
 | call expression, see the warning below. | 
 |  | 
 | [[DynamicRouter-SpringXML]] | 
 | == Spring XML | 
 |  | 
 | The same example in Spring XML would be: | 
 |  | 
 | [source,xml] | 
 | ---- | 
 | <bean id="mySlip" class="org.apache.camel.processor.DynamicRouterTest"/> | 
 |   | 
 | <camelContext xmlns="http://camel.apache.org/schema/spring"> | 
 |     <route> | 
 |         <from uri="direct:start"/> | 
 |         <dynamicRouter> | 
 |             <!-- use a method call on a bean as dynamic router --> | 
 |             <method ref="mySlip" method="slip"/> | 
 |         </dynamicRouter> | 
 |     </route> | 
 |   | 
 |     <route> | 
 |         <from uri="direct:foo"/> | 
 |         <transform><constant>Bye World</constant></transform> | 
 |     </route> | 
 |   | 
 | </camelContext> | 
 | ---- | 
 |  | 
 | [[DynamicRouter-DynamicRouterannotation]] | 
 | == @DynamicRouter annotation | 
 |  | 
 | You can also use the `@DynamicRouter` annotation. The `route` method would | 
 | then be invoked repeatedly as the message is processed dynamically. The | 
 | idea is to return the next endpoint uri where to go. Return `null` to | 
 | indicate the end. You can return multiple endpoints if you like, just as | 
 | the Routing Slip, where each endpoint is | 
 | separated by a delimiter. | 
 |  | 
 | [source,java] | 
 | ---- | 
 | public class MyDynamicRouter { | 
 |  | 
 |     @Consume(uri = "activemq:foo") | 
 |     @DynamicRouter | 
 |     public String route(@XPath("/customer/id") String customerId, @Header("Location") String location, Document body) { | 
 |         // query a database to find the best match of the endpoint based on the input parameteres | 
 |         // return the next endpoint uri, where to go. Return null to indicate the end. | 
 |     } | 
 | } | 
 | ---- | 
 |  | 
 | In the above we can use the | 
 | Parameter Binding Annotations | 
 | to bind different parts of the Message to method | 
 | parameters or use an Expression such as using | 
 | xref:components::xpath-language.adoc[XPath] or xref:components::xpath-language.adoc[XQuery]. | 
 |  | 
 | The method can be invoked in a number of ways as described in the | 
 | Bean Integration such as | 
 |  | 
 | * POJO Producing | 
 | * Spring Remoting | 
 | * xref:components::bean-component.adoc[Bean] component | 
 |  |