This is an automated email from the ASF dual-hosted git repository. zregvart pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push: new d907d20 CAMEL-13558: auto-generate navigation toc for E... d907d20 is described below commit d907d203f8069111ee028ceb6f14ce3f975d6325 Author: Zoran Regvart <zregv...@apache.org> AuthorDate: Thu May 23 11:45:18 2019 +0200 CAMEL-13558: auto-generate navigation toc for E... ...IPs and languages --- docs/component-nav.adoc.template | 4 + docs/components/modules/ROOT/nav.adoc | 3 + docs/generated.txt | 2 + docs/gulpfile.js | 84 ++++- docs/nav.adoc.template | 2 - docs/user-manual-nav.adoc.template | 49 +++ docs/user-manual/modules/ROOT/nav.adoc | 31 +- .../annotation-based-expression-language.adoc | 128 ------- .../modules/ROOT/pages/bean-language.adoc | 167 --------- .../modules/ROOT/pages/scala-dsl-eip.adoc | 395 --------------------- 10 files changed, 138 insertions(+), 727 deletions(-) diff --git a/docs/component-nav.adoc.template b/docs/component-nav.adoc.template new file mode 100644 index 0000000..169357f --- /dev/null +++ b/docs/component-nav.adoc.template @@ -0,0 +1,4 @@ +<!-- generated:txt --> +<!-- endinject --> +<!-- inject:adoc --> +<!-- endinject --> diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc index 3dfa474..405ef71 100644 --- a/docs/components/modules/ROOT/nav.adoc +++ b/docs/components/modules/ROOT/nav.adoc @@ -1,3 +1,6 @@ +// this file is auto generated and changes to it will be overwritten +// make edits in docs/*nav.adoc.template files instead + * xref:activemq-component.adoc[ActiveMQ Component] * xref:ahc-ws-component.adoc[AHC Websocket Component] * xref:ahc-component.adoc[AHC Component] diff --git a/docs/generated.txt b/docs/generated.txt new file mode 100644 index 0000000..f62ddd6 --- /dev/null +++ b/docs/generated.txt @@ -0,0 +1,2 @@ +// this file is auto generated and changes to it will be overwritten +// make edits in docs/*nav.adoc.template files instead diff --git a/docs/gulpfile.js b/docs/gulpfile.js index 61bd4e2..e0da250 100644 --- a/docs/gulpfile.js +++ b/docs/gulpfile.js @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const { dest, series, src, symlink } = require('gulp'); +const { dest, series, parallel, src, symlink } = require('gulp'); const del = require('del'); const inject = require('gulp-inject'); const map = require('map-stream') @@ -22,11 +22,11 @@ const path = require('path'); const rename = require('gulp-rename'); const sort = require('gulp-sort'); -function deleteSymlinks() { +function deleteComponentSymlinks() { return del(['components/modules/ROOT/pages/*', '!components/modules/ROOT/pages/index.adoc']); } -function createSymlinks() { +function createComponentSymlinks() { return src('../components/*/src/main/docs/*.adoc') .pipe(map((file, done) => { // this flattens the output to just .../pages/....adoc @@ -46,25 +46,87 @@ function createSymlinks() { .pipe(dest('components/modules/ROOT/pages/')); } -function nav() { - return src('nav.adoc.template') +function deleteUserManualSymlinks() { + return del(['user-manual/modules/ROOT/pages/*-eip.adoc', 'user-manual/modules/ROOT/pages/*-language.adoc']); +} + +function createUserManualSymlinks() { + return src(['../core/camel-base/src/main/docs/*.adoc', '../core/camel-core/src/main/docs/eips/*.adoc']) + // Antora disabled symlinks, there is an issue open + // https://gitlab.com/antora/antora/issues/188 + // to reinstate symlink support, until that's resolved + // we'll simply copy over instead of creating symlinks + // .pipe(symlink('user-manual/modules/ROOT/pages/', { + // relativeSymlinks: true + // })); + // uncomment above .pipe() and remove the .pipe() below + // when antora#188 is resolved + .pipe(dest('user-manual/modules/ROOT/pages/')); +} + +function titleFrom(file) { + const maybeName = /(?:==|##) (.*)/.exec(file.contents.toString()) + if (maybeName == null) { + throw new Error(`${file.path} doesn't contain Asciidoc heading ('== <Title>') or ('## <Title')`); + } + + return maybeName[1]; +} + +function insertGeneratedNotice() { + return inject(src('./generated.txt'), { + name: 'generated', + removeTags: true, + transform: (filename, file) => { + return file.contents.toString('utf8'); + } + }); +} + +function createComponentNav() { + return src('component-nav.adoc.template') + .pipe(insertGeneratedNotice()) .pipe(inject(src('../components/*/src/main/docs/*.adoc').pipe(sort()), { removeTags: true, transform: (filename, file) => { const filepath = path.basename(filename); - const maybeName = /(?:==|##) (.*)/.exec(file.contents.toString()) - if (maybeName == null) { - throw new Error(`${file.path} doesn't contain Asciidoc heading ('== <Title>') or ('## <Title')`); - } - return `* xref:${filepath}[${maybeName[1]}]`; + const title = titleFrom(file); + return `* xref:${filepath}[${title}]`; } })) .pipe(rename('nav.adoc')) .pipe(dest('components/modules/ROOT/')) } -const symlinks = series(deleteSymlinks, createSymlinks); +function createUserManualNav() { + return src('user-manual-nav.adoc.template') + .pipe(insertGeneratedNotice()) + .pipe(inject(src('../core/camel-base/src/main/docs/*-language.adoc').pipe(sort()), { + removeTags: true, + name: 'languages', + transform: (filename, file) => { + const filepath = path.basename(filename); + const title = titleFrom(file); + return ` ** xref:${filepath}[${title}]`; + } + })) + .pipe(inject(src('../core/camel-core/src/main/docs/eips/*.adoc').pipe(sort()), { + removeTags: true, + name: 'eips', + transform: (filename, file) => { + const filepath = path.basename(filename); + const title = titleFrom(file); + return ` ** xref:${filepath}[${title}]`; + } + })) + .pipe(rename('nav.adoc')) + .pipe(dest('user-manual/modules/ROOT/')) +} + +const symlinks = parallel(series(deleteComponentSymlinks, createComponentSymlinks), series(deleteUserManualSymlinks, createUserManualSymlinks)); +const nav = parallel(createComponentNav, createUserManualNav); exports.symlinks = symlinks; exports.nav = nav; exports.default = series(symlinks, nav); + diff --git a/docs/nav.adoc.template b/docs/nav.adoc.template deleted file mode 100644 index 8223a81..0000000 --- a/docs/nav.adoc.template +++ /dev/null @@ -1,2 +0,0 @@ -<!-- inject:adoc --> -<!-- endinject --> diff --git a/docs/user-manual-nav.adoc.template b/docs/user-manual-nav.adoc.template new file mode 100644 index 0000000..a4e0ca0 --- /dev/null +++ b/docs/user-manual-nav.adoc.template @@ -0,0 +1,49 @@ +<!-- generated:txt --> +<!-- endinject --> +* xref:getting-started.adoc[Getting started] + ** xref:book-getting-started.adoc[Getting Started with Apache Camel] +* xref:architecture.adoc[Architecture] + ** xref:async.adoc[Async] + ** xref:asynchronous-routing-engine.adoc[Asynchronous Routing Engine] + ** xref:backlogdebugger.adoc[Backlog debugger] + ** xref:bam.adoc[Business Activity Monitoring] + ** xref:batch-consumer.adoc[Batch Consumer] + ** xref:browsable-endpoint.adoc[BrowsableEndpoint] + ** xref:camel-core.adoc[Core] + ** xref:camelcontext.adoc[Context] + ** xref:endpoint.adoc[Endpoints] + ** xref:cep.adoc[Complex Event Processing] + ** xref:component.adoc[Component] + ** xref:debugger.adoc[Debugger] + ** xref:delay-interceptor.adoc[Delay interceptor] + ** xref:dependency-injection.adoc[Dependency Injection] + ** xref:dozer-type-conversion.adoc[Dozer Type Conversion] + ** xref:bean-integration.adoc[Bean Integration] + ** xref:error-handler.adoc[Error Handler] + ** xref:exchange.adoc[Message Exchange] + ** xref:exchange-pattern.adoc[Exchange Pattern] + ** xref:expression.adoc[Expressions] + ** xref:injector.adoc[Injector] + ** xref:intercept.adoc[Intercept] + ** xref:inversion-of-control-with-smart-defaults.adoc[Inversion Of Control With Smart Defaults] + ** xref:jmx.adoc[JMX] + ** xref:lifecycle.adoc[Camel Lifecycle] + ** xref:oncompletion.adoc[OnCompletion] + ** xref:predicate.adoc[Predicates] + ** xref:registry.adoc[Registry] + ** xref:route-builder.adoc[RouteBuilder] + ** xref:routes.adoc[Routes] + ** xref:transformer.adoc[Transformer] + ** xref:validator.adoc[Validator] +* Domain Specific Languages + ** xref:dsl.adoc[Camel Domain Specific Language] + ** xref:java-dsl.adoc[Java DSL] + ** xref:spring.adoc[Spring support] + ** xref:groovy-dsl.adoc[Groovy DSL] +* xref:using-osgi-blueprint-with-camel.adoc[Using OSGi blueprint with Camel] +* Supported expression languages +<!-- languages:adoc --> +<!-- endinject --> +* xref:enterprise-integration-patterns.adoc[Enterprise Integration Patterns] +<!-- eips:adoc --> +<!-- endinject --> diff --git a/docs/user-manual/modules/ROOT/nav.adoc b/docs/user-manual/modules/ROOT/nav.adoc index b6d3e03..01e62e6 100644 --- a/docs/user-manual/modules/ROOT/nav.adoc +++ b/docs/user-manual/modules/ROOT/nav.adoc @@ -1,3 +1,6 @@ +// this file is auto generated and changes to it will be overwritten +// make edits in docs/*nav.adoc.template files instead + * xref:getting-started.adoc[Getting started] ** xref:book-getting-started.adoc[Getting Started with Apache Camel] * xref:architecture.adoc[Architecture] @@ -31,29 +34,22 @@ ** xref:registry.adoc[Registry] ** xref:route-builder.adoc[RouteBuilder] ** xref:routes.adoc[Routes] + ** xref:transformer.adoc[Transformer] + ** xref:validator.adoc[Validator] * Domain Specific Languages ** xref:dsl.adoc[Camel Domain Specific Language] ** xref:java-dsl.adoc[Java DSL] ** xref:spring.adoc[Spring support] ** xref:groovy-dsl.adoc[Groovy DSL] * xref:using-osgi-blueprint-with-camel.adoc[Using OSGi blueprint with Camel] -* Camel Core Features - ** xref:bean-language.adoc[Bean method Language] - ** xref:clustering.adoc[Clustering] +* Supported expression languages ** xref:constant-language.adoc[Constant Language] - ** xref:dynamic-router.adoc[Dynamic Router] ** xref:exchangeProperty-language.adoc[ExchangeProperty Language] ** xref:file-language.adoc[File Language] ** xref:header-language.adoc[Header Language] - ** xref:health-check.adoc[Health Check] ** xref:ref-language.adoc[Ref Language] - ** xref:rest-dsl.adoc[REST DSL Component] - ** xref:return-address.adoc[Return Address] - ** xref:service-registry.adoc[Service Registry] ** xref:simple-language.adoc[Simple Language] ** xref:tokenize-language.adoc[Tokenize Language] - ** xref:transformer.adoc[Transformer] - ** xref:validator.adoc[Validator] * xref:enterprise-integration-patterns.adoc[Enterprise Integration Patterns] ** xref:aggregate-eip.adoc[Aggregate EIP] ** xref:batch-config-eip.adoc[Batch-config EIP] @@ -64,18 +60,15 @@ ** xref:content-based-router-eip.adoc[Content Based Router] ** xref:content-filter-eip.adoc[Content Filter] ** xref:convertBodyTo-eip.adoc[Convert Body To EIP] - ** xref:correlation-identifier.adoc[Correlation Identifier] ** xref:customLoadBalancer-eip.adoc[Custom Load Balancer EIP] - ** xref:dead-letter-channel.adoc[Dead Letter Channel] ** xref:delay-eip.adoc[Delay EIP] + ** xref:dynamic-router.adoc[Dynamic Router] ** xref:dynamicRouter-eip.adoc[Dynamic Router EIP] ** xref:enrich-eip.adoc[Enrich EIP] - ** xref:event-message.adoc[Event Message] ** xref:eventDrivenConsumer-eip.adoc[Event Driven Consumer] ** xref:failover-eip.adoc[Failover EIP] ** xref:filter-eip.adoc[Filter EIP] ** xref:from-eip.adoc[From EIP] - ** xref:guaranteed-delivery.adoc[Guaranteed Delivery] ** xref:hystrix-eip.adoc[Hystrix EIP] ** xref:hystrixConfiguration-eip.adoc[Hystrix Configuration EIP] ** xref:idempotentConsumer-eip.adoc[Idempotent Consumer EIP] @@ -85,20 +78,12 @@ ** xref:log-eip.adoc[Log EIP] ** xref:loop-eip.adoc[Loop EIP] ** xref:marshal-eip.adoc[Marshal EIP] - ** xref:message-bus.adoc[Message Bus] - ** xref:message-channel.adoc[Message Channel] - ** xref:message-endpoint.adoc[Message Endpoint] - ** xref:message-router.adoc[Message Router] - ** xref:message-translator.adoc[Message Translator] - ** xref:message.adoc[Message] ** xref:multicast-eip.adoc[Multicast EIP] ** xref:onFallback-eip.adoc[On Fallback EIP] ** xref:otherwise-eip.adoc[Otherwise EIP] ** xref:pipeline-eip.adoc[Pipeline EIP] - ** xref:point-to-point-channel.adoc[Point to Point Channel] ** xref:pollEnrich-eip.adoc[Poll Enrich EIP] ** xref:process-eip.adoc[Process EIP] - ** xref:publish-subscribe-channel.adoc[Publish Subscribe Channel] ** xref:random-eip.adoc[Random EIP] ** xref:recipientList-eip.adoc[Recipient List EIP] ** xref:removeHeader-eip.adoc[Remove Header EIP] @@ -130,11 +115,9 @@ ** xref:to-eip.adoc[To EIP] ** xref:toD-eip.adoc[To D EIP] ** xref:topic-eip.adoc[Topic EIP] - ** xref:transactional-client.adoc[Transactional Client] ** xref:transform-eip.adoc[Transform EIP] ** xref:unmarshal-eip.adoc[Unmarshal EIP] ** xref:validate-eip.adoc[Validate EIP] ** xref:weighted-eip.adoc[Weighted EIP] ** xref:when-eip.adoc[When EIP] ** xref:wireTap-eip.adoc[Wire Tap EIP] - diff --git a/docs/user-manual/modules/ROOT/pages/annotation-based-expression-language.adoc b/docs/user-manual/modules/ROOT/pages/annotation-based-expression-language.adoc deleted file mode 100644 index ebb46da..0000000 --- a/docs/user-manual/modules/ROOT/pages/annotation-based-expression-language.adoc +++ /dev/null @@ -1,128 +0,0 @@ -[[AnnotationBasedExpressionLanguage-AnnotationBasedExpressionLanguage]] -=== Annotation Based Expression Language - -You can also use any of the link:languages.adoc[Languages] supported in -Camel to bind expressions to method parameters when using -link:bean-integration.adoc[Bean Integration]. For example you can use -any of these annotations: - -[width="100%",cols="50%,50%",options="header",] -|======================================================================= -|Annotation |Description -|@Bean |Inject a <<bean-language,Bean>> expression - -|@Constant |Inject a <<constant-language,Constant>> expression - -|@EL |Inject an <<el-language,EL>> expression - -|@Groovy |Inject a <<groovy-language,Groovy>> expression - -|@Header |Inject a <<header-language,Header>> expression - -|@MVEL |Inject a <<mvel-language,MVEL>> expression - -|@OGNL |Inject an <<ognl-language,OGNL>> expression - -|@Simple |Inject an <<simple-language,Simple>> expression - -|@XPath |Inject an <<xpath-language,XPath>> expression - -|@XQuery |Inject an <<xquery-language,XQuery>> expression -|======================================================================= - -[[AnnotationBasedExpressionLanguage-Example]] -===== Example - -[source,java] ----- -public class Foo { - - @MessageDriven(uri = "activemq:my.queue") - public void doSomething(@XPath("/foo/bar/text()") String correlationID, @Body String body) { - // process the inbound message here - } -} ----- - -[[AnnotationBasedExpressionLanguage-AdvancedexampleusingBean]] -===== Advanced example using @Bean - -And an example of using the the -@Bean binding annotation, where you can use a <<bean-component,POJO>> where you -can do whatever java code you like: - -[source,java] ----- -public class Foo { - - @MessageDriven(uri = "activemq:my.queue") - public void doSomething(@Bean("myCorrelationIdGenerator") String correlationID, @Body String body) { - // process the inbound message here - } -} ----- - -And then we can have a spring bean with the id -`myCorrelationIdGenerator` where we can compute the id. - -[source,java] ----- -public class MyIdGenerator { - - private UserManager userManager; - - public String generate(@Header(name = "user") String user, @Body String payload) throws Exception { - User user = userManager.lookupUser(user); - String userId = user.getPrimaryId(); - String id = userId + generateHashCodeForPayload(payload); - return id; - } -} ----- - -The <<bean-component,POJO>> `MyIdGenerator` has one public method that -accepts two parameters. However we have also annotated this one with the -`@Header` and `@Body` annotation to help Camel know what to bind here from -the Message from the Exchange being processed. - -Of course this could be simplified a lot if you for instance just have a -simple id generator. But we wanted to demonstrate that you can use the -link:bean-binding.adoc[Bean Binding] annotations anywhere. - -[source,java] ----- -public class MySimpleIdGenerator { - - public static int generate() { - // generate a unique id - return 123; - } -} ----- - -And finally we just need to remember to have our bean registered in the -Spring link:registry.adoc[Registry]: - -[source,xml] ----- - <bean id="myCorrelationIdGenerator" class="com.mycompany.MySimpleIdGenerator"/> ----- - -[[AnnotationBasedExpressionLanguage-ExampleusingGroovy]] -===== Example using <<groovy-language,Groovy>> - -In this example we have an Exchange that has a User object stored in the -in header. This User object has methods to get some user information. We -want to use <<groovy.adoc[Groovy] to inject an expression that -extracts and concats the fullname of the user into the fullName -parameter. - -[source,java] ----- - public void doSomething(@Groovy("$request.header['user'].firstName $request.header['user'].familyName) String fullName, @Body String body) { - // process the inbound message here - } ----- - -Groovy supports GStrings that is like a template where we can insert $ -placeholders that will be evaluated by Groovy. diff --git a/docs/user-manual/modules/ROOT/pages/bean-language.adoc b/docs/user-manual/modules/ROOT/pages/bean-language.adoc deleted file mode 100644 index ecab01d..0000000 --- a/docs/user-manual/modules/ROOT/pages/bean-language.adoc +++ /dev/null @@ -1,167 +0,0 @@ -[[bean-language]] -== Bean method Language - -*Available as of Camel version 1.3* - -The purpose of the Bean Language is to be able to implement an -Expression or Predicate using -a simple method on a bean. - -So the idea is you specify a bean name which will then be resolved in -the Registry such as the Spring -ApplicationContext then a method is invoked to evaluate the -Expression or Predicate. - -If no method name is provided then one is attempted to be chosen using -the rules for Bean Binding; using the type of -the message body and using any annotations on the bean methods. - -The Bean Binding rules are used to bind the -Message Exchange to the method parameters; so you can -annotate the bean to extract headers or other expressions such as -<<xpath-language,XPath>> or <<xpath-language,XQuery>> from the message. - -=== Bean Options - -// language options: START -The Bean method language supports 4 options, which are listed below. - - - -[width="100%",cols="2,1m,1m,6",options="header"] -|=== -| Name | Default | Java Type | Description -| ref | | String | Reference to bean to lookup in the registry -| method | | String | Name of method to call -| beanType | | String | Class name of the bean to use -| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks -|=== -// language options: END - - -=== Using Bean Expressions from the Java DSL - -[source,java] ----- -from("activemq:topic:OrdersTopic"). - filter().method("myBean", "isGoldCustomer"). - to("activemq:BigSpendersQueue"); ----- - -=== Using Bean Expressions from XML - -[source,xml] ----- -<route> - <from uri="activemq:topic:OrdersTopic"/> - <filter> - <method ref="myBean" method="isGoldCustomer"/> - <to uri="activemq:BigSpendersQueue"/> - </filter> -</route> ----- - -CAUTION: Bean attribute is now deprecated. The `bean` attribute of the method expression element is now -deprecated. You should now make use of `ref` attribute instead. - -=== Writing the expression bean - -The bean in the above examples is just any old Java Bean with a method -called isGoldCustomer() that returns some object that is easily -converted to a *boolean* value in this case, as its used as a predicate. - -So we could implement it like this... - -[source,java] ----- -public class MyBean { - public boolean isGoldCustomer(Exchange exchange) { - ... - } -} ----- - -We can also use the Bean Integration -annotations. For example you could do... - -[source,java] ----- -public boolean isGoldCustomer(String body) { - // do something -} ----- - -or - -[source,java] ----- -public boolean isGoldCustomer(@Header(name = "foo") Integer fooHeader) { - // do something -} ----- - -So you can bind parameters of the method to the Exchange, the -Message or individual headers, properties, the body -or other expressions. - -=== Non registry beans - -The <<bean-language,Bean Language>> also supports invoking beans -that isn't registered in the Registry. This is -usable for quickly to invoke a bean from Java DSL where you don't need -to register the bean in the Registry such as the -Spring ApplicationContext. - -Camel can instantiate the bean and invoke the method if given a class or -invoke an already existing instance. This is illustrated from the -example below: - -[source,java] ----- -from("activemq:topic:OrdersTopic"). - filter().expression(BeanLanguage(MyBean.class, "isGoldCustomer")). - to("activemq:BigSpendersQueue"); ----- - -The 2nd parameter `isGoldCustomer` is an optional parameter to explicit -set the method name to invoke. If not provided Camel will try to invoke -the best suited method. If case of ambiguity Camel will thrown an -Exception. In these situations the 2nd parameter can solve this problem. -Also the code is more readable if the method name is provided. The 1st -parameter can also be an existing instance of a Bean such as: - -[source,java] ----- -private MyBean my; - - from("activemq:topic:OrdersTopic"). - filter().expression(BeanLanguage.bean(my, "isGoldCustomer")). - to("activemq:BigSpendersQueue"); ----- - -In Camel 2.2 onwards you can avoid the `BeanLanguage` and have it just -as: - -[source,java] ----- -private MyBean my; - - from("activemq:topic:OrdersTopic"). - filter().expression(bean(my, "isGoldCustomer")). - to("activemq:BigSpendersQueue"); ----- - -Which also can be done in a bit shorter and nice way: - -[source,java] ----- -private MyBean my; - - from("activemq:topic:OrdersTopic"). - filter().method(my, "isGoldCustomer"). - to("activemq:BigSpendersQueue"); ----- - -=== Dependencies - -The Bean language is part of *camel-core*. diff --git a/docs/user-manual/modules/ROOT/pages/scala-dsl-eip.adoc b/docs/user-manual/modules/ROOT/pages/scala-dsl-eip.adoc deleted file mode 100644 index 624d9d4..0000000 --- a/docs/user-manual/modules/ROOT/pages/scala-dsl-eip.adoc +++ /dev/null @@ -1,395 +0,0 @@ -= Scala DSL - EIP - -[TIP] -==== -*DSL supported* - -The Scala DSL supports *every* DSL from the -Java DSL. - -On this page we have examples for a number of the EIPs. + - You can check the -https://svn.apache.org/repos/asf/camel/trunk/components/camel-scala/src/test/scala/[unit -test source code] for the Scala Component to find more examples. -==== - -* 1 link:#ScalaDSL-EIP-Messagingsystems[Messaging systems] -** 1.1 link:#ScalaDSL-EIP-Pipelinepipeline[Pipeline] -** 1.2 link:#ScalaDSL-EIP-Filterfilter[Filter] -* 2 link:#ScalaDSL-EIP-Messagingchannels[Messaging channels] -** 2.1 link:#ScalaDSL-EIP-Deadletterchannel[Dead letter channel] -* 3 link:#ScalaDSL-EIP-Messagerouting[Message routing] -** 3.1 link:#ScalaDSL-EIP-Aggregator[Aggregator] -** 3.2 link:#ScalaDSL-EIP-Contentbasedrouter[Content based router] -** 3.3 link:#ScalaDSL-EIP-Delayer[Delayer] -** 3.4 link:#ScalaDSL-EIP-Loadbalancer[Load balancer] -** 3.5 link:#ScalaDSL-EIP-Multicast[Multicast] -** 3.6 link:#ScalaDSL-EIP-Recipientlist[Recipient list] -** 3.7 link:#ScalaDSL-EIP-Resequencer[Resequencer] -** 3.8 link:#ScalaDSL-EIP-Splitter[Splitter] -** 3.9 link:#ScalaDSL-EIP-Throttler[Throttler] -* 4 link:#ScalaDSL-EIP-Messagetransformation[Message transformation] -** 4.1 link:#ScalaDSL-EIP-Contentenricher[Content enricher] - -[[ScalaDSL-EIP-Messagingsystems]] -== Messaging systems - -[[ScalaDSL-EIP-Pipelinepipeline]] -=== Pipeline - -There is a simple syntax available for specifying pipeline, by simple -putting `to` or `→` between the different steps in the pipeline. - -[source,java] ----------------------------------------------------------- -"direct:a" --> "mock:a" --> "mock:b" -"direct:c" to "mock:c" to "mock:d" ----------------------------------------------------------- - -For more advanced use cases, you can also use a block-based syntax, -where every step in the pipeline starts with either `to` or `→`. - -[source,java] ----------------------------------------------------------- -"direct:e" ==> { - --> ("mock:e") - --> ("mock:f") -} - -"direct:g" ==> { - to ("mock:g") - to ("mock:h") -} ----------------------------------------------------------- - -[[ScalaDSL-EIP-Filterfilter]] -=== Filter - -For a message filter, use the `when()` method with a parameter of type -The `Exchange ⇒ Boolean`. In the example below, we use a Scala -convenience method named `in` to access the 'in' message body; only -messages where the 'in' message is `<hello/>` will arrive at the -`mock:a` endpoint. - -[source,scala] ----------------------------------------------------------- -"direct:a" when(_.in == "<hello/>") to("mock:a") ----------------------------------------------------------- - -Once again, if you need to specify a more advanced route, you can use -the more elaborate syntax. - -[source,java] ----------------------------------------------------------- -"direct:b" ==> { - when(_.in == "<hallo/>") { - --> ("mock:b") - to ("mock:c") - } otherwise { - to ("mock:e") - } - to ("mock:d") -} ----------------------------------------------------------- - -[[ScalaDSL-EIP-Messagingchannels]] -==== Messaging channels - -[[ScalaDSL-EIP-Deadletterchannel]] -===== Dead letter channel - -The http://www.eaipatterns.com/DeadLetterChannel.html[dead letter -channel] can be created with the syntax similar to the one used in -http://camel.apache.org/dead-letter-channel.html[Java DSL]. - -[source,java] ------------------------------------------------------------------- -"jms:in" errorHandler(deadLetterChannel("jms:error")) to "jms:out" ------------------------------------------------------------------- - -You can also use different error handler available for the -http://camel.apache.org/error-handler.html[Java DSL]. In particular -Scala DSL supports -http://camel.apache.org/defaulterrorhandler.html[DefaultErrorHandler] -and -http://camel.apache.org/error-handler.html#ErrorHandler-LoggingErrorHandler[LoggingErrorHandler]. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -// DefaultErrorHandler -"jms:in" errorHandler(defaultErrorHandler) to "jms:out" - -// LoggingErrorHandler -"jms:in" errorHandler(loggingErrorHandler.level(LoggingLevel.INFO).logName("com.example.MyLogger")) to "jms:out" ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Messagerouting]] -==== Message routing - -[[ScalaDSL-EIP-Aggregator]] -===== Aggregator - -The aggregator EIP aggregates messages based on some message correlation -criteria. In the Scala DSL, the `aggregate` method takes a function -`Exchange ⇒ Any` to determine the correlation value for the exchange. In -the sample below, message are being aggregated if the first 7 letters in -the message body are the same. - -[[ScalaDSL-EIP-Contentbasedrouter]] -===== Content based router - -Similar to the Filter, the content based router -uses `when` methods with `Exchange ⇒ Boolean` function literals and an -optional `otherwise`. The function literal can contain plain Scala code -as well as any of the link:scala-dsl-supported-languages.html[supported -languages]. The example below routes a given message based on the -language of the message body. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" ==> { - to ("mock:polyglot") - choice { - when (_.in == "<hello/>") to ("mock:english") - when (_.in == "<hallo/>") { - to ("mock:dutch") - to ("mock:german") - } - otherwise to ("mock:french") - } -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Delayer]] -===== Delayer - -Unlike a throttler, which only slows down messages if the rate exceeds a -threshold, a delayer delays every messages with a fixed amount of time. -An example: to delay every message going from `seda:a` to `mock:a` with -1 second, you write... - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"seda:a" delay(1 seconds) to ("mock:a") ----------------------------------------------------------------------------------------------------------------- - -Our second example will delay the entire block (containing `mock:c`) -without doing anything to `mock:b` - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"seda:b" ==> { - to ("mock:b") - delay(1 seconds) { - to ("mock:c") - } -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Loadbalancer]] -===== Load balancer - -To distribute the message handling load over multiple endpoints, we add -a `loadbalance` to our route definition. You can optionally specify a -load balancer strategy, like `roundrobin` - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" ==> { - loadbalance roundrobin { - to ("mock:a") - to ("mock:b") - to ("mock:c") - } -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Multicast]] -===== Multicast - -Multicast allows you to send a message to multiple endpoints at the same -time. In a simple route, you can specify multiple targets in the `to` or -`→` method call: - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" --> ("mock:a", "mock:b") --> "mock:c" -"direct:d" to ("mock:d", "mock:e") to "mock:f" ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Recipientlist]] -===== Recipient list - -You can handle a static recipient list with a multicast or -pipeline, but this EIP is usually applied when -you want to dynamically determine the name(s) of the next endpoint(s) to -route to. Use the `recipients()` method with a function literal -(`Exchange => Any`) that returns the endpoint name(s). In the example -below, the target endpoint name can be found in the String message -starting at position 21. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" recipients(_.in[String].substring(21)) ----------------------------------------------------------------------------------------------------------------- - -Because the `recipients()` method just takes a function literal, you can -basically use any kind of valid Scala code to determine the endpoint -name. Have a look at the next example which uses pattern matching to -figure out where to send the message: - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:b" recipients(_.getIn.getBody match { - case Toddler(_) => "mock:playgarden" - case _ => "mock:work" -}) ----------------------------------------------------------------------------------------------------------------- - -Again, we can also use the same thing in a more block-like syntax. For -this example, we use the Scala DSL's -support for JXPath to determine -the target. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:c" ==> { - to("mock:c") - recipients(jxpath("./in/body/destination")) -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Resequencer]] -===== Resequencer - -Use the `resequence` method to add a resequencer to the RouteBuilder. -The method takes a function (`Exchange ⇒ Unit`) that determines the -value to resequence on. In this example, we resequence messages based on -the 'in' message body. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" resequence (_.in) to "mock:a" ----------------------------------------------------------------------------------------------------------------- - -The same EIP can also be used with a block-like syntax... - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:b" ==> { - to ("mock:b") - resequence (_.in) { - to ("mock:c") - } -} ----------------------------------------------------------------------------------------------------------------- - -... and with configurable batch size. In this last example, messages -will be send to `mock:e` whenever a batch of 5 messages is available. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:d" ==> { - to ("mock:d") - resequence(_.in).batch(5) { - to ("mock:e") - } -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Splitter]] -===== Splitter - -To handle large message in smaller chunks, you can write a Scala -`Exchange ⇒ Any*` method and add it to your route with the `splitter` -method. As with many other EIPs, we support a short, in-line version as -well as a more elaborate block based one. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" as(classOf[Document]) split(xpath("/persons/person")) to "mock:a" ----------------------------------------------------------------------------------------------------------------- - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:b" ==> { - as(classOf[Document]) - split(xpath("/persons/person")) { - to("mock:b") - to("mock:c") - } -} ----------------------------------------------------------------------------------------------------------------- - -The above examples also show you how -other languages like XPath can -be within the Scala DSL. - -[[ScalaDSL-EIP-Throttler]] -===== Throttler - -The throttler allows you to slow down messages before sending them -along. The `throttle` methods allows you to specify the maximum -throughput rate of message: - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"seda:a" throttle (3 per (2 seconds)) to ("mock:a") ----------------------------------------------------------------------------------------------------------------- - -It can also be used in front of block to throttle messages at that -point. In the example below, message are passed on to `mock:b` in a -normal rate (i.e. as fast as possible), but a maximum 3 messages/2 -seconds will arrive at the `mock:c` endpoint. - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"seda:b" ==> { - to ("mock:b") - throttle (3 per (2 seconds)) { - to ("mock:c") - } -} ----------------------------------------------------------------------------------------------------------------- - -[[ScalaDSL-EIP-Messagetransformation]] -==== Message transformation - -[[ScalaDSL-EIP-Contentenricher]] -===== Content enricher - -Using a processor function (`Exchange → Unit`), you can alter/enrich the -message content. This example uses a simple function literal to append -`" says Hello"` to the message content: - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:a" process(_.in += " says hello") to ("mock:a") ----------------------------------------------------------------------------------------------------------------- - -However, you can also define a separate method/function to handle the -transformation and pass that to the `process` method instead. The -example below uses pattern matching to enrich the message content: - -[source,java] ----------------------------------------------------------------------------------------------------------------- -val myProcessor = (exchange: Exchange) => { - exchange.in match { - case "hello" => exchange.in = "hello from the UK" - case "hallo" => exchange.in = "hallo vanuit Belgie" - case "bonjour" => exchange.in = "bonjour de la douce France" - } -} - -"direct:b" process(myProcessor) to ("mock:b") ----------------------------------------------------------------------------------------------------------------- - -Off course, you can also use any other Camel component (e.g. -<<velocity-component,Velocity>>) to enrich the content and add it to a -pipeline - - -[source,java] ----------------------------------------------------------------------------------------------------------------- -"direct:c" to ("velocity:org/apache/camel/scala/dsl/enricher.vm") to ("mock:c") -----------------------------------------------------------------------------------------------------------------