This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 25fac54 CAMEL-16861: Cleanup and update EIP docs 25fac54 is described below commit 25fac54ab42f7b8333bc8d63c9752063c9a64aab Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Oct 7 17:42:31 2021 +0200 CAMEL-16861: Cleanup and update EIP docs --- .../docs/modules/eips/pages/multicast-eip.adoc | 249 ++++++++++++++++----- 1 file changed, 189 insertions(+), 60 deletions(-) diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/multicast-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/multicast-eip.adoc index 34acbe9..fe33060 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/multicast-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/multicast-eip.adoc @@ -5,10 +5,15 @@ :since: :supportlevel: Stable -The Multicast EIP allows to route the same message to a number of endpoints -and process them in a different way. The main difference between the -Multicast and Splitter is that Splitter will split the message into -several pieces but the Multicast will not modify the request message. +The Multicast EIP allows to route *the same* message to a number of xref:latest@manual:ROOT:endpoint.adoc[endpoints] +and process them in a different way. + +image::eip/RecipientListIcon.gif[image] + +The Multicast EIP has many features and is also used as baseline for +the xref:recipientList-eip.adoc[Recipient List] and xref:split-eip.adoc[Split] EIPs. +For example the Multicast EIP is capable of aggregating each multicasted message into a single +_response_ message as the result after the Multicast EIP. == Options @@ -16,116 +21,240 @@ several pieces but the Multicast will not modify the request message. include::partial$eip-options.adoc[] // eip options: END -== Multicast example +== Exchange properties + +The following properties are set on each Exchange that are multicasted: + +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Property | Type | Description +| `CamelMulticastIndex` | `int` | An index counter that increases for each Exchange being multicasted. The counter starts from 0. +| `MULTICAST_COMPLETE` | `boolean` |Whether or not this Exchange is the last. +|======================================================================= + +== Using Multicast + +The following example shows how to take a request from the direct:a +endpoint, then multicast these request to direct:x, direct:y, and direct:z. + +[source,java] +---- +from("direct:a") + .multicast() + .to("direct:x") + .to("direct:y") + .to("direct:z"); +---- + +And in XML: + +[source,xml] +---- +<route> + <from uri="direct:a"/> + <multicast> + <to uri="direct:b"/> + <to uri="direct:c"/> + <to uri="direct:d"/> + </multicast> +</route> +---- -The following example shows how to take a request from the *direct:a* -endpoint , then multicast these request to *direct:x*, *direct:y*, -*direct:z*. +By default, Multicast EIP runs in single threaded mode, which mean +that the next multicasted message is processed only when the previous is finished. +This means that direct:b must be done before Camel will call direct:c and so on. -== Using the fluent builder +=== Multicasting with parallel processing -By default Multicast invokes each endpoint sequentially. If parallel -processing is desired, simply use +You can enable parallel processing with Multicast EIP so each multicasted message +is processed by its own thread in parallel. + +The example below enabled parallel mode: [source,java] ---- -from("direct:a").multicast().parallelProcessing().to("direct:x", "direct:y", "direct:z"); +from("direct:a") + .multicast().paralllelProcessing() + .to("direct:x") + .to("direct:y") + .to("direct:z"); +---- + +And in XML: + +[source,xml] +---- +<route> + <from uri="direct:a"/> + <multicast parallelProcessing="true"> + <to uri="direct:b"/> + <to uri="direct:c"/> + <to uri="direct:d"/> + </multicast> +</route> ---- -In case of using InOut MEP, an AggregationStrategy is used for -aggregating all reply messages. The default is to only use the latest -reply message and discard any earlier replies. The aggregation strategy -is configurable: +=== Ending a Multicast block + +You may want to continue routing the exchange after the Multicast EIP. In Java DSL you need to use `end()` +to mark where multicast ends, and where other EIPs can be added to continue the route. + +In the example above then sending to mock:result happens after the Multicast EIP has finished. +In other words direct:y, direct:y, and direct:z should be completed first, before the message +continues. + +[source,java] +---- +from("direct:a") + .multicast().paralllelProcessing() + .to("direct:x") + .to("direct:y") + .to("direct:z") + .end() + .to("mock:result"); +---- + +And in XML its intuitive as `</multicast>` marks the end of the block: + +[source,xml] +---- +<route> + <from uri="direct:a"/> + <multicast parallelProcessing="true"> + <to uri="direct:b"/> + <to uri="direct:c"/> + <to uri="direct:d"/> + </multicast> + <to uri="mock:result"/> +</route> +---- + +=== Aggregating + +The `AggregationStrategy` is used for aggregating all the multicasted exchanges together +as a single response exchange, that becomes the outgoing exchange after the Multicast EIP block. + +The example now aggregates with the `MyAggregationStrategy` class: [source,java] ---- from("direct:start") - .multicast(new MyAggregationStrategy()) - .parallelProcessing().timeout(500).to("direct:a", "direct:b", "direct:c") + .multicast(new MyAggregationStrategy()).parallelProcessing().timeout(500) + .to("direct:x") + .to("direct:y") + .to("direct:z") .end() .to("mock:result"); ---- +And in XML we can refer to the FQN class name with `#class:` syntax as shown below: + +[source,xml] +---- +<route> + <from uri="direct:a"/> + <multicast parallelProcessing="true" timeout="5000" + strategyRef="#class:com.foo.MyAggregationStrategy"> + <to uri="direct:b"/> + <to uri="direct:c"/> + <to uri="direct:d"/> + </multicast> + <to uri="mock:result"/> +</route> +---- + [NOTE] ==== The Multicast, Recipient List, and Splitter EIPs have special support for using `AggregationStrategy` with access to the original input exchange. You may want to use this when you aggregate messages and there has been a failure in one of the messages, which you then want to enrich on the original -input message and return as response; its the aggregate method with 3 exchange parameters. +input message and return as response; it's the aggregate method with 3 exchange parameters. ==== -== Stop processing in case of exception +=== Stop processing in case of exception -The mutlicast EIP will by default continue to process +The Multicast EIP will by default continue to process the entire exchange even in case one of the multicasted messages will throw an exception during routing. + For example if you want to multicast to 3 destinations and the 2nd destination fails by an exception. What Camel does by default is to -process the remainder destinations. You have the chance to remedy or -handle this in the `AggregationStrategy`. +process the remainder destinations. You have the chance to deal with the exception +when aggregating using an `AggregationStrategy`. But sometimes you just want Camel to stop and let the exception be -propagated back, and let the Camel error handler handle it. You can do -this by specifying that it should stop in case of an +propagated back, and let the Camel xref:latest@manual:ROOT:error-handler.adoc[Error Handler] +handle it. You can do this by specifying that it should stop in case of an exception occurred. This is done by the `stopOnException` option as shown below: [source,java] ---- - from("direct:start") - .multicast() - .stopOnException().to("direct:foo", "direct:bar", "direct:baz") - .end() - .to("mock:result"); +from("direct:start") + .multicast() + .stopOnException().to("direct:foo", "direct:bar", "direct:baz") + .end() + .to("mock:result"); - from("direct:foo").to("mock:foo"); + from("direct:foo").to("mock:foo"); - from("direct:bar").process(new MyProcessor()).to("mock:bar"); + from("direct:bar").process(new MyProcessor()).to("mock:bar"); - from("direct:baz").to("mock:baz"); + from("direct:baz").to("mock:baz"); ---- +In the example above, then `MyProcessor` is causing a failure and throws an exception. +This means the Multicast EIP will stop after this, and not the last route (direct:baz). + And using XML DSL you specify it as follows: [source,xml] ---- - <route> - <from uri="direct:start"/> - <multicast stopOnException="true"> - <to uri="direct:foo"/> - <to uri="direct:bar"/> - <to uri="direct:baz"/> - </multicast> - <to uri="mock:result"/> - </route> +<routes> + <route> + <from uri="direct:start"/> + <multicast stopOnException="true"> + <to uri="direct:foo"/> + <to uri="direct:bar"/> + <to uri="direct:baz"/> + </multicast> + <to uri="mock:result"/> + </route> - <route> - <from uri="direct:foo"/> - <to uri="mock:foo"/> - </route> + <route> + <from uri="direct:foo"/> + <to uri="mock:foo"/> + </route> - <route> - <from uri="direct:bar"/> - <process ref="myProcessor"/> - <to uri="mock:bar"/> - </route> + <route> + <from uri="direct:bar"/> + <process ref="myProcessor"/> + <to uri="mock:bar"/> + </route> - <route> - <from uri="direct:baz"/> - <to uri="mock:baz"/> - </route> + <route> + <from uri="direct:baz"/> + <to uri="mock:baz"/> + </route> +</routes> ---- -== Using onPrepare to execute custom logic when preparing messages +=== Preparing the message by deep copying before multicasting The multicast EIP will copy the source -exchange and multicast each copy. However the copy -is a shallow copy, so in case you have mutateable message bodies, then +exchange and multicast each copy. However, the copy +is a shallow copy, so in case you have mutable message bodies, then any changes will be visible by the other copied messages. If you want to use a deep clone copy then you need to use a custom `onPrepare` which -allows you to do this using the processor -interface. +allows you to create a deep copy of the message body in the `Processor`. Notice the `onPrepare` can be used for any kind of custom logic which you would like to execute before the xref:latest@manual:ROOT:exchange.adoc[Exchange] is being multicasted. + +== See Also + +Because Multicast EIP is baseline for +the xref:recipientList-eip.adoc[Recipient List] and xref:split-eip.adoc[Split] EIPs, +then you can find more information in those EIPs about features that is also available +with Multicast EIP.