You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2018/10/03 10:45:57 UTC

[camel-k] branch master updated: runtime: improve kotlin dsl

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/master by this push:
     new 2fe4d27  runtime: improve kotlin dsl
2fe4d27 is described below

commit 2fe4d278fb133d2f98cb549aab61add5adb22c45
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Wed Oct 3 00:27:09 2018 +0200

    runtime: improve kotlin dsl
---
 runtime/kotlin/pom.xml                             | 28 ++++++-
 .../apache/camel/k/kotlin/KotlinRoutesLoader.java  | 80 --------------------
 .../apache/camel/k/kotlin/KotlinRoutesLoader.kt    | 85 +++++++++++++++++++++
 .../camel/k/kotlin/dsl/ComponentsConfiguration.kt  | 43 +++++++++++
 .../camel/k/kotlin/dsl/ContextConfiguration.kt     | 35 +++++++++
 .../camel/k/kotlin/dsl/RegistryConfiguration.kt    | 25 ++++++
 .../k/kotlin/extension/LogComponentExtensions.kt   | 24 ++++++
 .../apache/camel/k/kotlin/RoutesLoadersTest.java   | 51 -------------
 .../apache/camel/k/kotlin/RuntimeRegistryTest.java | 51 -------------
 .../kotlin/org/apache/camel/k/kotlin/LoaderTest.kt | 46 +++++++++++
 .../apache/camel/k/kotlin/dsl/IntegrationTest.kt   | 88 ++++++++++++++++++++++
 .../camel/k/kotlin/extension/LogExtensionTest.kt   | 25 ++++++
 runtime/kotlin/src/test/resources/log4j2-test.xml  | 19 +++++
 .../src/test/resources/routes-with-bindings.kts    |  7 +-
 .../routes-with-component-configuration.kts        | 28 +++++++
 .../kotlin/src/test/resources/routes-with-rest.kts | 17 +++++
 runtime/pom.xml                                    |  1 +
 17 files changed, 467 insertions(+), 186 deletions(-)

diff --git a/runtime/kotlin/pom.xml b/runtime/kotlin/pom.xml
index 0fa91dd..9f42363 100644
--- a/runtime/kotlin/pom.xml
+++ b/runtime/kotlin/pom.xml
@@ -58,9 +58,9 @@
         <!-- ****************************** -->
 
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>${junit.version}</version>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>${junit-juniper.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -71,4 +71,26 @@
         </dependency>
     </dependencies>
 
+    <build>
+        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
+        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <artifactId>kotlin-maven-plugin</artifactId>
+                <groupId>org.jetbrains.kotlin</groupId>
+                <version>${kotlin.version}</version>
+                <executions>
+                    <execution>
+                        <id>compile</id>
+                        <goals> <goal>compile</goal> </goals>
+                    </execution>
+                    <execution>
+                        <id>test-compile</id>
+                        <goals> <goal>test-compile</goal> </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
 </project>
diff --git a/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java b/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java
deleted file mode 100644
index 3759371..0000000
--- a/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java
+++ /dev/null
@@ -1,80 +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.kotlin;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Collections;
-import java.util.List;
-import javax.script.Bindings;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.SimpleBindings;
-
-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.k.jvm.Language;
-import org.apache.camel.k.jvm.RoutesLoader;
-import org.apache.camel.util.ResourceHelper;
-
-public class KotlinRoutesLoader implements RoutesLoader {
-
-    @Override
-    public List<Language> getSupportedLanguages() {
-        return Collections.singletonList(Language.Kotlin);
-    }
-
-    @Override
-    public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                final CamelContext context = getContext();
-                final ScriptEngineManager manager = new ScriptEngineManager();
-                final ScriptEngine engine = manager.getEngineByExtension("kts");
-                final Bindings bindings = new SimpleBindings();
-
-                // Exposed to the underlying script, but maybe better to have
-                // a nice dsl
-                bindings.put("builder", this);
-                bindings.put("registry", registry);
-                bindings.put("context", context);
-                bindings.put("components", new Components(context));
-
-                try (InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(context, resource)) {
-                    StringBuilder builder = new StringBuilder();
-
-                    // extract global objects from 'bindings'
-                    builder.append("val builder = bindings[\"builder\"] as org.apache.camel.builder.RouteBuilder").append('\n');
-                    builder.append("val context = bindings[\"context\"] as org.apache.camel.CamelContext").append('\n');
-                    builder.append("val components = bindings[\"components\"] as org.apache.camel.k.jvm.dsl.Components").append('\n');
-                    builder.append("val registry = bindings[\"registry\"] as org.apache.camel.k.jvm.RuntimeRegistry").append('\n');
-
-                    // create aliases for common functions
-                    builder.append("fun from(uri: String): org.apache.camel.model.RouteDefinition = builder.from(uri)").append('\n');
-                    builder.append("fun rest(): org.apache.camel.model.rest.RestDefinition = builder.rest()").append('\n');
-                    builder.append("fun restConfiguration(): org.apache.camel.model.rest.RestConfigurationDefinition = builder.restConfiguration()").append('\n');
-
-                    engine.eval(builder.toString(), bindings);
-                    engine.eval(new InputStreamReader(is), bindings);
-                }
-            }
-        };
-    }
-}
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
new file mode 100644
index 0000000..804664b
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
@@ -0,0 +1,85 @@
+/**
+ * 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.kotlin
+
+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.util.ResourceHelper
+import java.io.InputStreamReader
+import javax.script.ScriptEngineManager
+import javax.script.SimpleBindings
+
+class KotlinRoutesLoader : RoutesLoader {
+
+    override fun getSupportedLanguages(): List<Language> {
+        return listOf(Language.Kotlin)
+    }
+
+    @Throws(Exception::class)
+    override fun load(registry: RuntimeRegistry, resource: String): RouteBuilder {
+        return object : RouteBuilder() {
+            @Throws(Exception::class)
+            override fun configure() {
+                val context = context
+                val manager = ScriptEngineManager()
+                val engine = manager.getEngineByExtension("kts")
+                val bindings = SimpleBindings()
+
+                bindings["builder"] = this
+                bindings["registry"] = registry
+                bindings["context"] = context
+
+                ResourceHelper.resolveMandatoryResourceAsInputStream(context, resource).use { `is` ->
+                    val pre = """
+                        val builder = bindings["builder"] as org.apache.camel.builder.RouteBuilder
+
+                        fun rest(block: org.apache.camel.model.rest.RestDefinition.() -> Unit) {
+                            val delegate = builder.rest()
+                            delegate.block()
+                        }
+
+                        fun restConfiguration(block: org.apache.camel.model.rest.RestConfigurationDefinition.() -> Unit) {
+                            val delegate = builder.restConfiguration()
+                            delegate.block()
+                        }
+
+                        fun restConfiguration(component: String, block: org.apache.camel.model.rest.RestConfigurationDefinition.() -> Unit) {
+                            val delegate = builder.restConfiguration(component)
+                            delegate.block()
+                        }
+
+                        fun context(block: org.apache.camel.k.kotlin.dsl.ContextConfiguration.() -> Unit) {
+                            val delegate = org.apache.camel.k.kotlin.dsl.ContextConfiguration(
+                                context  = bindings["context"] as org.apache.camel.CamelContext,
+                                registry = bindings["registry"] as org.apache.camel.k.jvm.RuntimeRegistry
+                            )
+
+                            delegate.block()
+                        }
+
+                        fun from(uri: String): org.apache.camel.model.RouteDefinition = builder.from(uri)
+                    """.trimIndent()
+
+                    engine.eval(pre, bindings)
+                    engine.eval(InputStreamReader(`is`), bindings)
+                }
+            }
+        }
+    }
+}
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ComponentsConfiguration.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ComponentsConfiguration.kt
new file mode 100644
index 0000000..97e8103
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ComponentsConfiguration.kt
@@ -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.kotlin.dsl
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Component
+
+class ComponentsConfiguration(val context: CamelContext) {
+    inline fun <reified T : Component> component(name: String, block: T.() -> Unit) : T {
+        var component = context.getComponent(name, true, false)
+
+        // 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 (component == null) {
+            component = T::class.java.newInstance()
+
+            // let's the camel context be aware of the new component
+            context.addComponent(name, component)
+        }
+
+        if (component is T) {
+            component.block()
+            return component
+        }
+
+        throw IllegalArgumentException("Type mismatch, expected: " + T::class.java + ", got: " + component.javaClass)
+    }
+}
\ No newline at end of file
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ContextConfiguration.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ContextConfiguration.kt
new file mode 100644
index 0000000..618d1c7
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/ContextConfiguration.kt
@@ -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.
+ */
+package org.apache.camel.k.kotlin.dsl
+
+import org.apache.camel.CamelContext
+import org.apache.camel.k.jvm.RuntimeRegistry
+
+class ContextConfiguration (val registry: RuntimeRegistry, val context: CamelContext) {
+
+    fun registry(block: RegistryConfiguration.() -> Unit): RegistryConfiguration {
+        val delegate = RegistryConfiguration(registry)
+        delegate.block()
+        return delegate
+    }
+
+    fun components(block: ComponentsConfiguration.() -> Unit): ComponentsConfiguration {
+        val delegate = ComponentsConfiguration(context)
+        delegate.block()
+        return delegate
+    }
+}
\ No newline at end of file
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/RegistryConfiguration.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/RegistryConfiguration.kt
new file mode 100644
index 0000000..f15f71a
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/RegistryConfiguration.kt
@@ -0,0 +1,25 @@
+/**
+ * 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.kotlin.dsl
+
+import org.apache.camel.k.jvm.RuntimeRegistry
+
+class RegistryConfiguration(val registry: RuntimeRegistry) {
+    fun bind(name: String, value: Any) {
+        registry.bind(name, value)
+    }
+}
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/extension/LogComponentExtensions.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/extension/LogComponentExtensions.kt
new file mode 100644
index 0000000..7d948c4
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/extension/LogComponentExtensions.kt
@@ -0,0 +1,24 @@
+/**
+ * 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.kotlin.extension
+
+import org.apache.camel.Exchange
+import org.apache.camel.component.log.LogComponent
+
+fun LogComponent.formatter(fmt : (Exchange) -> String) {
+    this.setExchangeFormatter(fmt)
+}
\ No newline at end of file
diff --git a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java
deleted file mode 100644
index ecf3c51..0000000
--- a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java
+++ /dev/null
@@ -1,51 +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.kotlin;
-
-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.ProcessDefinition;
-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 RoutesLoadersTest {
-
-    @Test
-    public void testLoadKotlin() throws Exception {
-        String resource = "classpath:routes.kts";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new RuntimeRegistry(), resource);
-
-        assertThat(loader).isInstanceOf(KotlinRoutesLoader.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(ProcessDefinition.class);
-        assertThat(routes.get(0).getOutputs().get(1)).isInstanceOf(ToDefinition.class);
-    }
-}
diff --git a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java
deleted file mode 100644
index aa826ae..0000000
--- a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java
+++ /dev/null
@@ -1,51 +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.kotlin;
-
-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.Assertions.assertThat;
-
-public class RuntimeRegistryTest {
-    @Test
-    public void testLoadRouteWithBindings() throws Exception {
-        Runtime runtime = new Runtime();
-        runtime.setDuration(5);
-        runtime.load("classpath:routes-with-bindings.kts", null);
-        runtime.addMainListener(new MainListenerSupport() {
-            @Override
-            public void afterStart(MainSupport main) {
-                try {
-                    CamelContext context = main.getCamelContexts().get(0);
-                    Object value = context.getRegistry().lookup("myEntry");
-
-                    assertThat(value).isEqualTo("myRegistryEntry");
-
-                    main.stop();
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        runtime.run();
-    }
-}
diff --git a/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
new file mode 100644
index 0000000..12cb096
--- /dev/null
+++ b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
@@ -0,0 +1,46 @@
+/**
+ * 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.kotlin
+
+import org.apache.camel.k.jvm.RoutesLoaders
+import org.apache.camel.k.jvm.RuntimeRegistry
+import org.apache.camel.model.ProcessDefinition
+import org.apache.camel.model.ToDefinition
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+class LoaderTest {
+
+    @Test
+    @Throws(Exception::class)
+    fun `load integration with bindings`() {
+        val resource = "classpath:routes.kts"
+        val loader = RoutesLoaders.loaderFor(resource, null)
+        val builder = loader.load(RuntimeRegistry(), resource)
+
+        assertThat(loader).isInstanceOf(KotlinRoutesLoader::class.java)
+        assertThat(builder).isNotNull()
+
+        builder.configure()
+
+        val routes = builder.routeCollection.routes
+        assertThat(routes).hasSize(1)
+        assertThat(routes[0].inputs[0].endpointUri).isEqualTo("timer:tick")
+        assertThat(routes[0].outputs[0]).isInstanceOf(ProcessDefinition::class.java)
+        assertThat(routes[0].outputs[1]).isInstanceOf(ToDefinition::class.java)
+    }
+}
diff --git a/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationTest.kt b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationTest.kt
new file mode 100644
index 0000000..4e56d34
--- /dev/null
+++ b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationTest.kt
@@ -0,0 +1,88 @@
+package org.apache.camel.k.kotlin.dsl
+
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.component.seda.SedaComponent
+import org.apache.camel.main.MainListenerSupport
+import org.apache.camel.main.MainSupport
+import org.apache.camel.spi.ExchangeFormatter
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.AtomicReference
+
+class IntegrationTest {
+    @Test
+    @Throws(Exception::class)
+    fun `load integration with rest`() {
+        var runtime = org.apache.camel.k.jvm.Runtime()
+        runtime.duration = 5
+        runtime.load("classpath:routes-with-rest.kts", null)
+        runtime.addMainListener(object: MainListenerSupport() {
+            override fun afterStart(main: MainSupport) {
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        assertThat(runtime.camelContext.restConfiguration.host).isEqualTo("my-host")
+        assertThat(runtime.camelContext.restConfiguration.port).isEqualTo(9192)
+        assertThat(runtime.camelContext.getRestConfiguration("undertow", false).host).isEqualTo("my-undertow-host")
+        assertThat(runtime.camelContext.getRestConfiguration("undertow", false).port).isEqualTo(9193)
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun `load integration with binding`() {
+        var runtime = org.apache.camel.k.jvm.Runtime()
+        runtime.duration = 5
+        runtime.load("classpath:routes-with-bindings.kts", null)
+        runtime.addMainListener(object: MainListenerSupport() {
+            override fun afterStart(main: MainSupport) {
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        assertThat(runtime.camelContext.registry.lookup("myEntry1")).isEqualTo("myRegistryEntry1")
+        assertThat(runtime.camelContext.registry.lookup("myEntry2")).isEqualTo("myRegistryEntry2")
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun `load integration with component configuration`() {
+        val sedaSize = AtomicInteger()
+        val sedaConsumers = AtomicInteger()
+        val mySedaSize = AtomicInteger()
+        val mySedaConsumers = AtomicInteger()
+        val format = AtomicReference<ExchangeFormatter>()
+
+        var runtime = org.apache.camel.k.jvm.Runtime()
+        runtime.duration = 5
+        runtime.load("classpath:routes-with-component-configuration.kts", null)
+        runtime.addMainListener(object : MainListenerSupport() {
+            override fun afterStart(main: MainSupport) {
+                val seda = runtime.camelContext.getComponent("seda", SedaComponent::class.java)
+                val mySeda = runtime.camelContext.getComponent("mySeda", SedaComponent::class.java)
+                val log = runtime.camelContext.getComponent("log", LogComponent::class.java)
+
+                sedaSize.set(seda!!.queueSize)
+                sedaConsumers.set(seda!!.concurrentConsumers)
+                mySedaSize.set(mySeda!!.queueSize)
+                mySedaConsumers.set(mySeda!!.concurrentConsumers)
+                format.set(log!!.exchangeFormatter)
+
+                main.stop()
+            }
+        })
+
+        runtime.run()
+
+        assertThat(sedaSize.get()).isEqualTo(1234)
+        assertThat(sedaConsumers.get()).isEqualTo(12)
+        assertThat(mySedaSize.get()).isEqualTo(4321)
+        assertThat(mySedaConsumers.get()).isEqualTo(21)
+        assertThat(format.get()).isNotNull()
+    }
+}
\ No newline at end of file
diff --git a/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/extension/LogExtensionTest.kt b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/extension/LogExtensionTest.kt
new file mode 100644
index 0000000..d3be5de
--- /dev/null
+++ b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/extension/LogExtensionTest.kt
@@ -0,0 +1,25 @@
+package org.apache.camel.k.kotlin.extension
+
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.impl.DefaultExchange
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+class LogExtensionTest {
+    @Test
+    @Throws(Exception::class)
+    fun `invoke extension method - formatter`()  {
+        val ctx = DefaultCamelContext()
+
+        var log = LogComponent()
+        log.formatter {
+            e -> "body: " + e.getIn().body
+        }
+
+        var ex = DefaultExchange(ctx)
+        ex.getIn().body = "hello"
+
+        assertThat(log.exchangeFormatter.format(ex)).isEqualTo("body: hello")
+    }
+}
\ No newline at end of file
diff --git a/runtime/kotlin/src/test/resources/log4j2-test.xml b/runtime/kotlin/src/test/resources/log4j2-test.xml
new file mode 100644
index 0000000..84eda6d
--- /dev/null
+++ b/runtime/kotlin/src/test/resources/log4j2-test.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="INFO">
+  <Appenders>
+    <Console name="STDOUT" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
+    </Console>
+    <File name="FILE" fileName="target/camel-k-runtime-kotlin-test.log">
+      <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
+    </File>
+  </Appenders>
+
+  <Loggers>
+    <Root level="INFO">
+      <!--<AppenderRef ref="STDOUT"/>-->
+      <AppenderRef ref="FILE"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/runtime/kotlin/src/test/resources/routes-with-bindings.kts b/runtime/kotlin/src/test/resources/routes-with-bindings.kts
index 368bf69..530ea98 100644
--- a/runtime/kotlin/src/test/resources/routes-with-bindings.kts
+++ b/runtime/kotlin/src/test/resources/routes-with-bindings.kts
@@ -1,5 +1,10 @@
 
-registry.bind("myEntry", "myRegistryEntry")
+context {
+    registry {
+        bind("myEntry1", "myRegistryEntry1")
+        bind("myEntry2", "myRegistryEntry2")
+    }
+}
 
 
 from("timer:tick")
diff --git a/runtime/kotlin/src/test/resources/routes-with-component-configuration.kts b/runtime/kotlin/src/test/resources/routes-with-component-configuration.kts
new file mode 100644
index 0000000..a93be0c
--- /dev/null
+++ b/runtime/kotlin/src/test/resources/routes-with-component-configuration.kts
@@ -0,0 +1,28 @@
+import org.apache.camel.Exchange
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.component.seda.SedaComponent
+
+context {
+
+    components {
+
+        component<LogComponent>("log") {
+            setExchangeFormatter {
+                e: Exchange -> "" + e.getIn().body
+            }
+        }
+
+        component<SedaComponent>("seda") {
+            queueSize = 1234
+            concurrentConsumers = 12
+        }
+
+        component<SedaComponent>("mySeda") {
+            queueSize = 4321
+            concurrentConsumers = 21
+        }
+    }
+}
+
+from("timer:tick")
+    .to("log:info")
\ No newline at end of file
diff --git a/runtime/kotlin/src/test/resources/routes-with-rest.kts b/runtime/kotlin/src/test/resources/routes-with-rest.kts
new file mode 100644
index 0000000..29a748f
--- /dev/null
+++ b/runtime/kotlin/src/test/resources/routes-with-rest.kts
@@ -0,0 +1,17 @@
+
+restConfiguration {
+    host = "my-host"
+    port = "9192"
+}
+
+restConfiguration("undertow") {
+    host = "my-undertow-host"
+    port = "9193"
+}
+
+
+from("timer:tick")
+    .process().message {
+        m -> m.headers["MyHeader"] = "MyHeaderValue"
+    }
+    .to("log:info")
diff --git a/runtime/pom.xml b/runtime/pom.xml
index 56eb2b7..b76b2bb 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -35,6 +35,7 @@
 
         <camel.version>2.22.1</camel.version>
         <junit.version>4.12</junit.version>
+        <junit-juniper.version>5.3.1</junit-juniper.version>
         <joor.version>0.9.9</joor.version>
         <commons-io.version>2.6</commons-io.version>
         <commons-lang.version>3.8.1</commons-lang.version>