Added DSL and Groovy-DSL docs to Gitbook
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/70d6968f Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/70d6968f Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/70d6968f Branch: refs/heads/master Commit: 70d6968fd5c2a79f2eb874bf6a854d8d3aaf58c3 Parents: b308eda Author: Andrea Cosentino <anco...@gmail.com> Authored: Tue Jul 19 10:50:00 2016 +0200 Committer: Andrea Cosentino <anco...@gmail.com> Committed: Tue Jul 19 10:50:00 2016 +0200 ---------------------------------------------------------------------- docs/user-manual/en/SUMMARY.md | 3 +- docs/user-manual/en/dsl.adoc | 44 ++++ docs/user-manual/en/groovy-dsl.adoc | 402 +++++++++++++++++++++++++++++++ 3 files changed, 448 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/70d6968f/docs/user-manual/en/SUMMARY.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index 610d9d4..448836f 100644 --- a/docs/user-manual/en/SUMMARY.md +++ b/docs/user-manual/en/SUMMARY.md @@ -17,6 +17,8 @@ * [Delay Interceptor](delay-interceptor.adoc) * [Dependency Injection](dependency-injection.adoc) * [Dozer Type Conversion](dozer-type-conversion.adoc) + * [DSL](dsl.adoc) + * [Groovy DSL](groovy-dsl.adoc) * [Endpoint](endpoint.adoc) * [Exchange](exchange.adoc) * [Exchange Pattern](exchange-pattern.adoc) @@ -28,7 +30,6 @@ <!-- * [AOP](aop.adoc) * [Camel-Core](camel-core.adoc) - * [DSL](dsl.adoc) * [Error Handler](.adoc) * [Expression](.adoc) * [Injector](.adoc) http://git-wip-us.apache.org/repos/asf/camel/blob/70d6968f/docs/user-manual/en/dsl.adoc ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/dsl.adoc b/docs/user-manual/en/dsl.adoc new file mode 100644 index 0000000..31f10ad --- /dev/null +++ b/docs/user-manual/en/dsl.adoc @@ -0,0 +1,44 @@ +[[DSL-DSL]] +DSL +~~~ + +Camel uses a Java _Domain Specific Language_ or DSL for creating +link:enterprise-integration-patterns.html[Enterprise Integration +Patterns] or link:routes.html[Routes] in a variety of domain-specific +languages (DSL) as listed below. + +* link:java-dsl.html[Java DSL] - A Java based DSL using the fluent +builder style. +* link:spring.html[Spring XML] - A XML based DSL in Spring XML files +* link:using-osgi-blueprint-with-camel.html[Blueprint XML] - A XML based +DSL in OSGi Blueprint XML files +* link:rest-dsl.html[Rest DSL] - A DSL to define REST services using a +REST style in either Java or XML. +* link:groovy-dsl.html[Groovy DSL] - A Groovy based DSL using Groovy +programming language +* link:scala-dsl.html[Scala DSL] - A Scala based DSL using Scala +programming language +* link:bean-integration.html[Annotation DSL] - Use annotations in Java +beans. +* https://github.com/koolio/kool/tree/master/kool-camel[Kotlin DSL] - +*Work in progress* - Currently developed outside ASF, but will we +included later in Camel when Kotlin and the DSL is ready. + +The main entry points for the DSL are + +* link:camelcontext.html[CamelContext] for creating a Camel routing +rulebase +* link:routebuilder.html[RouteBuilder] for creating a collection of +routes using the routing DSL + +[[DSL-SeeAlso]] +See Also +^^^^^^^^ + +For more examples of the DSL in action see + +* link:enterprise-integration-patterns.html[Enterprise Integration +Patterns] +* link:examples.html[Examples] +* link:routes.html[Routes] + http://git-wip-us.apache.org/repos/asf/camel/blob/70d6968f/docs/user-manual/en/groovy-dsl.adoc ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/groovy-dsl.adoc b/docs/user-manual/en/groovy-dsl.adoc new file mode 100644 index 0000000..8f3c126 --- /dev/null +++ b/docs/user-manual/en/groovy-dsl.adoc @@ -0,0 +1,402 @@ +[[GroovyDSL-AbouttheGroovyDSL]] +About the Groovy DSL +^^^^^^^^^^^^^^^^^^^^ + +The Groovy DSL implementation is built on top of the existing Java-based +link:dsl.html[DSL], but it additionally allows to use Groovy language +features in your routes, particularly +http://www.groovy-lang.org/closures.html[Closures] acting as +link:processor.html[Processor], link:expression.html[Expression], +link:predicate.html[Predicate], or link:aggregator.html[Aggregation +Strategy]. + + With the Groovy DSL you write your RouteBuilder classes entirely in +Groovy, while the link:scripting-languages.html[scripting component] +allows to embed small scripts into Java routes. The Groovy DSL requires +Groovy 2.0 or newer and is available as of *Camel 2.11*. + +[[GroovyDSL-Introduction]] +Introduction +^^^^^^^^^^^^ + +Because Groovy is syntactically very similar to Java, you can write your +Groovy routes just like Java routes. The same Java DSL classes are being +used, with the exception that some of the DSL classes get extended with +a bunch of new methods at runtime. This is achieved by turning +camel-groovy into a Groovy +http://docs.codehaus.org/display/GROOVY/Creating+an+extension+module[Extension +Module] that defines extension methods on existing classes. + +The majority of the extension methods allow +http://www.groovy-lang.org/closures.html[Closures] to be used as +parameters e.g. for expressions, predicates, processors. The following +example reverses a string in the message body and then prints the value +to System.out: + +*MyRouteBuilder.groovy* + +[source,java] +----------------------------------------- +... + from('direct:test') + .transform { it.in.body.reverse() } + .process { println it.in.body } +... +----------------------------------------- + +The corresponding route in Java would look something like this: + +*MyRouteBuilder.java* + +[source,java] +----------------------------------------------------------------------------------------- +... + from("direct:test") + .transform(new Expression() { + @Override + public Object evaluate(Exchange e) { + return new StringBuffer(e.getIn().getBody().toString()).reverse().toString(); + } + }) + .process(new Processor() { + @Override + public void process(Exchange e) { + System.out.println(e.getIn().getBody()); + } + }); +... +----------------------------------------------------------------------------------------- + +[[GroovyDSL-DevelopingwiththeGroovyDSL]] +Developing with the Groovy DSL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To be able to use the Groovy DSL in your camel routes you need to add +the a dependency on *camel-groovy* which implements the Groovy DSL. + +If you use Maven you can just add the following to your pom.xml, +substituting the version number for the latest & greatest release (see +the download page for the latest versions). + +[source,xml] +--------------------------------------- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-groovy</artifactId> + <version>2.11.0</version> +</dependency> +--------------------------------------- + +Additionally you need to make sure that the Groovy classes will be +compiled. You can either use gmaven for this or, particularly with mixed +projects containing Java and Groovy code, you might want to use the +http://groovy.codehaus.org/Groovy-Eclipse+compiler+plugin+for+Maven[Groovy +Eclipse compiler]: + +[source,xml] +-------------------------------------------------------- + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerId>groovy-eclipse-compiler</compilerId> + </configuration> + <dependencies> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-compiler</artifactId> + <version>2.7.0-01</version> + </dependency> + </dependencies> + </plugin> +-------------------------------------------------------- + +As Eclipse user, you might want to configure the Maven Eclipse plugin in +a way so that your project is set up correctly for using +http://groovy.codehaus.org/Eclipse+Plugin[Eclipse Plugin for Groovy] +when `mvn eclipse:eclipse` is executed: + +[source,xml] +---------------------------------------------------------------------------------------- + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-eclipse-plugin</artifactId> + <configuration> + <additionalProjectnatures> + <projectnature>org.eclipse.jdt.groovy.core.groovyNature</projectnature> + </additionalProjectnatures> + <classpathContainers> + <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer> + <classpathContainer>GROOVY_DSL_SUPPORT</classpathContainer> + </classpathContainers> + </configuration> + </plugin> +---------------------------------------------------------------------------------------- + +[[GroovyDSL-UsingClosuresinyourroutes]] +Using Closures in your routes ++++++++++++++++++++++++++++++ + +Groovy closures can be used to write concise implementations of Camel +processors, expressions, predicates, and aggregation strategies. It is +recommended to keep more complicated implementations of these objects in +their own classes, e.g. to be able to test them more easily and not to +clutter up your routes with business logic. + +[[GroovyDSL-ProcessorClosures]] +Processor Closures + +All Java DSL parameters of type `org.apache.camel.Processor` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is disregarded. All closures may also refer to variables not +listed in their parameter list. Example: + +[source,java] +------------------------------------------------------------------------------ +... + private String someValue +... + from('direct:test') + .process { Exchange exchange -> println (exchange.in.body + someValue) } + .process { println (it.in.body + someValue) } // equivalent +... +------------------------------------------------------------------------------ + +[[GroovyDSL-ExpressionClosures]] +Expression Closures + +All Java DSL parameters of type `org.apache.camel.Expression` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is the result of the expression. Example: + +[source,java] +----------------------------------------------------- +... + private String someValue +... + from('direct:test') + .transform { it.in.body.reverse() + someValue } + .setHeader("myHeader") { someValue.reverse() } +... +----------------------------------------------------- + +[[GroovyDSL-PredicateClosures]] +Predicate Closures + +All Java DSL parameters of type `org.apache.camel.Predicate` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is translated into a boolean value representing the result of +the predicate. Example: + +[source,java] +------------------------------------------------------ +... + private String someValue + + // This time, the closure is stored in a variable + def pred = { Exchange e -> e.in.body != someValue } +... + from('direct:test') + .filter(pred) +... +------------------------------------------------------ + +[[GroovyDSL-AggregationStrategyClosures]] +Aggregation Strategy Closures + +Java DSL parameters of type +`org.apache.camel.processor.aggregate.AggregationStrategy` can be +replaced by a closure that accepts two objects of type +`org.apache.camel.Exchange` representing the two Exchanges to be +aggregated. The return value of the closure must be the aggregated +Exchange. Example: + +[source,java] +------------------------------------------------------------------------- +... + private String separator +... + from('direct:test1') + .enrich('direct:enrich') { Exchange original, Exchange resource -> + original.in.body += resource.in.body + separator + original // don't forget to return resulting exchange + } +... +------------------------------------------------------------------------- + +[[GroovyDSL-Genericclosurebridges]] +Generic closure bridges + +In addition to the above-mentioned DSL extensions, you can use closures +even if no DSL method signature with closure parameters is available. +Assuming there's no `filter(Closure)` method, you could instead write: + +[source,java] +--------------------------------------------------------- +... + private String someValue + + // This time, the closure is stored in a variable + def pred = { Exchange e -> e.in.body != someValue } +... + from('direct:test') + // predicate(Closure) -> org.apache.camel.Predicate + .filter(predicate(pred)) +... +--------------------------------------------------------- + +Similarly, `expression(Closure)` returns a Camel expression, +`processor(Closure)` returns a Processor, and `aggregator(Closure)` +returns an AggregationStrategy. + +[[GroovyDSL-UsingGroovyXMLprocessing]] +Using Groovy XML processing ++++++++++++++++++++++++++++ + +Groovy provides special http://groovy-lang.org/processing-xml.html[XML +processing support] through its `XmlParser`, `XmlNodePrinter` and +`XmlSlurper` classes. camel-groovy provides two +link:data-format.html[data formats] to use these classes directly in +your routes. + +*Unmarshal XML with XmlParser* + +[source,java] +----------------------------------------------------- +... + from('direct:test1') + .unmarshal().gnode() + // message body is now of type groovy.util.Node +... +----------------------------------------------------- + +By default, XML processing is _namespace-aware_. You can change this by +providing a boolean `false` parameter. + +*Unmarshal XML with XmlSlurper* + +[source,java] +--------------------------------------------------------------------------- +... + from('direct:test1') + .unmarshal().gpath(false) // explicitly namespace-unaware + // message body is now of type groovy.util.slurpersupport.GPathResult +... +--------------------------------------------------------------------------- + +Currently, marshalling is only supported for `groovy.util.Node` objects. + +*Marshal XML with XmlNodePrinter* + +[source,java] +------------------------------------------------------ +... + from('direct:test1') + // message body must be of type groovy.util.Node + .marshal().gnode() +... +------------------------------------------------------ + +[[GroovyDSL-UsingGroovyGStrings]] +Using Groovy GStrings ++++++++++++++++++++++ + +Groovy +http://docs.groovy-lang.org/latest/html/documentation/index.html#all-strings[GStrings] +are declared inside double-quotes and can contain arbitrary Groovy +expressions like accessing properties or calling methods, e.g. + +[source,java] +----------------------------------------- +def x = "It is currently ${ new Date() }" +----------------------------------------- + +Because GStrings aren't Strings, camel-groovy adds the necessary +link:type-converter.html[TypeConverter] to automatically turn them into +the required type. + +[[GroovyDSL-CustomDSLextensions]] +Custom DSL extensions ++++++++++++++++++++++ + +You can easily define your custom extensions - be it as a Java DSL +extension for your Groovy routes or for any other class unrelated to +Camel. All you have to do is to write your extension methods and provide +a extension module descriptor - the details are described in the +http://www.groovy-lang.org/metaprogramming.html#_extension_modules[Groovy +documentation]. And as long as you don't require other extension +methods, you can even use plain Java code to achieve this! + + As an example, let's write two DSL extensions to make commonly used DSL +methods more concise: + +*MyExtension.java* + +[source,java] +------------------------------------------------------------------------------------------------------------------------------- +import org.apache.camel.Endpoint; +import org.apache.camel.Predicate; + +public final class MyExtension { + private MyExtension() { + // Utility Class + } + + // Set the id of a route to its consumer URI + public static RouteDefinition fromId(RouteDefinition delegate, String uri) { + return delegate.from(uri).routeId(uri); + } + + public static RouteDefinition fromId(RouteDefinition delegate, Endpoint endpoint) { + return delegate.from(endpoint).routeId(endpoint.getEndpointUri()); + } + + // Make common choice pattern more concise + + public static ProcessorDefinition<?> fork(ProcessorDefinition<?> delegate, String uri1, String uri2, Predicate predicate) { + return delegate.choice().when(predicate).to(uri1).otherwise().to(uri2); + } + +} +------------------------------------------------------------------------------------------------------------------------------- + +Add a corresponding extension module descriptor to `META-INF/services`: + +*META-INF/services/org.codehaus.groovy.runtime.ExtensionModule* + +[source,java] +---------------------------- +moduleName=my-extension +moduleVersion=2.11 +extensionClasses=MyExtension +staticExtensionClasses= +---------------------------- + +And now your Groovy route can look like this: + +*MyRoute.groovy* + +[source,java] +------------------------------------------------------------ +... + fromId('direct:test1') + .fork('direct:null','direct:not-null',body().isNull()) +... +------------------------------------------------------------ + +Using the plain Java DSL, the route would look something like this: + +*MyRoute.java* + +[source,java] +----------------------------------- +... + from("direct:test1") + .routeId("direct:test1") + .choice() + .when(body().isNull()) + .to("direct:null") + .otherwise() + .to("direct:not-null"); +... +-----------------------------------