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>