You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@camel.apache.org by GitBox <gi...@apache.org> on 2018/10/02 15:06:28 UTC

[GitHub] nicolaferraro closed pull request #148: runtime: enhance groovy dsl

nicolaferraro closed pull request #148: runtime: enhance groovy dsl
URL: https://github.com/apache/camel-k/pull/148
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/runtime/.gitignore b/runtime/.gitignore
new file mode 100644
index 00000000..ed929831
--- /dev/null
+++ b/runtime/.gitignore
@@ -0,0 +1,10 @@
+target
+
+*.iml
+
+.idea
+.project
+.metadata
+.settings
+.factorypath
+.classpath
diff --git a/runtime/catalog-builder/pom.xml b/runtime/catalog-builder/pom.xml
index 931bef8c..ff5c84a3 100644
--- a/runtime/catalog-builder/pom.xml
+++ b/runtime/catalog-builder/pom.xml
@@ -61,7 +61,6 @@
             <artifactId>groovy-all</artifactId>
             <version>${groovy.version}</version>
             <scope>runtime</scope>
-            <type>pom</type>
           </dependency>
           <dependency>
             <groupId>org.apache.camel</groupId>
diff --git a/runtime/groovy/pom.xml b/runtime/groovy/pom.xml
index 5fdc4fd6..deae9590 100644
--- a/runtime/groovy/pom.xml
+++ b/runtime/groovy/pom.xml
@@ -38,6 +38,18 @@
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-groovy</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.codehaus.groovy</groupId>
+                    <artifactId>groovy-all</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+            <version>${groovy.version}</version>
+            <classifier>indy</classifier>
         </dependency>
 
         <!-- ****************************** -->
@@ -46,6 +58,18 @@
         <!--                                -->
         <!-- ****************************** -->
 
+        <dependency>
+            <groupId>org.spockframework</groupId>
+            <artifactId>spock-core</artifactId>
+            <version>${spock.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.codehaus.groovy</groupId>
+                    <artifactId>groovy-all</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
@@ -60,4 +84,27 @@
         </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>
+        </plugins>
+    </build>
+
 </project>
diff --git a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
new file mode 100644
index 00000000..e3042aaa
--- /dev/null
+++ b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
@@ -0,0 +1,57 @@
+/**
+ * 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.k.groovy
+
+
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.k.groovy.dsl.Integration
+import org.apache.camel.k.jvm.Language
+import org.apache.camel.k.jvm.RoutesLoader
+import org.apache.camel.k.jvm.RuntimeRegistry
+import org.apache.camel.util.ResourceHelper
+import org.codehaus.groovy.control.CompilerConfiguration
+
+class GroovyRoutesLoader implements RoutesLoader {
+    @Override
+    List<Language> getSupportedLanguages() {
+        return Collections.singletonList(Language.Groovy)
+    }
+
+    @Override
+    RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
+        return new RouteBuilder() {
+            @Override
+            void configure() throws Exception {
+                def cc = new CompilerConfiguration()
+                cc.setScriptBaseClass(DelegatingScript.class.getName())
+
+                def cl = Thread.currentThread().getContextClassLoader()
+                def sh = new GroovyShell(cl, new Binding(), cc)
+                def is = ResourceHelper.resolveMandatoryResourceAsInputStream(context, resource)
+
+                is.withCloseable {
+                    def reader = new InputStreamReader(is)
+                    def script = (DelegatingScript) sh.parse(reader)
+
+                    // set the delegate target
+                    script.setDelegate(new Integration(registry, this))
+                    script.run()
+                }
+            }
+        }
+    }
+}
diff --git a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/ComponentConfiguration.groovy b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/ComponentConfiguration.groovy
new file mode 100644
index 00000000..33aea0b1
--- /dev/null
+++ b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/ComponentConfiguration.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.k.groovy.dsl
+
+
+import org.apache.camel.util.IntrospectionSupport
+
+import java.lang.reflect.Array
+
+class ComponentConfiguration {
+    private final org.apache.camel.Component component
+
+    ComponentConfiguration(org.apache.camel.Component component) {
+        this.component = component
+    }
+
+    def methodMissing(String name, args) {
+        final Object value
+
+        if (args == null) {
+            value = null
+        } else if (!args.getClass().isArray()) {
+            value = args
+        } else if (Array.getLength(args) == 1) {
+            value = Array.get(args, 0)
+        } else {
+            throw new IllegalArgumentException("Unable to set property \"" + name + "\" on component \"" + name + "\"")
+        }
+
+        if (value instanceof Closure<?>) {
+            def m = this.component.metaClass.getMetaMethod(name, Closure.class)
+            if (m) {
+                m.invoke(component, args)
+
+                // done
+                return
+            }
+        }
+
+        if (!IntrospectionSupport.setProperty(component, name, value, true)) {
+            throw new MissingMethodException("Missing method \"" + name + "\" on component: \"" + this.component.class.name + "\"")
+        }
+    }
+
+    def propertyMissing(String name, value) {
+        if (!IntrospectionSupport.setProperty(component, name, value, true)) {
+            throw new MissingMethodException("Missing method \"" + name + "\" on component: \"" + this.component.class.name + "\"")
+        }
+    }
+
+    def propertyMissing(String name) {
+        def properties = [:]
+
+        IntrospectionSupport.getProperties(component, properties, null, false)
+
+        return properties[name]
+    }
+}
diff --git a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/Integration.groovy b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/Integration.groovy
new file mode 100644
index 00000000..f3127f60
--- /dev/null
+++ b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/dsl/Integration.groovy
@@ -0,0 +1,84 @@
+/**
+ * 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.k.groovy.dsl
+
+import org.apache.camel.CamelContext
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.k.jvm.RuntimeRegistry
+import org.apache.camel.k.jvm.dsl.Components
+import org.apache.camel.model.RouteDefinition
+import org.apache.camel.model.rest.RestConfigurationDefinition
+import org.apache.camel.model.rest.RestDefinition
+
+class Integration {
+    private final RuntimeRegistry registry
+
+    final CamelContext context
+    final Components components
+    final RouteBuilder builder
+
+    Integration(RuntimeRegistry registry, RouteBuilder builder) {
+        this.registry = registry
+        this.context = builder.getContext()
+        this.components = new Components(this.context)
+        this.builder = builder
+    }
+
+    def component(String name, Closure<?> callable) {
+        def component = context.getComponent(name, true, false)
+
+        callable.resolveStrategy = Closure.DELEGATE_ONLY
+        callable.delegate = new ComponentConfiguration(component)
+        callable.call()
+    }
+
+    RouteDefinition from(String endpoint) {
+        return builder.from(endpoint)
+    }
+
+    RestDefinition rest() {
+        return builder.rest()
+    }
+
+    def rest(Closure<?> callable) {
+        callable.resolveStrategy = Closure.DELEGATE_ONLY
+        callable.delegate = builder.rest()
+        callable.call()
+    }
+
+    RestConfigurationDefinition restConfiguration() {
+        return builder.restConfiguration()
+    }
+
+    def restConfiguration(Closure<?> callable) {
+        callable.resolveStrategy = Closure.DELEGATE_ONLY
+        callable.delegate = builder.restConfiguration()
+        callable.call()
+    }
+
+    def restConfiguration(String component, Closure<?> callable) {
+        callable.resolveStrategy = Closure.DELEGATE_ONLY
+        callable.delegate = builder.restConfiguration(component)
+        callable.call()
+    }
+
+    def registry(Closure<?> callable) {
+        callable.resolveStrategy = Closure.DELEGATE_ONLY
+        callable.delegate = registry
+        callable.call()
+    }
+}
diff --git a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/extension/LogComponentExtension.groovy b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/extension/LogComponentExtension.groovy
new file mode 100644
index 00000000..cb60da09
--- /dev/null
+++ b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/extension/LogComponentExtension.groovy
@@ -0,0 +1,34 @@
+/**
+ * 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.k.groovy.extension
+
+import org.apache.camel.Exchange
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.spi.ExchangeFormatter
+
+class LogComponentExtension {
+    static void formatter(LogComponent self, Closure callable) {
+        self.exchangeFormatter = new ExchangeFormatter() {
+            @Override
+            String format(Exchange exchange) {
+                callable.resolveStrategy = Closure.DELEGATE_ONLY
+                callable.delegate = exchange
+                callable.call()
+            }
+        }
+    }
+}
diff --git a/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java b/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java
deleted file mode 100644
index 6b7beeda..00000000
--- a/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * 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.k.groovy;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.lang.reflect.Array;
-import java.util.Collections;
-import java.util.List;
-
-import groovy.lang.Binding;
-import groovy.lang.Closure;
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.GroovyShell;
-import groovy.util.DelegatingScript;
-import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.k.jvm.Language;
-import org.apache.camel.k.jvm.RoutesLoader;
-import org.apache.camel.k.jvm.RuntimeRegistry;
-import org.apache.camel.k.jvm.dsl.Components;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.rest.RestConfigurationDefinition;
-import org.apache.camel.model.rest.RestDefinition;
-import org.apache.camel.util.IntrospectionSupport;
-import org.apache.camel.util.ResourceHelper;
-import org.codehaus.groovy.control.CompilerConfiguration;
-
-public class GroovyRoutesLoader implements RoutesLoader {
-    @Override
-    public List<Language> getSupportedLanguages() {
-        return Collections.singletonList(Language.Groovy);
-    }
-
-    @Override
-    public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                CompilerConfiguration cc = new CompilerConfiguration();
-                cc.setScriptBaseClass(DelegatingScript.class.getName());
-
-                ClassLoader cl = Thread.currentThread().getContextClassLoader();
-                GroovyShell sh = new GroovyShell(cl, new Binding(), cc);
-
-                try (InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getContext(), resource)) {
-                    Reader reader = new InputStreamReader(is);
-                    DelegatingScript script = (DelegatingScript) sh.parse(reader);
-
-                    // set the delegate target
-                    script.setDelegate(new Scripting(registry, this));
-                    script.run();
-                }
-            }
-        };
-    }
-
-
-    public static class Scripting  {
-        private final RuntimeRegistry registry;
-
-        public final CamelContext context;
-        public final Components components;
-        public final RouteBuilder builder;
-
-        public Scripting(RuntimeRegistry registry, RouteBuilder builder) {
-            this.registry = registry;
-            this.context = builder.getContext();
-            this.components = new Components(this.context);
-            this.builder = builder;
-        }
-
-        public Component component(String name, Closure<Component> callable) {
-            final Component component = context.getComponent(name, true);
-
-            callable.setResolveStrategy(Closure.DELEGATE_ONLY);
-            callable.setDelegate(new GroovyObjectSupport() {
-                public Object invokeMethod(String name, Object arg) {
-                    final Object value;
-
-                    if (arg == null) {
-                        value = null;
-                    } else if (!arg.getClass().isArray()) {
-                        value = arg;
-                    } else if (Array.getLength(arg) == 1) {
-                        value = Array.get(arg, 0);
-                    } else {
-                        throw new IllegalArgumentException("Unable to set property \"" + name + "\" on component \"" + name + "\"");
-                    }
-
-                    try {
-                        IntrospectionSupport.setProperty(component, name, value, true);
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-
-                    return component;
-                }
-            });
-
-            return callable.call();
-        }
-
-        public RouteDefinition from(String endpoint) {
-            return builder.from(endpoint);
-        }
-
-        public RestDefinition rest() {
-            return builder.rest();
-        }
-
-        public RestDefinition rest(Closure<RestDefinition> callable) {
-            callable.setResolveStrategy(Closure.DELEGATE_ONLY);
-            callable.setDelegate(builder.rest());
-            return callable.call();
-        }
-
-        public RestConfigurationDefinition restConfiguration() {
-            return builder.restConfiguration();
-        }
-
-        public void restConfiguration(Closure<?> callable) {
-            callable.setResolveStrategy(Closure.DELEGATE_ONLY);
-            callable.setDelegate(builder.restConfiguration());
-            callable.call();
-        }
-
-        public RestConfigurationDefinition restConfiguration(String component, Closure<RestConfigurationDefinition> callable) {
-            callable.setResolveStrategy(Closure.DELEGATE_ONLY);
-            callable.setDelegate(builder.restConfiguration(component));
-            return callable.call();
-        }
-
-        public RuntimeRegistry registry(Closure<RuntimeRegistry> callable) {
-            callable.setResolveStrategy(Closure.DELEGATE_ONLY);
-            callable.setDelegate(registry);
-
-            return callable.call();
-        }
-    }
-}
diff --git a/runtime/groovy/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/runtime/groovy/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
new file mode 100644
index 00000000..217436e2
--- /dev/null
+++ b/runtime/groovy/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
@@ -0,0 +1,4 @@
+moduleName=camel-k-runtime-groovy
+moduleVersion=0.0.3-SNAPSHOT
+extensionClasses=org.apache.camel.k.groovy.extension.LogComponentExtension
+#staticExtensionClasses=support.StaticStringExtension
\ No newline at end of file
diff --git a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
new file mode 100644
index 00000000..e24e0cf3
--- /dev/null
+++ b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.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.k.groovy
+
+
+import org.apache.camel.k.jvm.RoutesLoaders
+import org.apache.camel.k.jvm.RuntimeRegistry
+import org.apache.camel.model.ToDefinition
+import spock.lang.Specification
+
+class LoaderTest extends Specification {
+
+    def "load route from classpath"() {
+        given:
+            def resource = "classpath:routes.groovy"
+
+        when:
+            def loader = RoutesLoaders.loaderFor(resource, null);
+            def builder = loader.load(new RuntimeRegistry(), resource);
+
+        then:
+            loader instanceof GroovyRoutesLoader
+            builder != null
+
+            builder.configure()
+
+            def routes = builder.routeCollection.routes
+
+            routes.size() == 1
+            routes[0].inputs[0].endpointUri == 'timer:tick'
+            routes[0].outputs[0] instanceof ToDefinition
+    }
+}
diff --git a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/IntegrationTest.groovy b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/IntegrationTest.groovy
new file mode 100644
index 00000000..a3ce2cef
--- /dev/null
+++ b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/IntegrationTest.groovy
@@ -0,0 +1,127 @@
+/**
+ * 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.k.groovy.dsl
+
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.component.seda.SedaComponent
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.impl.DefaultExchange
+import org.apache.camel.k.jvm.Runtime
+import org.apache.camel.main.MainListenerSupport
+import org.apache.camel.main.MainSupport
+import spock.lang.Specification
+
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.AtomicReference
+
+class IntegrationTest extends Specification {
+    def "load integration with rest"()  {
+        when:
+        def runtime = new Runtime()
+        runtime.setDuration(5)
+        runtime.load('classpath:routes-with-rest.groovy', null)
+        runtime.addMainListener(new MainListenerSupport() {
+            @Override
+            void afterStart(MainSupport main) {
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        then:
+        runtime.camelContext.restConfiguration.host == 'my-host'
+        runtime.camelContext.restConfiguration.port == 9192
+        runtime.camelContext.getRestConfiguration('undertow', false).host == 'my-undertow-host'
+        runtime.camelContext.getRestConfiguration('undertow', false).port == 9193
+    }
+
+    def "load integration with bindings"()  {
+        when:
+        def runtime = new Runtime()
+        runtime.setDuration(5)
+        runtime.load('classpath:routes-with-bindings.groovy', null)
+        runtime.addMainListener(new MainListenerSupport() {
+            @Override
+            void afterStart(MainSupport main) {
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        then:
+        runtime.camelContext.registry.lookup('myEntry1') == 'myRegistryEntry1'
+        runtime.camelContext.registry.lookup('myEntry2') == 'myRegistryEntry2'
+    }
+
+    def "load integration with component configuration"()  {
+        given:
+        def size = new AtomicInteger()
+        def consumers = new AtomicInteger()
+        def format = new AtomicReference()
+
+        when:
+        def runtime = new Runtime()
+        runtime.setDuration(5)
+        runtime.load('classpath:routes-with-component-configuration.groovy', null)
+        runtime.addMainListener(new MainListenerSupport() {
+            @Override
+            void afterStart(MainSupport main) {
+                def seda = runtime.camelContext.getComponent('seda', SedaComponent)
+                def log = runtime.camelContext.getComponent('log', LogComponent)
+
+                assert seda != null
+                assert log != null
+
+                size = seda.queueSize
+                consumers = seda.concurrentConsumers
+                format = log.exchangeFormatter
+
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        then:
+        size == 1234
+        consumers == 12
+        format != null
+    }
+
+
+
+    def "xyz"()  {
+        given:
+        def ctx = new DefaultCamelContext()
+
+        def log = new LogComponent()
+        log.formatter {
+            "body: " + in.body
+        }
+
+        def ex = new DefaultExchange(ctx)
+        ex.in.body = 'hello'
+
+        when:
+        def result = log.exchangeFormatter.format(ex)
+
+        then:
+        result == 'body: hello'
+    }
+}
diff --git a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/extension/LogExtensionTest.groovy b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/extension/LogExtensionTest.groovy
new file mode 100644
index 00000000..e53433a2
--- /dev/null
+++ b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/dsl/extension/LogExtensionTest.groovy
@@ -0,0 +1,43 @@
+/**
+ * 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.k.groovy.dsl.extension
+
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.impl.DefaultExchange
+import spock.lang.Specification
+
+class LogExtensionTest extends Specification {
+
+    def "invoke extension method - formatter"()  {
+        given:
+        def ctx = new DefaultCamelContext()
+
+        when:
+        def log = new LogComponent()
+        log.formatter {
+            "body: " + in.body
+        }
+
+        def ex = new DefaultExchange(ctx)
+        ex.in.body = 'hello'
+        def result = log.exchangeFormatter.format(ex)
+
+        then:
+        result == 'body: hello'
+    }
+}
diff --git a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/helper/Runner.groovy b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/helper/Runner.groovy
new file mode 100644
index 00000000..8376c296
--- /dev/null
+++ b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/helper/Runner.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.
+ */
+package org.apache.camel.k.groovy.helper
+
+import org.apache.camel.k.jvm.Runtime
+
+class Runner {
+    static void main(args) {
+        def runtime = new Runtime()
+        runtime.setDuration(5)
+        runtime.load('classpath:routes-with-component-configuration.groovy', null)
+        runtime.run()
+    }
+}
diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java
deleted file mode 100644
index 2589039e..00000000
--- a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * 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.k.groovy;
-
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.k.jvm.Runtime;
-import org.apache.camel.main.MainListenerSupport;
-import org.apache.camel.main.MainSupport;
-import org.junit.Test;
-
-import static org.assertj.core.api.Java6Assertions.assertThat;
-
-public class ComponentConfigurationTest {
-    @Test
-    public void testLoadRouteWithComponentConfiguration() throws Exception {
-        Runtime runtime = new Runtime();
-        runtime.setDuration(5);
-        runtime.load("classpath:routes-with-component-configuration.groovy", null);
-        runtime.addMainListener(new MainListenerSupport() {
-            @Override
-            public void afterStart(MainSupport main) {
-                try {
-                    CamelContext context = main.getCamelContexts().get(0);
-                    Component component = context.getComponent("seda");
-
-                    assertThat(component).isNotNull();
-                    assertThat(component).hasFieldOrPropertyWithValue("queueSize", 1234);
-
-                    main.stop();
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        runtime.run();
-    }
-}
diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java
deleted file mode 100644
index 09d93416..00000000
--- a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * 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.k.groovy;
-
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.k.jvm.Runtime;
-import org.apache.camel.main.MainListenerSupport;
-import org.apache.camel.main.MainSupport;
-import org.junit.Test;
-
-import static org.assertj.core.api.Java6Assertions.assertThat;
-
-public class RestTest {
-    @Test
-    public void testLoadRouteWithRest() throws Exception {
-        Runtime runtime = new Runtime();
-        runtime.setDuration(5);
-        runtime.load("classpath:routes-with-rest.groovy", null);
-        runtime.addMainListener(new MainListenerSupport() {
-            @Override
-            public void afterStart(MainSupport main) {
-                try {
-                    CamelContext context = main.getCamelContexts().get(0);
-
-                    assertThat(context.getRestConfiguration()).hasFieldOrPropertyWithValue("host", "my-host");
-                    assertThat(context.getRestConfiguration()).hasFieldOrPropertyWithValue("port", 9192);
-                    assertThat(context.getRestConfiguration("undertow", false)).hasFieldOrPropertyWithValue("host", "my-undertow-host");
-                    assertThat(context.getRestConfiguration("undertow", false)).hasFieldOrPropertyWithValue("port", 9193);
-
-                    main.stop();
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        runtime.run();
-    }
-}
diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java
deleted file mode 100644
index 90933838..00000000
--- a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * 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.k.groovy;
-
-import java.util.List;
-
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.k.jvm.RoutesLoader;
-import org.apache.camel.k.jvm.RoutesLoaders;
-import org.apache.camel.k.jvm.RuntimeRegistry;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.ToDefinition;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class RoutesLoaderTest {
-    @Test
-    public void testLoadGroovy() throws Exception {
-        String resource = "classpath:routes.groovy";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new RuntimeRegistry(), resource);
-
-        assertThat(loader).isInstanceOf(GroovyRoutesLoader.class);
-        assertThat(builder).isNotNull();
-
-        builder.configure();
-
-        List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
-        assertThat(routes).hasSize(1);
-        assertThat(routes.get(0).getInputs().get(0).getEndpointUri()).isEqualTo("timer:tick");
-        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
-    }
-}
diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java
deleted file mode 100644
index f9d50f50..00000000
--- a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * 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.k.groovy;
-
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.k.jvm.Runtime;
-import org.apache.camel.main.MainListenerSupport;
-import org.apache.camel.main.MainSupport;
-import org.apache.camel.spi.Registry;
-import org.junit.Test;
-
-import static org.assertj.core.api.Java6Assertions.assertThat;
-
-public class RuntimeRegistryTest {
-    @Test
-    public void testLoadRouteWithBindings() throws Exception {
-        Runtime runtime = new Runtime();
-        runtime.setDuration(5);
-        runtime.load("classpath:routes-with-bindings.groovy", null);
-        runtime.addMainListener(new MainListenerSupport() {
-            @Override
-            public void afterStart(MainSupport main) {
-                try {
-                    CamelContext context = main.getCamelContexts().get(0);
-                    Registry registry = context.getRegistry();
-
-                    assertThat(registry.lookup("myEntry1")).isEqualTo("myRegistryEntry1");
-                    assertThat(registry.lookup("myEntry2")).isEqualTo("myRegistryEntry2");
-
-                    main.stop();
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        runtime.run();
-    }
-}
diff --git a/runtime/groovy/src/test/resources/log4j2-test.xml b/runtime/groovy/src/test/resources/log4j2-test.xml
index 092e4fff..9d4c35b8 100644
--- a/runtime/groovy/src/test/resources/log4j2-test.xml
+++ b/runtime/groovy/src/test/resources/log4j2-test.xml
@@ -9,6 +9,7 @@
     </File>
   </Appenders>
 
+
   <Loggers>
     <Root level="INFO">
       <!--<AppenderRef ref="STDOUT"/>-->
diff --git a/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy b/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy
index 31ff8b96..932e9da1 100644
--- a/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy
+++ b/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy
@@ -1,7 +1,18 @@
 
 component('seda') {
+    // set value as method
     queueSize 1234
+
+    // set value as property
+    concurrentConsumers = 12
+}
+
+component('log') {
+    formatter {
+        'body ==> ' + in.body
+    }
 }
 
+
 from('timer:tick')
     .to('log:info')
\ No newline at end of file
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
index c9a70c2d..72753f77 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
@@ -58,17 +58,18 @@ public RuntimeRegistry getRegistry() {
         return registry;
     }
 
-    public CamelContext getOrCreateCamelContext() {
+    public CamelContext getCamelContext() {
         return contextMap.computeIfAbsent("camel-1", key -> {
-            DefaultCamelContext camelContext = new DefaultCamelContext();
+            DefaultCamelContext context = new DefaultCamelContext();
+            context.setName(key);
 
             CompositeRegistry registry = new CompositeRegistry();
             registry.addRegistry(this.registry);
-            registry.addRegistry(camelContext.getRegistry());
+            registry.addRegistry(context.getRegistry());
 
-            camelContext.setRegistry(registry);
+            context.setRegistry(registry);
 
-            return camelContext;
+            return context;
         });
     }
 
@@ -86,7 +87,7 @@ protected ProducerTemplate findOrCreateCamelTemplate() {
 
     @Override
     protected Map<String, CamelContext> getCamelContextMap() {
-        getOrCreateCamelContext();
+        getCamelContext();
 
         return contextMap;
     }
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java
index f8371863..8fc7589a 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java
@@ -80,16 +80,19 @@ public Object lookupByName(String name) {
             .collect(Collectors.toSet());
     }
 
+    @SuppressWarnings("deprecation")
     @Override
     public Object lookup(String name) {
         return lookupByName(name);
     }
 
+    @SuppressWarnings("deprecation")
     @Override
     public <T> T lookup(String name, Class<T> type) {
         return lookupByNameAndType(name, type);
     }
 
+    @SuppressWarnings("deprecation")
     @Override
     public <T> Map<String, T> lookupByType(Class<T> type) {
         return findByTypeWithName(type);
diff --git a/runtime/pom.xml b/runtime/pom.xml
index 3cd3c785..e0ea0c1c 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -41,9 +41,10 @@
         <assertj.version>3.11.1</assertj.version>
         <log4j2.version>2.11.1</log4j2.version>
         <slf4j.version>1.7.25</slf4j.version>
-        <groovy.version>2.5.2</groovy.version>
+        <groovy.version>2.4.15</groovy.version>
         <kotlin.version>1.2.71</kotlin.version>
         <snakeyaml.version>1.23</snakeyaml.version>
+        <spock.version>1.0-groovy-2.4</spock.version>
 
         <gmavenplus-plugin.version>1.6.1</gmavenplus-plugin.version>
         <fabric8-maven-plugin.version>3.5.40</fabric8-maven-plugin.version>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services