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 bfdb502 CAMEL-16861: Cleanup and update EIP docs bfdb502 is described below commit bfdb502cbbd743f1dfd37ab549d5f6f6bca344d4 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Sep 17 14:13:32 2021 +0200 CAMEL-16861: Cleanup and update EIP docs --- .../modules/eips/pages/dead-letter-channel.adoc | 2 +- .../main/docs/modules/eips/pages/delay-eip.adoc | 2 + .../main/docs/modules/eips/pages/enrich-eip.adoc | 203 ++++++++++----------- .../pages/enterprise-integration-patterns.adoc | 12 +- .../docs/modules/eips/pages/event-message.adoc | 65 ++++--- .../eips/pages/eventDrivenConsumer-eip.adoc | 30 +-- 6 files changed, 151 insertions(+), 163 deletions(-) diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/dead-letter-channel.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/dead-letter-channel.adoc index 7c1131b..9a4dc19 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/dead-letter-channel.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/dead-letter-channel.adoc @@ -454,7 +454,7 @@ The `Exchange.FAILURE_ROUTE_ID` have the constant value `CamelFailureRouteId`. This allows for example you to fetch this information in your dead letter queue and use that for error reporting. -== Control if redelivery is allowed during stopping/shutdown +=== Control if redelivery is allowed during stopping/shutdown The option `allowRedeliveryWhileStopping` (default is `true`) controls whether redelivery is allowed or not, during stopping Camel or the route. This only applies for any potential new redelivery attempts; diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/delay-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/delay-eip.adoc index dbd7922..c246b7f 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/delay-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/delay-eip.adoc @@ -5,6 +5,8 @@ :since: :supportLevel: Stable +The Delay EIP is used for delaying messages during routing. + == Options // eip options: START diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/enrich-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/enrich-eip.adoc index 467b5c0..ce377ec 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/enrich-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/enrich-eip.adoc @@ -5,11 +5,32 @@ :since: :supportLevel: Stable -Camel supports the Content Enricher from the EIP patterns using a Message Translator, an arbitrary Processor in the routing logic, or using the enrich DSL element to enrich the message. +Camel supports the +http://www.enterpriseintegrationpatterns.com/DataEnricher.html[Content +Enricher] from the xref:enterprise-integration-patterns.adoc[EIP +patterns]. image::eip/DataEnricher.gif[image] -TIP: See the `cacheSize` option for more details on _how much cache_ to use depending on how many or few unique endpoints are used. +In Camel the Content Enricher can be done in several ways: + +* Using xref:enrich-eip.adoc[Enrich] EIP +* Using a xref:message-translator.adoc[Message Translator] +* Using a xref:latest@manual:ROOT:processor.adoc[Processor] with the enrichment programmed in Java +* Using a xref:bean-eip.adoc[Bean] EIP with the enrichment programmed in Java + +The most natural Camel approach is using xref:enrich-eip.adoc[Enrich] EIP, +which comes as two kinds: + +* xref:enrich-eip.adoc[Enrich] EIP - This is the most common content enricher that uses a `Producer` to obtain the data. +It is usually used for xref:requestReply-eip.adoc[Request Reply] messaging, for instance to invoke an external web service. + +* xref:pollEnrich-eip.adoc[Poll Enrich] EIP - Uses a xref:polling-consumer.adoc[Polling +Consumer] to obtain the additional data. It is usually used for +xref:event-message.adoc[Event Message] messaging, for instance to read a +file or download a xref:components::ftp-component.adoc[FTP] file. + +NOTE: This page documents the Enrich EIP. // eip options: START The Enrich EIP supports 8 options which are listed below: @@ -28,160 +49,110 @@ The Enrich EIP supports 8 options which are listed below: |=== // eip options: END -== Content enrichment using a Message Translator or a Processor -You can use Templating to consume a message from one destination, transform it with something like Velocity or XQuery, and then send it on to another destination. For example using InOnly (one way messaging) +== Content enrichment using Enrich EIP -== Samples +Enrich EIP is the most common content enricher that uses a `Producer` to obtain the data. -[source,java] ----- -from("activemq:My.Queue"). - to("velocity:com/acme/MyResponse.vm"). - to("activemq:Another.Queue"); ----- +The content enricher (`enrich`) retrieves additional data from a _resource endpoint_ in order to enrich an incoming message (contained in the _original exchange_). -If you want to use InOut (request-reply) semantics to process requests on the *My.Queue* queue on ActiveMQ with a template generated response, then sending responses back to the JMSReplyTo Destination you could use this: +An `AggregationStrategy` is used to combine the original exchange and the _resource exchange_. The first parameter of the `AggregationStrategy.aggregate(Exchange, Exchange)` method corresponds to the original exchange, the second parameter the resource exchange. -[source,java] ----- -from("activemq:My.Queue"). - to("velocity:com/acme/MyResponse.vm"); ----- - -Here is a simple example using the DSL directly to transform the message body +Here's an example for implementing an `AggregationStrategy`, which merges the two data together +as a `String` with colon separator: [source,java] ---- -from("direct:start").setBody(body().append(" World!")).to("mock:result"); ----- +public class ExampleAggregationStrategy implements AggregationStrategy { -In this example we add our own Processor using explicit Java code + public Exchange aggregate(Exchange original, Exchange resource) { + // this is just an example, for real-world use-cases the + // aggregation strategy would be specific to the use-case -[source,java] ----- -from("direct:start").process(new Processor() { - public void process(Exchange exchange) { - Message in = exchange.getIn(); - in.setBody(in.getBody(String.class) + " World!"); + if (newExchange == null) { + return oldExchange; + } + Object oldBody = oldExchange.getIn().getBody(); + Object newBody = newExchange.getIn().getBody(); + oldExchange.getIn().setBody(oldBody + ":" + newBody); + return oldExchange; } -}).to("mock:result"); ----- - -Finally we can use Bean Integration to use any Java method on any bean to act as the transformer -[source,java] ----- -from("activemq:My.Queue"). - beanRef("myBeanName", "myMethodName"). - to("activemq:Another.Queue"); ----- - -=== Using Spring XML - -[source,xml] ----- -<route> - <from uri="activemq:Input"/> - <bean ref="myBeanName" method="doTransform"/> - <to uri="activemq:Output"/> -</route> +} ---- -== Content enrichment using the enrich DSL element - -Camel comes with flavor `enrich` as a choice of content enricher in the DSL. -The other one is `pollEnrich` - -`enrich` uses a Producer to obtain the additional data. It is usually used for Request Reply messaging, for instance to invoke an external web service. - -Both `enrich` and `pollEnrich` supports dynamic endpoints that uses an Expression to compute the uri, which allows to use data from the current Exchange. - -=== Enrich example using Java +You then use the `AggregationStrategy` with the `enrich` in the Java DSL as shown: [source,java] ---- AggregationStrategy aggregationStrategy = ... from("direct:start") - .enrich("direct:resource", aggregationStrategy) - .to("direct:result"); - -from("direct:resource") -... + .enrich("http:remoteserver/foo", aggregationStrategy) + .to("mock:result"); ---- -The content enricher (`enrich`) retrieves additional data from a _resource endpoint_ in order to enrich an incoming message (contained in the _original exchange_). -An aggregation strategy is used to combine the original exchange and the _resource exchange_. The first parameter of the `AggregationStrategy.aggregate(Exchange, Exchange)` method corresponds to the original exchange, the second parameter the resource exchange. -The results from the resource endpoint are stored in the resource exchange's out-message. Here's an example template for implementing an aggregation strategy: +In the example Camel will call the http endpoint to collect some data, that will then +be merged with the original message using the `AggregationStrategy`. -[source,java] ----- -public class ExampleAggregationStrategy implements AggregationStrategy { - - public Exchange aggregate(Exchange original, Exchange resource) { - Object originalBody = original.getIn().getBody(); - Object resourceResponse = resource.getIn().getBody(); - Object mergeResult = ... // combine original body and resource response - if (original.getPattern().isOutCapable()) { - original.getOut().setBody(mergeResult); - } else { - original.getIn().setBody(mergeResult); - } - return original; - } - -} ----- - -Using this template the original exchange can be of any pattern. The resource exchange created by the enricher is always an in-out exchange. - -=== Enrich example using XML +In XML DSL you use `enrich` as follows: [source,xml] ---- +<bean id="myStrategy" class="com.foo.ExampleAggregationStrategy"/> + <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start"/> - <enrich strategyRef="aggregationStrategy"> - <constant>direct:resource</constant> + <enrich strategyRef="myStrategy"> + <constant>http:remoteserver/foo</constant> </enrich> - <to uri="direct:result"/> - </route> - <route> - <from uri="direct:resource"/> - ... + <to uri="mock:result"/> </route> </camelContext> - -<bean id="aggregationStrategy" class="..." /> ---- -== Aggregation strategy is optional -The aggregation strategy is optional. If you do not provide it Camel will by default just use the body obtained from the resource. +=== Aggregation Strategy is optional + +The aggregation strategy is optional. +If not provided then Camel will just use the result exchange as the result. + +The following example: + [source,java] ---- from("direct:start") - .enrich("direct:resource") + .enrich("http:remoteserver/foo") .to("direct:result"); ---- -In the route above the message sent to the direct:result endpoint will contain the output from the direct:resource as we do not use any custom aggregation. +And in XML: [source,xml] ---- <route> - <from uri="direct:start"/> - <enrich> - <constant>direct:resource</constant> - </enrich> - <to uri="direct:result"/> + <from uri="direct:start"/> + <enrich> + <constant>http:remoteserver/foo</constant> + </enrich> + <to uri="mock:result"/> </route> ---- -== Using dynamic uris + +Would be the same as using `to`: + +[source,java] +---- +from("direct:start") + .to("http:remoteserver/foo") + .to("direct:result"); +---- + +=== Using dynamic uris Both `enrich` and `pollEnrich` supports using dynamic uris computed based on information from the current Exchange. For example to enrich from a HTTP endpoint where the header with key orderId is used as part of the content-path of the HTTP url: + [source,java] ---- from("direct:start") @@ -189,7 +160,8 @@ from("direct:start") .to("direct:result"); ---- -And in XML DSL +And in XML DSL: + [source,xml] ---- <route> @@ -200,3 +172,18 @@ And in XML DSL <to uri="direct:result"/> </route> ---- + +=== Using out of the box Aggregation Strategies + +The `org.apache.camel.builder.AggregationStrategies` is a builder that can +be used for creating commonly used aggregation strategies without having to create a class. + +For example the `ExampleAggregationStrategy` from previously can be built as follows: + +[source,java] +---- +AggregationStrategy agg = AggregationStrategies.string(":"); +---- + +There are many other possibilities with the `AggregationStrategies` builder, and for +more details see the https://www.javadoc.io/static/org.apache.camel/camel-core-model/3.11.2/org/apache/camel/builder/AggregationStrategies.html[AggregationStrategies javadoc]. diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/enterprise-integration-patterns.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/enterprise-integration-patterns.adoc index 1dba6a8..6862c41 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/enterprise-integration-patterns.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/enterprise-integration-patterns.adoc @@ -5,10 +5,6 @@ Camel supports most of the http://www.eaipatterns.com/toc.html[Enterprise Integration Patterns] from the excellent book by Gregor Hohpe and Bobby Woolf. -If you are new to Camel you might want to try the xref:latest@manual:ROOT:getting-started.adoc[Getting Started] in the -User Guide before attempting to implement these patterns. - -[[EnterpriseIntegrationPatterns-MessagingSystems]] == Messaging Systems [width="100%",cols="10%,10%,80%",] @@ -40,7 +36,6 @@ a|image::eip/MessageEndpointIcon.gif[image] connect to a messaging channel to send and receive messages? |======================================================================= -[[EnterpriseIntegrationPatterns-MessagingChannels]] == Messaging Channels [width="100%",cols="10%,10%,80%",] @@ -82,7 +77,6 @@ a|image::eip/MessagingBridgeIcon.gif[image] changes made to a database, and apply those changes to another system. |======================================================================= -[[EnterpriseIntegrationPatterns-MessageConstruction]] == Message Construction [width="100%",cols="10%,10%,80%",] @@ -110,7 +104,6 @@ when a message should be considered stale and thus shouldn’t be processed? |======================================================================= -[[EnterpriseIntegrationPatterns-MessageRouting]] == Message Routing [width="100%",cols="10%,10%,80%",] @@ -211,7 +204,6 @@ a|image::eip/PollingConsumerIcon.gif[image] |xref:loop-eip.adoc[Loop] |How can I repeat processing a message in a loop? |======================================================================= -[[EnterpriseIntegrationPatterns-MessageTransformation]] == Message Transformation [width="100%",cols="10%,10%,80%",] @@ -244,7 +236,6 @@ a|image::eip/MessageSelectorIcon.gif[image] |xref:validate-eip.adoc[Validate] |How can I validate a message? |======================================================================= -[[EnterpriseIntegrationPatterns-MessagingEndpoints]] == Messaging Endpoints [width="100%",cols="10%,10%,80%",] @@ -297,7 +288,6 @@ design a service to be invoked both via various messaging technologies and via non-messaging techniques? |======================================================================= -[[EnterpriseIntegrationPatterns-SystemManagement]] == System Management [width="100%",cols="10%,10%,80%",] @@ -324,7 +314,7 @@ a|image::eip/ControlBusIcon.gif[image] |xref:log-eip.adoc[Log] |How can I log processing a message? a|image::eip/RoutingTableIcon.gif[image] -|xref:step-eip.adoc[Step] | Steps groups together a set of EIPs into a composite logical unit for metrics and monitoring. | +|xref:step-eip.adoc[Step] | Groups together a set of EIPs into a composite logical unit for metrics and monitoring. | |======================================================================= diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/event-message.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/event-message.adoc index bdbb468..24c5cd5 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/event-message.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/event-message.adoc @@ -17,37 +17,48 @@ xref:components::seda-component.adoc[SEDA] TIP: See the related xref:requestReply-eip.adoc[Request Reply] message. -[[eventMessage-ExplicitlyspecifyingInOnly]] -== Explicitly specifying InOnly +== Using endpoint URI -If you are using a component which defaults to InOut you can override -the xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] for an endpoint using +If you are using a component which defaults to `InOut` you can override +the xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] for a *consumer* endpoint using the pattern property. -[source] +[source,text] ---- foo:bar?exchangePattern=InOnly ---- +IMPORTANT: This is only possible on endpoints used by consumers (i.e. in `<from>`). -== Samples - -From 2.0 onwards on Camel you can specify the -xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] using the DSL. +In the example below the message will be forced as an event message as the consumer +is in `InOnly` mode. [source,java] ---- -from("mq:someQueue"). - setExchangePattern(ExchangePattern.InOnly). - bean(Foo.class); +from("mq:someQueue?exchangePattern=InOnly") + .to("activemq:queue:one-way"); +---- + +And with XML: + +[source,xml] +---- +<route> + <from uri="mq:someQueue?exchangePattern=InOnly"/> + <to uri="activemq:queue:one-way"/> +</route> ---- -or you can invoke an endpoint with an explicit pattern +== Using setExchangePattern EIP + +You can specify the +xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] using `setExchangePattern` in the DSL. [source,java] ---- -from("mq:someQueue"). - inOnly("mq:anotherQueue"); +from("mq:someQueue") + .setExchangePattern(ExchangePattern.InOnly) + .to("activemq:queue:one-way"); ---- And with XML: @@ -56,15 +67,27 @@ And with XML: ---- <route> <from uri="mq:someQueue"/> - <inOnly uri="bean:foo"/> + <setExchangePattern pattern="InOnly"/> + <to uri="activemq:queue:one-way"/> </route> ---- -[source,xml] +When using `setExchangePattern` then the xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] +on the xref:latest@manual:ROOT:exchange.adoc[Exchange] is changed from this point onwards in the route. + +This means you can change the pattern back again at a later point: + +[source,java] ---- -<route> - <from uri="mq:someQueue"/> - <inOnly uri="mq:anotherQueue"/> -</route> +from("mq:someQueue") + .setExchangePattern(ExchangePattern.InOnly) + .to("activemq:queue:one-way"); + .setExchangePattern(ExchangePattern.InOut) + .to("activemq:queue:in-and-out") + .log("InOut MEP received ${body}") ---- +NOTE: Using `setExchangePattern` to change the xref:latest@manual:ROOT:exchange-pattern.adoc[Exchange Pattern] +is often only used in special use-cases where you must +force to be using either `InOnly` or `InOut` mode when using components that support both modes (such as messaging components like ActiveMQ, JMS, RabbitMQ etc.) + diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/eventDrivenConsumer-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/eventDrivenConsumer-eip.adoc index aa3e086..e8a4af0 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/eventDrivenConsumer-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/eventDrivenConsumer-eip.adoc @@ -5,10 +5,13 @@ Camel supports the http://www.enterpriseintegrationpatterns.com/EventDrivenConsumer.html[Event Driven Consumer] from the xref:enterprise-integration-patterns.adoc[EIP patterns]. + The default consumer model is event based (i.e. asynchronous) as this means that the Camel container can then manage pooling, threading and concurrency for you in a declarative manner. +TIP: The alternative consumer mode is xref:pollEnrich-eip.adoc[Polling Consumer]. + image::eip/EventDrivenConsumerSolution.gif[image] The Event Driven Consumer is implemented by consumers implementing the @@ -16,41 +19,24 @@ http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Proces interface which is invoked by the xref:message-endpoint.adoc[Message Endpoint] when a xref:message.adoc[Message] is available for processing. -[[eventDrivenConsumer-Example]] == Example -The following demonstrates a -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Processor.html[Processor] -defined in the Camel xref:latest@manual:ROOT:registry.adoc[Registry] which is -invoked when an event occurs from a xref:components::jms-component.adoc[JMS] queue. +The following demonstrates a xref:bean-eip.adoc[Bean] being invoked when +an event occurs from a xref:components::jms-component.adoc[JMS] queue. [source,java] ---- from("jms:queue:foo") - .processRef("processor"); + .bean(MyBean.class); ---- -**Using the xref:latest@manual:ROOT:spring-xml-extensions.adoc[Spring XML Extensions]** +And in XML: [source,xml] ---- <route> <from uri="jms:queue:foo"/> - <to uri="processor"/> + <bean beanType="com.foo.MyBean"/> </route> ---- -For more details see: - -* xref:message.adoc[Message] -* xref:message-endpoint.adoc[Message Endpoint] - -[[eventDrivenConsumer-UsingThisPattern]] -== Using This Pattern - -If you would like to use this EIP Pattern then please read the -xref:latest@manual:ROOT:getting-started.adoc[Getting Started], you may also find the -xref:latest@manual:ROOT:architecture.adoc[Architecture] useful particularly the description -of xref:latest@manual:ROOT:endpoint.adoc[Endpoint] and xref:latest@manual:ROOT:uris.adoc[URIs]. Then you could -try out some of the xref:latest@manual:ROOT:examples.adoc[Examples] first before trying -this pattern out.