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

commit 1410dea38615fbeb6bc1b88be582cba7c6d370bb
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon Oct 11 14:43:42 2021 +0200

    CAMEL-16861: Cleanup and update EIP docs
---
 .../docs/modules/eips/pages/multicast-eip.adoc     |   2 +-
 .../docs/modules/eips/pages/recipientList-eip.adoc | 334 ++++++++++-----------
 .../org/apache/camel/support/ObjectHelper.java     |   1 -
 3 files changed, 165 insertions(+), 172 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 fe33060..bc18439 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
@@ -29,7 +29,7 @@ The following properties are set on each Exchange that are 
multicasted:
 |=======================================================================
 | 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.
+| `CamelMulticastComplete` | `boolean` | Whether this Exchange is the last.
 |=======================================================================
 
 == Using Multicast
diff --git 
a/core/camel-core-engine/src/main/docs/modules/eips/pages/recipientList-eip.adoc
 
b/core/camel-core-engine/src/main/docs/modules/eips/pages/recipientList-eip.adoc
index 83d2abe..e0c6e13 100644
--- 
a/core/camel-core-engine/src/main/docs/modules/eips/pages/recipientList-eip.adoc
+++ 
b/core/camel-core-engine/src/main/docs/modules/eips/pages/recipientList-eip.adoc
@@ -5,11 +5,15 @@
 :since: 
 :supportlevel: Stable
 
-image::eip/RecipientList.gif[image]
+Camel supports the
+https://www.enterpriseintegrationpatterns.com/RecipientList.html[Recipient 
List]
+from the xref:enterprise-integration-patterns.adoc[EIP patterns].
 
-The recipients will receive a copy of the *same* Exchange, and Camel will 
execute them sequentially.
+How do we route a message to a list of dynamically specified recipients?
 
-TIP: See the `cacheSize` option for more details on _how much cache_ to use 
depending on how many or few unique endpoints are used.
+image::eip/RecipientList.gif[image]
+
+Define a channel for each recipient. Then use a Recipient List to inspect an 
incoming message, determine the list of desired recipients, and forward the 
message to all channels associated with the recipients in the list.
 
 == Options
 
@@ -18,39 +22,63 @@ include::partial$eip-options.adoc[]
 // eip options: END
 
 
-[TIP]
-====
-You can use the RecipientList Annotation on a POJO to create a Dynamic 
Recipient List. For more details see the Bean Integration.
-====
+TIP: See the `cacheSize` option for more details on _how much cache_ to use 
depending on how many or few unique endpoints are used.
+
+== Exchange properties
 
-== Static Recipient List
-The following example shows how to route a request from an input *queue:a* 
endpoint to a static list of destinations
+The following properties are set on each Exchange that are sent by the 
recipient list:
+
+[width="100%",cols="3,1m,6",options="header"]
+|=======================================================================
+| Property | Type | Description
+| `CamelRecipientListEndpoint` | `String` | Uri of the `Endpoint` that the 
message was sent to.
+|=======================================================================
+
+== Using Recipient List
+
+The Recipient List 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.
+
+There can be 1 or more destinations, and Camel will execute them sequentially 
(by default).
+However, a parallel mode exists which allows processing messages concurrently.
+
+The Recipient List EIP has many features and is based on the 
xref:multicast-eip.adoc[Multicast] EIP.
+For example the Recipient List EIP is capable of aggregating each message into 
a single
+_response_ message as the result after the Recipient List EIP.
+
+=== Using static Recipient List
+
+The following example shows how to route a request from an input queue:a 
endpoint
+to a static list of destinations, using `constant`:
 
 [source,java]
 ----
 from("jms:queue:a")
-    .recipientList(constant("direct:b,direct:c,direct:d"));
+    .recipientList(constant("seda:x,seda:y,seda:z"));
 ----
 
 And in XML:
 
 [source,xml]
 ----
-<camelContext xmlns="http://camel.apache.org/schema/spring";>
-    <route>
-        <from uri="jms:queue:a"/>
-        <recipientList>
-            <constant>direct:b,direct:c,direct:d</constant>
-        </recipientList>
-    </route>
-</camelContext>
+<route>
+    <from uri="jms:queue:a"/>
+    <recipientList>
+        <constant>seda:x,seda:y,seda:z</constant>
+    </recipientList>
+</route>
 ----
 
-== Dynamic Recipient List
+=== Using dynamic Recipient List
+
 Usually one of the main reasons for using the Recipient List pattern is that 
the list of recipients is dynamic and
-calculated at runtime. The following example demonstrates how to create a 
dynamic recipient list using an Expression
-(which in this case extracts a named header value dynamically) to calculate 
the list of endpoints which are either
-of type Endpoint or are converted to a String and then resolved using the 
endpoint URIs (separated by comma).
+calculated at runtime.
+
+The following example demonstrates how to create a dynamic recipient list 
using an xref:latest@manual:ROOT:expression.adoc[Expression]
+(which in this case extracts a named header value dynamically) to calculate 
the list of endpoints; which are either
+of type `Endpoint` or are converted to a `String` and then resolved using the 
endpoint URIs (separated by comma).
+
+In Java DSL its as easy as:
 
 [source,java]
 ----
@@ -58,19 +86,34 @@ from("jms:queue:a")
     .recipientList(header("foo"));
 ----
 
-== Iteratable value
+And in XML:
+
+[source,xml]
+----
+<route>
+    <from uri="jms:queue:a"/>
+    <recipientList>
+        <header>foo</constant>
+    </recipientList>
+</route>
+----
+
+==== How is dynamic destinations evaluated
+
 The dynamic list of recipients that are defined in the header must be iterable 
such as:
 
 * `java.util.Collection`
 * `java.util.Iterator`
 * arrays
 * `org.w3c.dom.NodeList`
-* a single String with values separated by comma (the delimiter configured)
+* a single `String` with values separated by comma (the delimiter configured)
 * any other type will be regarded as a single value
 
-== Using delimiter in Spring XML
-In Spring DSL you can set the delimiter attribute for setting a delimiter to 
be used if the header value is a single String with multiple separated 
endpoints.
-By default Camel uses comma as delimiter, but this option lets you specify a 
custom delimiter to use instead.
+
+=== Configuring delimiter for dynamic destinations
+
+In XML DSL you can set the delimiter attribute for setting a delimiter to be 
used if the header value is a single `String` with multiple separated endpoints.
+By default, Camel uses comma as delimiter, but this option lets you specify a 
custom delimiter to use instead.
 
 [source,xml]
 ----
@@ -83,19 +126,25 @@ By default Camel uses comma as delimiter, but this option 
lets you specify a cus
 </route>
 ----
 
-So if *myHeader* contains a `String` with the value 
`"activemq:queue:foo;activemq:topic:hello ; log:bar"` then Camel will split the 
`String` using the delimiter given in the XML that was comma, resulting into 3 
endpoints to send to.
-You can use spaces between the endpoints as Camel will trim the value when it 
lookup the endpoint to send to.
+So if *myHeader* contains a `String` with the value 
`"activemq:queue:foo;activemq:topic:hello ; log:bar"`
+then Camel will split the `String` using the delimiter given in the XML that 
was comma, resulting into 3 endpoints to send to.
+You can use spaces between the endpoints as Camel will trim the value when it 
look up the endpoint to send to.
+
+And in Java DSL, you specify the delimiter as 2nd parameter as shown below:
 
-And in Java:
 [source,java]
 ----
 from("direct:a")
     .recipientList(header("myHeader"), ";");
 ----
 
-== Sending to multiple recipients in parallel
-The Recipient List now supports `parallelProcessing` that for example Splitter 
also supports.
-You can use it to use a thread pool to have concurrent tasks sending the 
Exchange to multiple recipients concurrently.
+=== Using parallel processing
+
+The Recipient List supports `parallelProcessing` similar to what 
xref:multicast-eip.adoc[Multicast] and xref:split-eip.adoc[Split] EIPs have as 
well.
+When using parallel processing then a thread pool is used to have concurrent 
tasks sending the `Exchange`
+to multiple recipients concurrently.
+
+You can enable parallel mode using `parallelProcessing` in Java as shown:
 
 [source,java]
 ----
@@ -103,7 +152,7 @@ from("direct:a")
     .recipientList(header("myHeader")).parallelProcessing();
 ----
 
-And in XML it is an attribute on the recipient list tag.
+And in XML it is an attribute on `<recipientList>`:
 
 [source,xml]
 ----
@@ -115,39 +164,79 @@ And in XML it is an attribute on the recipient list tag.
 </route>
 ----
 
-=== Using custom thread pool
+==== Using custom thread pool
+
 A thread pool is only used for `parallelProcessing`. You supply your own 
custom thread pool via the `ExecutorServiceStrategy` (see Camel's Threading 
Model),
 the same way you would do it for the `aggregationStrategy`. By default Camel 
uses a thread pool with 10 threads (subject to change in future versions).
 
-== Stop continuing in case one recipient failed
-The Recipient List now supports `stopOnException` that for example Splitter 
also supports.
-You can use it to stop sending to any further recipients in case any recipient 
failed.
+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 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 
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:a")
-    .recipientList(header("myHeader")).stopOnException();
+from("direct:start")
+    .recipientList(header("whereTo")).stopOnException()
+    .to("mock:result");
+
+    from("direct:foo").to("mock:foo");
+
+    from("direct:bar").process(new MyProcessor()).to("mock:bar");
+
+    from("direct:baz").to("mock:baz");
 ----
 
-And in XML its an attribute on the recipient list tag.
+In this example suppose a message is sent with the header 
`whereTo=direct:foo,direct:bar,direct:baz`
+that means the recipient list sends messages to those 3 endpoints.
+
+Now suppose that the `MyProcessor` is causing a failure and throws an 
exception.
+This means the Recipient List 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:a"/>
-    <recipientList stopOnException="true">
-        <header>myHeader</header>
-    </recipientList>
-</route>
+<routes>
+    <route>
+        <from uri="direct:start"/>
+        <recipientList stopOnException="true">
+            <header>whereTo</header>
+        </recipientList>
+        <to uri="mock:result"/>
+    </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:baz"/>
+        <to uri="mock:baz"/>
+    </route>
+</routes>
 ----
 
-[NOTE]
-====
-You can combine parallelProcessing and stopOnException and have them both true.
-====
+=== Ignore invalid endpoints
 
-== Ignore invalid endpoints
-The Recipient List now supports `ignoreInvalidEndpoints` (like the Routing 
Slip).
+The Recipient List now supports `ignoreInvalidEndpoints` (like 
xref:routingSlip-eip.adoc[Routing Slip] EIP).
 You can use it to skip endpoints which are invalid.
 
 [source,java]
@@ -156,7 +245,7 @@ from("direct:a")
     .recipientList(header("myHeader")).ignoreInvalidEndpoints();
 ----
 
-And in XML it is an attribute on the recipient list tag.
+And in XML it is an attribute on `<recipientList>`:
 
 [source,xml]
 ----
@@ -169,116 +258,24 @@ And in XML it is an attribute on the recipient list tag.
 ----
 
 Then let us say the `myHeader` contains the following two endpoints 
`direct:foo,xxx:bar`.
-The first endpoint is valid and works. However the second one is invalid and 
will just be ignored.
+The first endpoint is valid and works. However, the second one is invalid and 
will just be ignored.
 Camel logs at DEBUG level about it, so you can see why the endpoint was 
invalid.
 
-== Using custom AggregationStrategy
-You can now use your own `AggregationStrategy` with the Recipient List. 
However this is rarely needed.
-What it is good for is that in case you are using Request Reply messaging then 
the replies from the recipients can be aggregated.
-By default Camel uses `UseLatestAggregationStrategy` which just keeps that 
last received reply. If you must remember all the bodies that all the 
recipients sent back,
-then you can use your own custom aggregator that keeps those. It is the same 
principle as with the Aggregator EIP so check it out for details.
+=== Using timeout
 
-[source,java]
-----
-from("direct:a")
-    .recipientList(header("myHeader")).aggregationStrategy(new 
MyOwnAggregationStrategy())
-    .to("direct:b");
-----
+If you use `parallelProcessing` then you can configure a total `timeout` value 
in millis.
 
-And in XML it is again an attribute on the recipient list tag.
-
-[source,xml]
-----
-<route>
-    <from uri="direct:a"/>
-    <recipientList strategyRef="myStrategy">
-        <header>myHeader</header>
-    </recipientList>
-    <to uri="direct:b"/>
-</route>
-
-<!-- bean with the custom aggregation strategy -->
-<bean id="myStrategy" class="com.mycompany.MyOwnAggregationStrategy"/>
-----
-
-[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.
-====
-
-== Knowing which endpoint when using custom AggregationStrategy
-
-When using a custom `AggregationStrategy` then the `aggregate` method is 
always invoked in sequential order
-(also if parallel processing is enabled) of the endpoints the Recipient List 
is using.
-However, Exchange has a property stored (key is 
`Exchange.RECIPIENT_LIST_ENDPOINT` with the uri of the Endpoint.
-So you know which endpoint you are aggregating from. The code block shows how 
to access this property in your Aggregator.
-
-[source,java]
-----
-@Override
-public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
-    String uri = newExchange.getProperty(Exchange.RECIPIENT_LIST_ENDPOINT, 
String.class);
-}
-----
-
-== Using method call as recipient list
-You can use a Bean to provide the recipients, for example:
-
-[source,java]
-----
-from("activemq:queue:test")
-    .recipientList().method(MessageRouter.class, "routeTo");
-----
-
-And then `MessageRouter` bean:
-
-[source,java]
-----
-public class MessageRouter {
-
-    public String routeTo() {
-        String queueName = "activemq:queue:test2";
-        return queueName;
-    }
-}
-----
-
-[CAUTION]
-When you use a Bean then do *not* use the `@RecipientList` annotation as this 
will in fact add yet another recipient list, so you end up having two. Do *not* 
do the following:
-[source,java]
-----
-public class MessageRouter {
-
-    // do not use recipientList in the Camel route calling a bean with the 
@RecipientList annotation!
-    @RecipientList
-    public String routeTo() {
-        String queueName = "activemq:queue:test2";
-        return queueName;
-    }
-}
-----
-
-You should only use the snippet above (using `@RecipientList`) if you just 
route to a Bean which you then want to act as a recipient list.
-So the original route can be changed to:
-
-[source,java]
-----
-from("activemq:queue:test").bean(MessageRouter.class, "routeTo");
-----
-
-Which then would invoke the routeTo method and detect that it is annotated 
with `@RecipientList` and then act accordingly as if it was a recipient list 
EIP.
-
-== Using timeout
-If you use `parallelProcessing` then you can configure a total `timeout` value 
in millis. Camel will then process the messages in parallel until the timeout 
is hit. This allows you to continue processing if one message consumer is slow. 
For example you can set a timeout value of 20 sec.
+Camel will then process the messages in parallel until the timeout is hit.
+This allows you to continue processing if one message consumer is slow.
+For example, you can set a timeout value of 20 sec.
 
 [WARNING]
 .Tasks may keep running
-If the timeout is reached with running tasks still remaining, certain tasks 
for which it is difficult for Camel to shut down in a graceful manner may 
continue to run. So use this option with a bit of care. We may be able to 
improve this functionality in future Camel releases.
+If the timeout is reached with running tasks still remaining, certain tasks 
for which it is difficult for Camel to shut down in a graceful manner may 
continue to run. So use this option with a bit of care.
 
-For example in the unit test below you can see that we multicast the message 
to 3 destinations. We have a timeout of 2 seconds, which means only the last 
two messages can be completed within the timeframe. This means we will only 
aggregate the last two which yields a result aggregation which outputs "BC".
+For example in the unit test below you can see that we multicast the message 
to 3 destinations.
+We have a timeout of 2 seconds, which means only the last two messages can be 
completed within the timeframe.
+This means we will only aggregate the last two which yields a result 
aggregation which outputs "BC".
 
 [source,java]
 ----
@@ -306,13 +303,7 @@ from("direct:b").to("mock:B").setBody(constant("B"));
 from("direct:c").to("mock:C").setBody(constant("C"));
 ----
 
-[NOTE]
-.Timeout in other EIPs
-====
-This timeout feature is also supported by Splitter and both multicast and 
recipientList.
-====
-
-By default if a timeout occurs the `AggregationStrategy` is not invoked. 
However you can implement the `timeout` method:
+By default, if a timeout occurs the `AggregationStrategy` is not invoked. 
However, you can implement the `timeout` method:
 This allows you to deal with the timeout in the `AggregationStrategy` if you 
really need to.
 
 [NOTE]
@@ -322,13 +313,10 @@ The timeout is total, which means that after X time, 
Camel will aggregate the me
 The remainders will be cancelled. Camel will also only invoke the `timeout` 
method in the `TimeoutAwareAggregationStrategy` once, for the first index which 
caused the timeout.
 ====
 
-== Using onPrepare to execute custom logic when preparing messages
-See details at the Multicast EIP
-
-== Using ExchangePattern in recipients
+=== Using ExchangePattern in recipients
 
 The recipient list will by default use the current Exchange Pattern. Though 
one can imagine use-cases where one wants to send
-a message to a recipient using a different exchange pattern. For example you 
may have a route that initiates as an `InOnly` route,
+a message to a recipient using a different exchange pattern. For example, you 
may have a route that initiates as an `InOnly` route,
 but want to use `InOut` exchange pattern with a recipient list. You can 
configure the exchange pattern directly in the
 recipient endpoints.
 
@@ -349,7 +337,13 @@ from("file:inbox")
 ====
 The recipient list will not alter the original exchange pattern. So in the 
example above the exchange pattern will still
 be `InOnly` when the message is routed to the `file:outbox endpoint`.
-If you want to alter the exchange pattern permanently then use the 
`.setExchangePattern` option.
+If you want to alter the exchange pattern permanently then use 
`.setExchangePattern` in the route.
 
-See more details at Request Reply and Event Message EIPs.
+See more details at xref:event-message.adoc[Event Message] and 
xref:requestReply-eip.adoc[Request Reply] EIPs.
 ====
+
+== See Also
+
+Because Recipient List EIP is based from the 
xref:multicast-eip.adoc[Multicast],
+then you can find more information in xref:multicast-eip.adoc[Multicast] EIP
+about features that is also available with Recipient List EIP.
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/ObjectHelper.java 
b/core/camel-support/src/main/java/org/apache/camel/support/ObjectHelper.java
index ae62c3b..c4f982b 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/ObjectHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/ObjectHelper.java
@@ -660,7 +660,6 @@ public final class ObjectHelper {
      * Creates an iterable over the value if the value is a collection, an 
Object[], a String with values separated by
      * the given delimiter, or a primitive type array; otherwise to simplify 
the caller's code, we just create a
      * singleton collection iterator over a single value
-     *
      * </p>
      * In case of primitive type arrays the returned {@code Iterable} iterates 
over the corresponding Java primitive
      * wrapper objects of the given elements inside the {@code value} array. 
That's we get an autoboxing of the

Reply via email to