Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id AD9CB200BAE for ; Fri, 28 Oct 2016 12:00:59 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id AC50A160ADD; Fri, 28 Oct 2016 10:00:59 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id C9F0F160AE3 for ; Fri, 28 Oct 2016 12:00:58 +0200 (CEST) Received: (qmail 12506 invoked by uid 500); 28 Oct 2016 10:00:58 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 12395 invoked by uid 99); 28 Oct 2016 10:00:58 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 28 Oct 2016 10:00:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id BEFF0EFE5E; Fri, 28 Oct 2016 10:00:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: acosentino@apache.org To: commits@camel.apache.org Date: Fri, 28 Oct 2016 10:00:59 -0000 Message-Id: <346df67684524990b6da1be4045dce04@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/3] camel git commit: Added Dynamic Router docs to Gitbook archived-at: Fri, 28 Oct 2016 10:00:59 -0000 Added Dynamic Router docs to Gitbook Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cbebae83 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cbebae83 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cbebae83 Branch: refs/heads/master Commit: cbebae831aebf8c25741e34dc58fc5362a54d64d Parents: 8349ee7 Author: Andrea Cosentino Authored: Fri Oct 28 11:59:59 2016 +0200 Committer: Andrea Cosentino Committed: Fri Oct 28 11:59:59 2016 +0200 ---------------------------------------------------------------------- camel-core/src/main/docs/dynamic-router.adoc | 246 ++++++++++++++++++++++ docs/user-manual/en/SUMMARY.md | 1 + 2 files changed, 247 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/cbebae83/camel-core/src/main/docs/dynamic-router.adoc ---------------------------------------------------------------------- diff --git a/camel-core/src/main/docs/dynamic-router.adoc b/camel-core/src/main/docs/dynamic-router.adoc new file mode 100644 index 0000000..e97b900 --- /dev/null +++ b/camel-core/src/main/docs/dynamic-router.adoc @@ -0,0 +1,246 @@ +[[DynamicRouter-DynamicRouter]] +Dynamic Router +~~~~~~~~~~~~~~ + +The +http://www.enterpriseintegrationpatterns.com/DynamicRouter.html[Dynamic +Router] from the link:enterprise-integration-patterns.html[EIP patterns] +allows you to route messages while avoiding the dependency of the router +on all possible destinations while maintaining its efficiency. + +image:http://www.enterpriseintegrationpatterns.com/img/DynamicRouter.gif[image] + +In *Camel 2.5* we introduced a `dynamicRouter` in the DSL which is like +a dynamic link:routing-slip.html[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 link:expression.html[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` |*Camel 2.13.1/2.12.4:* 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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +From Camel 2.5 the link:dynamic-router.html[Dynamic Router] will set a +property (Exchange.SLIP_ENDPOINT) on the link:exchange.html[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 link:dynamic-router.html[Dynamic Router] implementation is +based on top of link:routing-slip.html[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 link:bean.html[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 null 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 link:exchange.html[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 null to indicate the end + */ +public String slip(String body, @Properties Map 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 +link:exchange.html[Exchange] are. Although there was a bug in the method +call expression, see the warning below. + +WARNING:*Using beans to store state* +Mind that in Camel 2.9.2 or older, when using a link:bean.html[Bean] the +state is not propagated, so you will have to use a +link:processor.html[Processor] instead. This is fixed in Camel 2.9.3 +onwards. + +[[DynamicRouter-SpringXML]] +Spring XML +++++++++++ + +The same example in Spring XML would be: + +[source,xml] +----------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + Bye World + + + +----------------------------------------------------------------------------------------------------------------------- + +[[DynamicRouter-DynamicRouterannotation]] +@DynamicRouter annotation ++++++++++++++++++++++++++ + +You can also use the `@DynamicRouter` annotation, for example the Camel +2.4 example below could be written as follows. 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 link:routing-slip.html[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. + } +} +----------------------------------------------------------------------------------------------------------------------- + +[[DynamicRouter-DynamicRouterinCamel2.4orolder]] +Dynamic Router in Camel 2.4 or older +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The simplest way to implement this is to use the +link:recipientlist-annotation.html[RecipientList Annotation] on a Bean +method to determine where to route the message. + +[source,java] +----------------------------------------------------------------------------------------------------------------------------- +public class MyDynamicRouter { + + @Consume(uri = "activemq:foo") + @RecipientList + public List 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 + ... + } +} +----------------------------------------------------------------------------------------------------------------------------- + +In the above we can use the +link:parameter-binding-annotations.html[Parameter Binding Annotations] +to bind different parts of the link:message.html[Message] to method +parameters or use an link:expression.html[Expression] such as using +link:xpath.html[XPath] or link:xquery.html[XQuery]. + +The method can be invoked in a number of ways as described in the +link:bean-integration.html[Bean Integration] such as + +* link:pojo-producing.html[POJO Producing] +* link:spring-remoting.html[Spring Remoting] +* link:bean.html[Bean] component + +[[DynamicRouter-UsingThisPattern]] +Using This Pattern +++++++++++++++++++ + +If you would like to use this EIP Pattern then please read the +link:getting-started.html[Getting Started], you may also find the +link:architecture.html[Architecture] useful particularly the description +of link:endpoint.html[Endpoint] and link:uris.html[URIs]. Then you could +try out some of the link:examples.html[Examples] first before trying +this pattern out. http://git-wip-us.apache.org/repos/asf/camel/blob/cbebae83/docs/user-manual/en/SUMMARY.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index bf4fef1..6d74c3f 100644 --- a/docs/user-manual/en/SUMMARY.md +++ b/docs/user-manual/en/SUMMARY.md @@ -95,6 +95,7 @@ * Message Routing * [Content Based Router](content-based-router.adoc) * [Message Filter](message-filter.adoc) + * [Dynamic Router](dynamic-router.adoc) * Community * FAQ