You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/03/18 06:19:00 UTC
[camel] branch master updated: dsl: add support for Groovy (#5231)
This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 3fae737 dsl: add support for Groovy (#5231)
3fae737 is described below
commit 3fae737bded1f1ca30580bdde2361c852e6b6b80
Author: Luca Burgazzoli <lb...@users.noreply.github.com>
AuthorDate: Thu Mar 18 07:18:29 2021 +0100
dsl: add support for Groovy (#5231)
---
bom/camel-bom/pom.xml | 5 +
dsl/camel-groovy-dsl/pom.xml | 200 +++++++++++++++++++
.../services/org/apache/camel/routes-loader/groovy | 2 +
dsl/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc | 13 ++
.../org/apache/camel/dsl/groovy/GroovyDSL.groovy | 135 +++++++++++++
.../dsl/groovy/GroovyRoutesBuilderLoader.groovy | 87 +++++++++
.../extensions/CamelContextExtensions.groovy | 33 ++++
.../extensions/ExpressionClauseExtensions.groovy | 56 ++++++
.../ProcessorDefinitionExtensions.groovy | 47 +++++
.../dsl/groovy/model/BeanConfiguration.groovy | 86 +++++++++
.../dsl/groovy/model/BeansConfiguration.groovy | 72 +++++++
.../dsl/groovy/model/CamelConfiguration.groovy | 45 +++++
.../camel/dsl/groovy/model/Components.groovy | 47 +++++
.../groovy/model/ComponentsConfiguration.groovy | 91 +++++++++
.../groovy/model/DataFormatsConfiguration.groovy | 92 +++++++++
.../dsl/groovy/model/LanguagesConfiguration.groovy | 91 +++++++++
.../dsl/groovy/model/RestConfiguration.groovy | 38 ++++
.../dsl/groovy/model/RestVerbConfiguration.groovy | 102 ++++++++++
.../org.codehaus.groovy.runtime.ExtensionModule | 6 +
.../src/main/resources/integration.gdsl | 21 ++
.../dsl/groovy/GroovyRouteBuilderLoaderTest.groovy | 213 +++++++++++++++++++++
.../apache/camel/dsl/groovy/support/MyBean.groovy | 29 +++
.../src/test/resources/log4j2-test.properties | 31 +++
.../test/resources/routes/issues/github-529.groovy | 29 +++
.../test/resources/routes/routes-with-beans.groovy | 32 ++++
...ith-component-wrong-method-configuration.groovy | 29 +++
...h-component-wrong-property-configuration.groovy | 28 +++
.../routes-with-components-configuration.groovy | 41 ++++
.../routes-with-dataformats-configuration.groovy | 35 ++++
.../test/resources/routes/routes-with-eip.groovy | 23 +++
.../routes/routes-with-endpoint-dsl.groovy | 21 ++
.../routes/routes-with-error-handler.groovy | 23 +++
.../routes-with-languages-configuration.groovy | 36 ++++
.../test/resources/routes/routes-with-rest.groovy | 42 ++++
.../src/test/resources/routes/routes.groovy | 18 ++
dsl/pom.xml | 1 +
parent/pom.xml | 5 +
37 files changed, 1905 insertions(+)
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 9536ef5..5c551d5 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -829,6 +829,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-groovy-dsl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-grpc</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/dsl/camel-groovy-dsl/pom.xml b/dsl/camel-groovy-dsl/pom.xml
new file mode 100644
index 0000000..e9e81fa
--- /dev/null
+++ b/dsl/camel-groovy-dsl/pom.xml
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>dsl</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-groovy-dsl</artifactId>
+ <packaging>jar</packaging>
+ <name>Camel :: Groovy DSL</name>
+ <description>Camel DSL with Groovy</description>
+
+ <properties>
+ <firstVersion>3.9.0</firstVersion>
+ <sourcecheckExcludes>
+ **/resources/**/My*.java
+ </sourcecheckExcludes>
+ <sourcecheckExcludesComma>
+ ${sourcecheckExcludes},
+ </sourcecheckExcludesComma>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-endpointdsl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-main</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-direct</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-rest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-languages</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-bean</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-log</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-telegram</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-seda</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-timer</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <version>${spock-version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-jcl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.gmavenplus</groupId>
+ <artifactId>gmavenplus-plugin</artifactId>
+ <version>${gmavenplus-plugin-version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>addSources</goal>
+ <goal>addTestSources</goal>
+ <goal>compile</goal>
+ <goal>compileTests</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <invokeDynamic>true</invokeDynamic>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-package-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-spi</id>
+ <goals>
+ <goal>generate-spi</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/groovy b/dsl/camel-groovy-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/groovy
new file mode 100644
index 0000000..f8ac58c
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/groovy
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.dsl.groovy.GroovyRoutesBuilderLoader
diff --git a/dsl/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc b/dsl/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc
new file mode 100644
index 0000000..24f8805
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc
@@ -0,0 +1,13 @@
+[[groovy-dsl-other]]
+= Groovy DSL
+:docTitle: Groovy Dsl
+:artifactId: camel-groovy-dsl
+:description: Camel DSL with Groovy
+:supportLevel: Experimental
+:since: 3.
+:supportLevel: Preview
+include::{cq-version}@camel-quarkus:ROOT:partial$reference/others/groovy-dsl.adoc[opts=optional]
+//Manually maintained attributes
+:group: DSL
+
+See https://camel.apache.org/manual/latest/dsl.html
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyDSL.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyDSL.groovy
new file mode 100644
index 0000000..81fba6c
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyDSL.groovy
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy
+
+import org.apache.camel.Exchange
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.builder.BuilderSupport
+import org.apache.camel.builder.EndpointConsumerBuilder
+import org.apache.camel.builder.ErrorHandlerBuilder
+import org.apache.camel.builder.endpoint.EndpointBuilderFactory
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder
+import org.apache.camel.dsl.groovy.model.BeansConfiguration
+import org.apache.camel.dsl.groovy.model.CamelConfiguration
+import org.apache.camel.dsl.groovy.model.Components
+import org.apache.camel.dsl.groovy.model.RestConfiguration
+import org.apache.camel.model.InterceptDefinition
+import org.apache.camel.model.InterceptFromDefinition
+import org.apache.camel.model.InterceptSendToEndpointDefinition
+import org.apache.camel.model.OnCompletionDefinition
+import org.apache.camel.model.OnExceptionDefinition
+import org.apache.camel.model.RouteDefinition
+import org.apache.camel.model.rest.RestConfigurationDefinition
+import org.apache.camel.model.rest.RestDefinition
+import org.apache.camel.spi.Registry
+
+class GroovyDSL extends BuilderSupport implements EndpointBuilderFactory {
+ final Registry registry
+ final Components components
+ final EndpointRouteBuilder builder
+
+ GroovyDSL(EndpointRouteBuilder builder) {
+ super(builder.context)
+
+ this.registry = this.context.registry
+ this.components = new Components(this.context)
+ this.builder = builder
+ }
+
+ def beans(@DelegatesTo(BeansConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new BeansConfiguration(context)
+ callable.call()
+ }
+
+ def camel(@DelegatesTo(CamelConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new CamelConfiguration(context)
+ callable.call()
+ }
+
+ def rest(@DelegatesTo(RestConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new RestConfiguration(builder)
+ callable.call()
+ }
+
+ RestDefinition rest() {
+ return builder.rest()
+ }
+
+ RestConfigurationDefinition restConfiguration() {
+ builder.restConfiguration();
+ }
+
+ RestDefinition rest(String path) {
+ return builder.rest(path)
+ }
+
+ RouteDefinition from(String endpoint) {
+ return builder.from(endpoint)
+ }
+
+ RouteDefinition from(EndpointConsumerBuilder endpoint) {
+ return builder.from(endpoint)
+ }
+
+ OnExceptionDefinition onException(Class<? extends Throwable> exception) {
+ return builder.onException(exception)
+ }
+
+ OnCompletionDefinition onCompletion() {
+ return builder.onCompletion()
+ }
+
+ InterceptDefinition intercept() {
+ return builder.intercept()
+ }
+
+ InterceptFromDefinition interceptFrom() {
+ return builder.interceptFrom()
+ }
+
+ InterceptFromDefinition interceptFrom(String uri) {
+ return builder.interceptFrom(uri)
+ }
+
+ InterceptSendToEndpointDefinition interceptSendToEndpoint(String uri) {
+ return builder.interceptSendToEndpoint(uri)
+ }
+
+ void errorHandler(ErrorHandlerBuilder handler) {
+ builder.errorHandler(handler)
+ }
+
+ static Processor processor(@DelegatesTo(Exchange) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+
+ return {
+ callable.call(it)
+ } as Processor
+ }
+
+ static Predicate predicate(@DelegatesTo(Exchange) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+
+ return {
+ return callable.call(it)
+ } as Predicate
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyRoutesBuilderLoader.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyRoutesBuilderLoader.groovy
new file mode 100644
index 0000000..e27a10f
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/GroovyRoutesBuilderLoader.groovy
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy
+
+import org.apache.camel.Experimental
+import org.apache.camel.ExtendedCamelContext
+import org.apache.camel.RoutesBuilder
+import org.apache.camel.StartupStep
+import org.apache.camel.api.management.ManagedAttribute
+import org.apache.camel.api.management.ManagedResource
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder
+import org.apache.camel.spi.Resource
+import org.apache.camel.spi.StartupStepRecorder
+import org.apache.camel.spi.annotations.RoutesLoader
+import org.apache.camel.support.RoutesBuilderLoaderSupport
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+
+@Experimental
+@ManagedResource(description = "Managed GroovyRoutesBuilderLoader")
+@RoutesLoader(EXTENSION)
+class GroovyRoutesBuilderLoader extends RoutesBuilderLoaderSupport {
+ public static final String EXTENSION = "groovy";
+
+ private StartupStepRecorder recorder;
+
+ @Override
+ protected void doBuild() throws Exception {
+ super.doBuild();
+
+ if (getCamelContext() != null) {
+ this.recorder = getCamelContext().adapt(ExtendedCamelContext.class).getStartupStepRecorder();
+ }
+ }
+
+ @ManagedAttribute(description = "Supported file extension")
+ @Override
+ public String getSupportedExtension() {
+ return EXTENSION;
+ }
+
+ @Override
+ public RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception {
+ StartupStep step = recorder != null
+ ? recorder.beginStep(GroovyRoutesBuilderLoader.class, resource.getLocation(), "Compiling RouteBuilder")
+ : null;
+
+ try {
+ return EndpointRouteBuilder.loadEndpointRoutesBuilder(resource, this::load);
+ } finally {
+ if (recorder != null) {
+ recorder.endStep(step);
+ }
+ }
+ }
+
+ private void load(Reader reader, EndpointRouteBuilder builder) {
+ def ic = new ImportCustomizer()
+ ic.addStarImports('org.apache.camel')
+ ic.addStarImports('org.apache.camel.spi')
+
+ def cc = new CompilerConfiguration()
+ cc.addCompilationCustomizers(ic)
+ cc.setScriptBaseClass(DelegatingScript.class.getName())
+
+ def sh = new GroovyShell(new Binding(), cc)
+ def script = (DelegatingScript) sh.parse(reader)
+
+ // set the delegate target
+ script.setDelegate(new GroovyDSL(builder))
+ script.run()
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/CamelContextExtensions.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/CamelContextExtensions.groovy
new file mode 100644
index 0000000..39065e1
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/CamelContextExtensions.groovy
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.extensions
+
+import groovy.transform.CompileStatic
+import org.apache.camel.CamelContext
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder
+
+@CompileStatic
+class CamelContextExtensions {
+ static void addRoutes(CamelContext self, @DelegatesTo(RouteBuilder.class) Closure<?> callable) {
+ self.addRoutes(EndpointRouteBuilder.loadRoutesBuilder {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = it
+ callable.call()
+ })
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ExpressionClauseExtensions.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ExpressionClauseExtensions.groovy
new file mode 100644
index 0000000..9257f13
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ExpressionClauseExtensions.groovy
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.extensions
+
+import groovy.transform.CompileStatic
+import org.apache.camel.Message
+import org.apache.camel.builder.ExpressionClause
+
+import java.util.function.Function
+
+@CompileStatic
+class ExpressionClauseExtensions {
+ static <T> T body(ExpressionClause<T> self, Closure<?> callable) {
+ return self.body(new Function<Object, Object>() {
+ @Override
+ Object apply(Object body) {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ return callable.call(body)
+ }
+ })
+ }
+
+ static <T, B> T body(ExpressionClause<T> self, Class<B> type, Closure<?> callable) {
+ return self.body(type, new Function<B, Object>() {
+ @Override
+ Object apply(B body) {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ return callable.call(body)
+ }
+ })
+ }
+
+ static <T> T message(ExpressionClause<T> self, @DelegatesTo(Message) Closure<?> callable) {
+ return self.message(new Function<Message, Object>() {
+ @Override
+ Object apply(Message body) {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ return callable.call(body)
+ }
+ })
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ProcessorDefinitionExtensions.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ProcessorDefinitionExtensions.groovy
new file mode 100644
index 0000000..d23d97f
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/extensions/ProcessorDefinitionExtensions.groovy
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.extensions
+
+import groovy.transform.CompileStatic
+import org.apache.camel.Exchange
+import org.apache.camel.Processor
+import org.apache.camel.model.ProcessorDefinition
+
+import java.util.function.Function
+
+@CompileStatic
+class ProcessorDefinitionExtensions {
+ static <T extends ProcessorDefinition<T>> T setBody(ProcessorDefinition<T> self, Closure<?> callable) {
+ return self.setBody(new Function<Exchange, Object>() {
+ @Override
+ Object apply(Exchange exchange) {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ return callable.call(exchange)
+ }
+ });
+ }
+
+ static <T extends ProcessorDefinition<T>> T process(ProcessorDefinition<T> self, Closure<?> callable) {
+ return self.process(new Processor() {
+ @Override
+ void process(Exchange exchange) throws Exception {
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.call(exchange)
+ }
+ });
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeanConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeanConfiguration.groovy
new file mode 100644
index 0000000..ecf5756
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeanConfiguration.groovy
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.ExtendedCamelContext
+import org.apache.camel.support.PropertyBindingSupport
+
+class BeanConfiguration {
+ private final CamelContext context
+ private final Object target
+
+ BeanConfiguration(CamelContext camelContext, Object target) {
+ this.context = camelContext
+ this.target = target
+ }
+
+ def methodMissing(String name, arguments) {
+ Object value = null
+ final Object[] args = arguments as Object[]
+
+ if (args == null) {
+ value = null
+ } else if (args.length == 1) {
+ value = args[0]
+ } else {
+ throw new IllegalArgumentException("Unable to set property '${name}' on target '${target.class.name}'")
+ }
+
+ if (value instanceof Closure<?>) {
+ def m = this.target.metaClass.getMetaMethod(name, Closure.class)
+ if (m) {
+ m.invoke(target, args)
+
+ // done
+ return
+ }
+ }
+
+ boolean bound = PropertyBindingSupport.build()
+ .withCamelContext(context)
+ .withTarget(target)
+ .withProperty(name, value)
+ .bind()
+
+ if (!bound) {
+ throw new MissingMethodException(name, this.target.class, args as Object[])
+ }
+ }
+
+ def propertyMissing(String name, value) {
+ boolean bound = PropertyBindingSupport.build()
+ .withCamelContext(context)
+ .withTarget(target)
+ .withProperty(name, value)
+ .bind()
+
+ if (!bound) {
+ throw new MissingPropertyException(name, this.target.class)
+ }
+ }
+
+ def propertyMissing(String name) {
+ def props = new HashMap<String, Object>()
+
+ context.adapt(ExtendedCamelContext.class)
+ .getBeanIntrospection()
+ .getProperties(target, props, null, false)
+
+ return props[name]
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeansConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeansConfiguration.groovy
new file mode 100644
index 0000000..8676217
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/BeansConfiguration.groovy
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Exchange
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.builder.endpoint.EndpointBuilderFactory
+
+class BeansConfiguration implements EndpointBuilderFactory {
+ private final CamelContext context
+
+ BeansConfiguration(CamelContext context) {
+ this.context = context
+ }
+
+ def propertyMissing(String name, value) {
+ context.registry.bind(name, value)
+ }
+
+ def methodMissing(String name, arguments) {
+ final Object[] args = arguments as Object[]
+
+ if (args != null && args.length == 2) {
+ def type = args[0] as Class<?>
+ def clos = args[1] as Closure<?>
+ def bean = context.injector.newInstance(type)
+
+ clos.resolveStrategy = Closure.DELEGATE_ONLY
+ clos.delegate = bean
+ clos.call()
+
+ context.registry.bind(name, type, bean)
+ } else if (args != null && args.length == 1) {
+ def clos = args[0] as Closure<?>
+ clos.resolveStrategy = Closure.DELEGATE_ONLY
+
+ context.registry.bind(name, clos.call())
+ }
+ }
+
+ static Processor processor(@DelegatesTo(Exchange) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+
+ return {
+ callable.call(it)
+ } as Processor
+ }
+
+ static Predicate predicate(@DelegatesTo(Exchange) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+
+ return {
+ return callable.call(it)
+ } as Predicate
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/CamelConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/CamelConfiguration.groovy
new file mode 100644
index 0000000..ae9c732
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/CamelConfiguration.groovy
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+
+class CamelConfiguration {
+ private final CamelContext context
+
+ CamelConfiguration(CamelContext context) {
+ this.context = context
+ }
+
+ def components(@DelegatesTo(ComponentsConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new ComponentsConfiguration(context)
+ callable.call()
+ }
+
+ def dataFormats(@DelegatesTo(DataFormatsConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new DataFormatsConfiguration(context)
+ callable.call()
+ }
+
+ def languages(@DelegatesTo(LanguagesConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new LanguagesConfiguration(context)
+ callable.call()
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/Components.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/Components.groovy
new file mode 100644
index 0000000..b2af1b8
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/Components.groovy
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Component
+
+class Components {
+ private final CamelContext context
+
+ Components(CamelContext context) {
+ this.context = context
+ }
+
+ Component get(String scheme) {
+ return context.getComponent(scheme, true)
+ }
+
+ Component put(String scheme, Component instance) {
+ context.addComponent(scheme, instance)
+
+ return instance;
+ }
+
+ Component make(String scheme, String type) {
+ final Class<?> clazz = context.getClassResolver().resolveClass(type)
+ final Component instance = (Component)context.getInjector().newInstance(clazz)
+
+ context.addComponent(scheme, instance)
+
+ return instance;
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/ComponentsConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/ComponentsConfiguration.groovy
new file mode 100644
index 0000000..2d5cff1
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/ComponentsConfiguration.groovy
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Component
+
+class ComponentsConfiguration {
+ private final CamelContext context
+
+ ComponentsConfiguration(CamelContext context) {
+ this.context = context
+ }
+
+ def component(String name, Closure<?> callable) {
+ def target = context.getComponent(name, true, false)
+ if (target == null) {
+ throw new IllegalArgumentException("Unable to find a component with name: ${name}")
+ }
+
+ // Just make sure the closure context is belong to component
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+ }
+
+ def component(String name, Class<? extends Component> type, Closure <?> callable) {
+ def target = context.getComponent(name, true, false)
+ def bind = false
+
+ if (target != null && !type.isInstance(target)) {
+ throw new IllegalArgumentException("Type mismatch, expected: ${type} , got: ${target.class}")
+ }
+
+ // if the component is not found, let's create a new one. This is
+ // equivalent to create a new named component, useful to create
+ // multiple instances of the same component but with different setup
+ if (target == null) {
+ target = context.injector.newInstance(type)
+ bind = true
+ }
+
+ // Just make sure the closure context is belong to component
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+
+ if (bind) {
+ context.registry.bind(name, type, target)
+ }
+ }
+
+ def methodMissing(String name, arguments) {
+ final Object[] args = arguments as Object[]
+
+ if (args != null) {
+ if (args.length == 1) {
+ def clos = args[0]
+
+ if (clos instanceof Closure) {
+ return component(name, clos)
+ }
+ }
+ if (args.length == 2) {
+ def type = args[0]
+ def clos = args[1]
+
+ if (type instanceof Class && Component.class.isAssignableFrom(type) && clos instanceof Closure) {
+ return component(name, type, clos)
+ }
+ }
+ }
+
+ throw new MissingMethodException(name, this, args)
+ }
+
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/DataFormatsConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/DataFormatsConfiguration.groovy
new file mode 100644
index 0000000..237d352
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/DataFormatsConfiguration.groovy
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.spi.DataFormat
+
+class DataFormatsConfiguration {
+ private final CamelContext context
+
+ DataFormatsConfiguration(CamelContext context) {
+ this.context = context
+ }
+
+ def dataFormat(String name, Closure<?> callable) {
+ def target = context.resolveDataFormat(name)
+ if (target == null) {
+ throw new IllegalArgumentException("Unable to find a dataformat with name: ${name}")
+ }
+
+ // Just make sure the closure context is belong to component
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+
+ // let's the camel context be aware of the new dataformat
+ context.registry.bind(name, DataFormat.class, target)
+ }
+
+ def dataFormat(String name, Class<? extends DataFormat> type, Closure <?> callable) {
+ def target = context.registry.lookupByNameAndType(name, type)
+ def bind = false
+
+ // if the dataformat is not found, let's create a new one. This is
+ // equivalent to create a new named dataformat, useful to create
+ // multiple instances of the same dataformat but with different setup
+ if (target == null) {
+ target = context.injector.newInstance(type)
+
+ bind = true
+ }
+
+ // Just make sure the closure context is belong to dataformat
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+
+ if (bind) {
+ // let's the camel context be aware of the new dataformat
+ context.registry.bind(name, type, target)
+ }
+ }
+
+ def methodMissing(String name, arguments) {
+ final Object[] args = arguments as Object[]
+
+ if (args != null) {
+ if (args.length == 1) {
+ def clos = args[0]
+
+ if (clos instanceof Closure) {
+ return dataFormat(name, clos)
+ }
+ }
+ if (args.length == 2) {
+ def type = args[0]
+ def clos = args[1]
+
+ if (type instanceof Class && DataFormat.class.isAssignableFrom(type) && clos instanceof Closure) {
+ return dataFormat(name,type, clos)
+ }
+ }
+ }
+
+ throw new MissingMethodException(name, this, args)
+ }
+
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/LanguagesConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/LanguagesConfiguration.groovy
new file mode 100644
index 0000000..a34dc17
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/LanguagesConfiguration.groovy
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.spi.Language
+
+class LanguagesConfiguration {
+ private final CamelContext context
+
+ LanguagesConfiguration(CamelContext context) {
+ this.context = context
+ }
+
+ def language(String name, Closure<?> callable) {
+ def target = context.resolveLanguage(name)
+ if (target == null) {
+ throw new IllegalArgumentException("Unable to find a language with name: ${name}")
+ }
+
+ // Just make sure the closure context is belong to component
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+
+ // let's the camel context be aware of the new dataformat
+ context.registry.bind(name, Language.class, target)
+ }
+
+ def language(String name, Class<? extends Language> type, Closure <?> callable) {
+ def target = context.registry.lookupByNameAndType(name, type)
+ def bind = false
+
+ // if the language is not found, let's create a new one. This is
+ // equivalent to create a new named language, useful to create
+ // multiple instances of the same language but with different setup
+ if (target == null) {
+ target = context.injector.newInstance(type)
+
+ bind = true
+ }
+
+ // Just make sure the closure context is belong to dataformat
+ callable.resolveStrategy = Closure.DELEGATE_ONLY
+ callable.delegate = new BeanConfiguration(context, target)
+ callable.call()
+
+ if (bind) {
+ // let's the camel context be aware of the new dataformat
+ context.registry.bind(name, type, target)
+ }
+ }
+
+ def methodMissing(String name, arguments) {
+ final Object[] args = arguments as Object[]
+
+ if (args != null) {
+ if (args.length == 1) {
+ def clos = args[0]
+
+ if (clos instanceof Closure) {
+ return language(name, clos)
+ }
+ }
+ if (args.length == 2) {
+ def type = args[0]
+ def clos = args[1]
+
+ if (type instanceof Class && Language.class.isAssignableFrom(type) && clos instanceof Closure) {
+ return language(name,type, clos)
+ }
+ }
+ }
+
+ throw new MissingMethodException(name, this, args)
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestConfiguration.groovy
new file mode 100644
index 0000000..ccaae28
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestConfiguration.groovy
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.model.rest.RestConfigurationDefinition
+
+class RestConfiguration extends RestVerbConfiguration {
+ RestConfiguration(RouteBuilder builder) {
+ super(builder, null)
+ }
+
+ def configuration(@DelegatesTo(RestConfigurationDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = builder.restConfiguration()
+ callable.call()
+ }
+
+ def path(String path, @DelegatesTo(RestVerbConfiguration) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = new RestVerbConfiguration(builder, path)
+ callable.call()
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestVerbConfiguration.groovy b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestVerbConfiguration.groovy
new file mode 100644
index 0000000..ec76e5f
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/groovy/org/apache/camel/dsl/groovy/model/RestVerbConfiguration.groovy
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.model
+
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.model.rest.RestDefinition
+
+class RestVerbConfiguration {
+ protected final RouteBuilder builder
+ protected final RestDefinition definition
+
+ RestVerbConfiguration(RouteBuilder builder, String path) {
+ this.builder = builder
+ this.definition = builder.rest(path)
+ }
+
+ def get(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.get(path)
+ callable.call()
+ }
+
+ def get(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.get()
+ callable.call()
+ }
+
+ def post(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.post(path)
+ callable.call()
+ }
+
+ def post(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.post()
+ callable.call()
+ }
+
+ def delete(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.delete(path)
+ callable.call()
+ }
+
+ def delete(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.delete()
+ callable.call()
+ }
+
+ def head(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.head(path)
+ callable.call()
+ }
+
+ def head(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.head()
+ callable.call()
+ }
+
+ def put(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.put(path)
+ callable.call()
+ }
+
+ def put(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.put()
+ callable.call()
+ }
+
+ def patch(String path, @DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.patch(path)
+ callable.call()
+ }
+
+ def patch(@DelegatesTo(RestDefinition) Closure<?> callable) {
+ callable.resolveStrategy = Closure.DELEGATE_FIRST
+ callable.delegate = definition.patch()
+ callable.call()
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/dsl/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
new file mode 100644
index 0000000..35c23f2
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
@@ -0,0 +1,6 @@
+moduleName=camel-k-loader-groovy
+moduleVersion=1.0.0
+extensionClasses=\
+ org.apache.camel.dsl.groovy.extensions.ExpressionClauseExtensions,\
+ org.apache.camel.dsl.groovy.extensions.ProcessorDefinitionExtensions,\
+ org.apache.camel.dsl.groovy.extensions.CamelContextExtensions
diff --git a/dsl/camel-groovy-dsl/src/main/resources/integration.gdsl b/dsl/camel-groovy-dsl/src/main/resources/integration.gdsl
new file mode 100644
index 0000000..05aff0e
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/main/resources/integration.gdsl
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+def ctx = context(scope: scriptScope())
+
+contributor(ctx) {
+ delegatesTo(findClass('org.apache.camel.dsl.groovy.GroovyDSL'))
+}
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/GroovyRouteBuilderLoaderTest.groovy b/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/GroovyRouteBuilderLoaderTest.groovy
new file mode 100644
index 0000000..d0fbbe0
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/GroovyRouteBuilderLoaderTest.groovy
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy
+
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.component.jackson.JacksonDataFormat
+import org.apache.camel.component.seda.SedaComponent
+import org.apache.camel.dsl.groovy.support.MyBean
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.impl.engine.DefaultChannel
+import org.apache.camel.language.bean.BeanLanguage
+import org.apache.camel.model.FromDefinition
+import org.apache.camel.model.ToDefinition
+import org.apache.camel.model.rest.GetVerbDefinition
+import org.apache.camel.model.rest.PostVerbDefinition
+import org.apache.camel.processor.FatalFallbackErrorHandler
+import org.apache.camel.processor.SendProcessor
+import org.apache.camel.spi.HeaderFilterStrategy
+import org.apache.camel.support.DefaultHeaderFilterStrategy
+import spock.lang.AutoCleanup
+import spock.lang.Specification
+
+class GroovyRouteBuilderLoaderTest extends Specification {
+ @AutoCleanup
+ def context = new DefaultCamelContext()
+
+ def loadRoute(String location) {
+ def route = context.getResourceLoader().resolveResource(location)
+ context.getRoutesLoader().loadRoutes(route)
+ }
+
+ def "load routes"() {
+ when:
+ loadRoute('/routes/routes.groovy')
+ then:
+ with(context.routeDefinitions) {
+ it.size() == 1
+
+ it[0].outputs[0] instanceof ToDefinition
+ it[0].input.endpointUri == 'timer:tick'
+ }
+ }
+
+ def "load routes with endpoint dsl"() {
+ when:
+ loadRoute('/routes/routes-with-endpoint-dsl.groovy')
+ then:
+ with(context.routeDefinitions) {
+ it.size() == 1
+
+ with(it[0].input, FromDefinition) {
+ it.endpointUri == 'timer://tick?period=1s'
+ }
+ with(it[0].outputs[0], ToDefinition) {
+ it.endpointUri == 'log://info'
+ }
+ }
+ }
+
+ def "load integration with rest"() {
+ when:
+ loadRoute('/routes/routes-with-rest.groovy')
+ then:
+ context.restConfiguration.host == 'my-host'
+ context.restConfiguration.port == 9192
+ context.restDefinitions.size() == 2
+
+ with(context.restDefinitions.find {it.path == '/my/path'}) {
+ verbs.size() == 1
+
+ with(verbs.first(), GetVerbDefinition) {
+ uri == '/get'
+ consumes == 'application/json'
+ produces == 'application/json'
+
+ with(to) {
+ endpointUri == 'direct:get'
+ }
+ }
+ }
+
+ with(context.restDefinitions.find {it.path == '/post'}) {
+ verbs.size() == 1
+
+ with(verbs.first(), PostVerbDefinition) {
+ uri == null
+ consumes == 'application/json'
+ produces == 'application/json'
+
+ with(to) {
+ endpointUri == 'direct:post'
+ }
+ }
+ }
+ }
+
+ def "load integration with beans"() {
+ when:
+ loadRoute('/routes/routes-with-beans.groovy')
+
+ then:
+ with(context.registry) {
+ it.findByType(MyBean).size() == 1
+ it.lookupByName('myBean') instanceof MyBean
+ it.findByType(HeaderFilterStrategy).size() == 1
+ it.lookupByName('filterStrategy') instanceof DefaultHeaderFilterStrategy
+ it.lookupByName('myProcessor') instanceof Processor
+ it.lookupByName('myPredicate') instanceof Predicate
+ }
+ }
+
+ def "load integration with components configuration"() {
+ when:
+ loadRoute('/routes/routes-with-components-configuration.groovy')
+
+ then:
+ with(context.getComponent('seda', SedaComponent)) {
+ queueSize == 1234
+ concurrentConsumers == 12
+ }
+ with(context.getComponent('mySeda', SedaComponent)) {
+ queueSize == 4321
+ concurrentConsumers == 21
+ }
+ }
+
+ def "load integration with languages configuration"() {
+ when:
+ loadRoute('/routes/routes-with-languages-configuration.groovy')
+
+ then:
+ with(context.resolveLanguage('bean'), BeanLanguage) {
+ beanType == String.class
+ method == "toUpperCase"
+ }
+ with(context.resolveLanguage('myBean'), BeanLanguage) {
+ beanType == String.class
+ method == "toLowerCase"
+ }
+ }
+
+ def "load integration with dataformats configuration"() {
+ when:
+ loadRoute('/routes/routes-with-dataformats-configuration.groovy')
+
+ then:
+ with(context.resolveDataFormat('json-jackson'), JacksonDataFormat) {
+ unmarshalType == Map.class
+ prettyPrint
+ }
+ with(context.resolveDataFormat('my-jackson'), JacksonDataFormat) {
+ unmarshalType == String.class
+ (!prettyPrint)
+ }
+ }
+
+ def "load integration with component error property configuration"() {
+ when:
+ loadRoute('/routes/routes-with-component-wrong-property-configuration.groovy')
+ then:
+ def e = thrown MissingPropertyException
+ assert e.message.contains("No such property: queueNumber for class: org.apache.camel.component.seda.SedaComponent")
+
+ }
+
+ def "load integration with component error method configuration"() {
+ when:
+ loadRoute('/routes/routes-with-component-wrong-method-configuration.groovy')
+ then:
+ def e = thrown MissingMethodException
+ assert e.message.contains("No signature of method: org.apache.camel.component.seda.SedaComponent.queueNumber()")
+
+ }
+
+ def "load integration with error handler"() {
+ when:
+ loadRoute('/routes/routes-with-error-handler.groovy')
+ context.start()
+ then:
+ context.routes?.size() == 1
+ context.routes[0].getOnException('my-on-exception') != null
+ context.routes[0].getOnException('my-on-exception') instanceof FatalFallbackErrorHandler
+
+ def eh = context.routes[0].getOnException('my-on-exception') as FatalFallbackErrorHandler
+ def ch = eh.processor as DefaultChannel
+
+ ch.output instanceof SendProcessor
+ }
+
+ // Test groovy eip extension, relates to https://issues.apache.org/jira/browse/CAMEL-14300
+ def "load integration with eip"() {
+ when:
+ loadRoute('/routes/routes-with-eip.groovy')
+ context.start()
+ then:
+ 1 == 1
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/support/MyBean.groovy b/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/support/MyBean.groovy
new file mode 100644
index 0000000..19242c2
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/groovy/org/apache/camel/dsl/groovy/support/MyBean.groovy
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.groovy.support
+
+class MyBean {
+ private String name
+
+ String getName() {
+ return name
+ }
+
+ void setName(String name) {
+ this.name = name
+ }
+}
diff --git a/dsl/camel-groovy-dsl/src/test/resources/log4j2-test.properties b/dsl/camel-groovy-dsl/src/test/resources/log4j2-test.properties
new file mode 100644
index 0000000..6cb5c3b
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/log4j2-test.properties
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-groovy-dsl-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
+#rootLogger.appenderRef.out.ref = out
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/issues/github-529.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/issues/github-529.groovy
new file mode 100644
index 0000000..246698b
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/issues/github-529.groovy
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+beans {
+ processInvoice = processor {
+ it.out.body = [
+ orderId: 'myOderId',
+ datetime: System.currentTimeMillis(),
+ currency: 'USD',
+ invoiceId: 'B-0' + (Math.floor(1000 + Math.random() * 9999))
+ ]
+ }
+}
+
+from('direct:process')
+ .process('processInvoice')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-beans.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-beans.groovy
new file mode 100644
index 0000000..e6e35e0
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-beans.groovy
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+beans {
+ myBean(org.apache.camel.dsl.groovy.support.MyBean) {
+ name = "test"
+ }
+ filterStrategy {
+ new org.apache.camel.support.DefaultHeaderFilterStrategy()
+ }
+
+ myProcessor = processor {
+ it.in.body = 'value'
+ }
+
+ myPredicate = predicate {
+ false
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-method-configuration.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-method-configuration.groovy
new file mode 100644
index 0000000..0496fe6
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-method-configuration.groovy
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.component.seda.SedaComponent
+
+camel {
+ components {
+ mySeda(SedaComponent) {
+ // a wrong method name
+ queueNumber 33
+ }
+ }
+}
+
+from('timer:tick')
+ .to('log:info')
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-property-configuration.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-property-configuration.groovy
new file mode 100644
index 0000000..e34832c
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-component-wrong-property-configuration.groovy
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+camel {
+ components {
+ seda {
+ // a wrong property name
+ queueNumber = 33
+ }
+ }
+}
+
+from('timer:tick')
+ .to('log:info')
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-components-configuration.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-components-configuration.groovy
new file mode 100644
index 0000000..7849982
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-components-configuration.groovy
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.component.seda.SedaComponent
+
+camel {
+ components {
+ seda {
+ // set value as method
+ queueSize 1234
+
+ // set value as property
+ concurrentConsumers = 12
+ }
+
+ mySeda(SedaComponent) {
+ // set value as method
+ queueSize 4321
+
+ // set value as property
+ concurrentConsumers = 21
+ }
+ }
+}
+
+
+from('timer:tick')
+ .to('log:info')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-dataformats-configuration.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-dataformats-configuration.groovy
new file mode 100644
index 0000000..68b55bf
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-dataformats-configuration.groovy
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.component.jackson.JacksonDataFormat
+
+camel {
+ dataFormats {
+ dataFormat("json-jackson") {
+ unmarshalType = Map.class
+ prettyPrint = true
+ }
+ dataFormat("my-jackson", JacksonDataFormat) {
+ unmarshalType = String.class
+ prettyPrint = false
+ }
+ }
+}
+
+
+from('timer:tick')
+ .to('log:info')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-eip.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-eip.groovy
new file mode 100644
index 0000000..3a4fa07
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-eip.groovy
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+from("direct:1")
+ .setBody { "" }
+ .transform().body { b -> null}
+ .transform().message { m -> null}
+ .transform().exchange { e -> null}
+ .process {e -> e.in.body = null }
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-endpoint-dsl.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-endpoint-dsl.groovy
new file mode 100644
index 0000000..1e69931
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-endpoint-dsl.groovy
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+def f = timer('tick').period('1s')
+def t = log('info')
+
+from(f)
+ .to(t)
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-error-handler.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-error-handler.groovy
new file mode 100644
index 0000000..fa36c49
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-error-handler.groovy
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+onException(IllegalArgumentException.class)
+ .id('my-on-exception')
+ .to('log:exception')
+
+from('timer:tick')
+ .to('log:info')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-languages-configuration.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-languages-configuration.groovy
new file mode 100644
index 0000000..707e057
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-languages-configuration.groovy
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.language.bean.BeanLanguage
+
+camel {
+
+ languages {
+ bean {
+ beanType = String.class
+ method = "toUpperCase"
+ }
+ myBean(BeanLanguage) {
+ beanType = String.class
+ method = "toLowerCase"
+ }
+ }
+}
+
+
+from('timer:tick')
+ .to('log:info')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-rest.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-rest.groovy
new file mode 100644
index 0000000..8ae6cdf
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes-with-rest.groovy
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+rest {
+ configuration {
+ host 'my-host'
+ port '9192'
+ }
+
+ path('/my/path') {
+ get('/get') {
+ consumes 'application/json'
+ produces 'application/json'
+ to 'direct:get'
+ }
+ }
+
+ post {
+ path '/post'
+ consumes 'application/json'
+ produces 'application/json'
+ to 'direct:post'
+ }
+}
+
+from('direct:get')
+ .to('log:get')
+from('direct:post')
+ .to('log:post')
\ No newline at end of file
diff --git a/dsl/camel-groovy-dsl/src/test/resources/routes/routes.groovy b/dsl/camel-groovy-dsl/src/test/resources/routes/routes.groovy
new file mode 100644
index 0000000..ceac916
--- /dev/null
+++ b/dsl/camel-groovy-dsl/src/test/resources/routes/routes.groovy
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+from('timer:tick')
+ .to('log:info')
\ No newline at end of file
diff --git a/dsl/pom.xml b/dsl/pom.xml
index 310cb36..f4b9346 100644
--- a/dsl/pom.xml
+++ b/dsl/pom.xml
@@ -34,6 +34,7 @@
<description>Camel DSLs Modules</description>
<modules>
+ <module>camel-groovy-dsl</module>
<module>camel-java-joor-dsl</module>
<module>camel-xml-io-dsl</module>
<module>camel-xml-jaxb-dsl</module>
diff --git a/parent/pom.xml b/parent/pom.xml
index c07ad1f..eaeeab8 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2709,6 +2709,11 @@
<artifactId>camel-kotlin-dsl</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-groovy-dsl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!-- camel catalog -->
<dependency>