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/26 08:38:08 UTC

[camel-k] 01/03: runtime(kotlin) : switch to kotlin 1.3 scripting

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

commit ddeca452aa6045178f116da04f4d65e2f7db5147
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Tue Oct 9 23:37:16 2018 +0200

    runtime(kotlin) : switch to kotlin 1.3 scripting
---
 runtime/examples/kotlin-routes.kts                 |  4 +-
 runtime/kotlin/pom.xml                             | 33 +++++++-
 .../apache/camel/k/kotlin/KotlinRoutesLoader.kt    | 90 +++++++++++++---------
 .../camel/k/kotlin/dsl/IntegrationConfiguration.kt | 54 +++++++++++++
 .../kotlin/org/apache/camel/k/kotlin/LoaderTest.kt |  1 -
 .../apache/camel/k/kotlin/dsl/IntegrationTest.kt   | 13 ++--
 .../camel/k/kotlin/extension/LogExtensionTest.kt   |  1 -
 runtime/kotlin/src/test/resources/log4j2-test.xml  |  8 +-
 runtime/kotlin/src/test/resources/routes-new.kts   |  2 +
 runtime/pom.xml                                    | 30 +++++++-
 10 files changed, 175 insertions(+), 61 deletions(-)

diff --git a/runtime/examples/kotlin-routes.kts b/runtime/examples/kotlin-routes.kts
index 8c49d44..8b15930 100644
--- a/runtime/examples/kotlin-routes.kts
+++ b/runtime/examples/kotlin-routes.kts
@@ -15,6 +15,6 @@ from("timer:kotlin?period=1s")
     .setBody()
         .constant("Hello Camel K!")
     .process().message {
-        m -> m.headers["RandomValue"] = rnd.nextInt()
+        it.headers["RandomValue"] = rnd.nextInt()
     }
-    .to("log:info?showHeaders=true")
\ No newline at end of file
+    .to("log:info?showAll=true&multiline=true")
\ No newline at end of file
diff --git a/runtime/kotlin/pom.xml b/runtime/kotlin/pom.xml
index 9589d96..0c0f706 100644
--- a/runtime/kotlin/pom.xml
+++ b/runtime/kotlin/pom.xml
@@ -47,7 +47,12 @@
         </dependency>
         <dependency>
             <groupId>org.jetbrains.kotlin</groupId>
-            <artifactId>kotlin-compiler-embeddable</artifactId>
+            <artifactId>kotlin-scripting-jvm</artifactId>
+            <version>${kotlin.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-scripting-jvm-host</artifactId>
             <version>${kotlin.version}</version>
         </dependency>
 
@@ -60,10 +65,17 @@
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter-api</artifactId>
-            <version>${junit-juniper.version}</version>
+            <version>${junit-jupiter.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
             <version>${assertj.version}</version>
@@ -82,14 +94,27 @@
                 <executions>
                     <execution>
                         <id>compile</id>
-                        <goals> <goal>compile</goal> </goals>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
                     </execution>
                     <execution>
                         <id>test-compile</id>
-                        <goals> <goal>test-compile</goal> </goals>
+                        <goals>
+                            <goal>test-compile</goal>
+                        </goals>
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${maven-surefire-plugin.version}</version>
+                <configuration>
+                    <useSystemClassLoader>false</useSystemClassLoader>
+                    <forkCount>0</forkCount>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
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
index 609f9c5..9551e95 100644
--- 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
@@ -20,12 +20,25 @@ 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.kotlin.dsl.IntegrationConfiguration
 import org.apache.camel.util.ResourceHelper
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import java.io.File
 import java.io.InputStreamReader
-import javax.script.ScriptEngineManager
-import javax.script.SimpleBindings
+import kotlin.script.experimental.api.*
+import kotlin.script.experimental.host.toScriptSource
+import kotlin.script.experimental.jvm.dependenciesFromClassloader
+import kotlin.script.experimental.jvm.javaHome
+import kotlin.script.experimental.jvm.jvm
+import kotlin.script.experimental.jvmhost.BasicJvmScriptEvaluator
+import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
+import kotlin.script.experimental.jvmhost.JvmScriptCompiler
 
 class KotlinRoutesLoader : RoutesLoader {
+    companion object {
+        val LOGGER : Logger = LoggerFactory.getLogger(KotlinRoutesLoader::class.java)
+    }
 
     override fun getSupportedLanguages(): List<Language> {
         return listOf(Language.Kotlin)
@@ -36,49 +49,50 @@ class KotlinRoutesLoader : RoutesLoader {
         return object : RouteBuilder() {
             @Throws(Exception::class)
             override fun configure() {
-                val context = context
-                val manager = ScriptEngineManager()
-                val engine = manager.getEngineByExtension("kts")
-                val bindings = SimpleBindings()
+                val builder = this
+                val compiler = JvmScriptCompiler()
+                val evaluator = BasicJvmScriptEvaluator()
+                val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
+                val javaHome = System.getenv("KOTLIN_JDK_HOME") ?: "/usr/lib/jvm/java"
 
-                bindings["builder"] = this
-                bindings["registry"] = registry
-                bindings["context"] = context
+                LOGGER.info("JAVA_HOME is set to {}", javaHome)
 
                 ResourceHelper.resolveMandatoryResourceAsInputStream(context, resource).use { `is` ->
-                    val pre = """
-                        val builder = bindings["builder"] as org.apache.camel.builder.RouteBuilder
-
-                        fun rest(block: org.apache.camel.k.kotlin.dsl.RestConfiguration.() -> Unit) {
-                            val delegate = org.apache.camel.k.kotlin.dsl.RestConfiguration(builder)
-                            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)
+                    val result = host.eval(
+                        InputStreamReader(`is`).readText().toScriptSource(),
+                        ScriptCompilationConfiguration {
+                            baseClass(IntegrationConfiguration::class)
+                            jvm {
+                                //
+                                // This is needed as workaround for:
+                                //     https://youtrack.jetbrains.com/issue/KT-27497
+                                //
+                                javaHome(File(javaHome))
 
-                        fun processor(fn: (org.apache.camel.Exchange) -> Unit) : org.apache.camel.Processor {
-                             return object: org.apache.camel.Processor {
-                                override fun process(exchange: org.apache.camel.Exchange) = fn(exchange)
+                                //
+                                // The Kotlin script compiler does not inherit
+                                // the classpath by default
+                                //
+                                dependenciesFromClassloader(wholeClasspath = true)
                             }
+                        },
+                        ScriptEvaluationConfiguration {
+                            //
+                            // Arguments used to initialize the script base class
+                            //
+                            constructorArgs(registry, builder)
                         }
-                        fun predicate(fn: (org.apache.camel.Exchange) -> Boolean) : org.apache.camel.Predicate {
-                            return object: org.apache.camel.Predicate {
-                                override fun matches(exchange: org.apache.camel.Exchange) : Boolean = fn(exchange)
-                            }
-                        }
-                    """.trimIndent()
+                    )
 
-                    engine.eval(pre, bindings)
-                    engine.eval(InputStreamReader(`is`), bindings)
+                    for (report in result.reports) {
+                        if (report.severity == ScriptDiagnostic.Severity.ERROR) {
+                            LOGGER.error("{}", report.message, report.exception)
+                        } else if (report.severity == ScriptDiagnostic.Severity.WARNING) {
+                            LOGGER.warn("{}", report.message, report.exception)
+                        } else {
+                            LOGGER.info("{}", report.message)
+                        }
+                    }
                 }
             }
         }
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationConfiguration.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationConfiguration.kt
new file mode 100644
index 0000000..52d20f4
--- /dev/null
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/dsl/IntegrationConfiguration.kt
@@ -0,0 +1,54 @@
+/**
+ * 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.Exchange
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.k.jvm.RuntimeRegistry
+import org.apache.camel.model.RouteDefinition
+
+abstract class IntegrationConfiguration(
+        private val registry : RuntimeRegistry,
+        private val builder : RouteBuilder) {
+
+    fun rest(block: RestConfiguration.() -> Unit) {
+        val delegate = RestConfiguration(builder)
+        delegate.block()
+    }
+
+    fun context(block: ContextConfiguration.() -> Unit) {
+        val delegate = ContextConfiguration(
+            context  = builder.context,
+            registry = registry
+        )
+
+        delegate.block()
+    }
+
+    fun from(uri: String): RouteDefinition {
+        return builder.from(uri)
+    }
+
+    fun processor(fn: (Exchange) -> Unit) : Processor {
+        return Processor { exchange -> fn(exchange) }
+    }
+    fun predicate(fn: (Exchange) -> Boolean) : Predicate {
+        return Predicate { exchange -> fn(exchange) }
+    }
+}
\ No newline at end of file
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
index 7d38bb3..da4ab18 100644
--- 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
@@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test
 class LoaderTest {
 
     @Test
-    @Throws(Exception::class)
     fun `load route from classpath`() {
         val resource = "classpath:routes.kts"
         val loader = RoutesLoaders.loaderFor(resource, null)
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
index 62f485f..734f278 100644
--- 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
@@ -13,7 +13,6 @@ 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
@@ -35,7 +34,6 @@ class IntegrationTest {
     }
 
     @Test
-    @Throws(Exception::class)
     fun `load integration with binding`() {
         var runtime = org.apache.camel.k.jvm.Runtime()
         runtime.duration = 5
@@ -48,12 +46,11 @@ class IntegrationTest {
 
         runtime.run()
 
-        assertThat(runtime.camelContext.registry.lookup("my-entry")).isEqualTo("myRegistryEntry1")
-        assertThat(runtime.camelContext.registry.lookup("my-proc")).isInstanceOf(Processor::class.java)
+        assertThat(runtime.camelContext.registry.lookupByName("my-entry")).isEqualTo("myRegistryEntry1")
+        assertThat(runtime.camelContext.registry.lookupByName("my-proc")).isInstanceOf(Processor::class.java)
     }
 
     @Test
-    @Throws(Exception::class)
     fun `load integration with component configuration`() {
         val sedaSize = AtomicInteger()
         val sedaConsumers = AtomicInteger()
@@ -71,9 +68,9 @@ class IntegrationTest {
                 val log = runtime.camelContext.getComponent("log", LogComponent::class.java)
 
                 sedaSize.set(seda!!.queueSize)
-                sedaConsumers.set(seda!!.concurrentConsumers)
+                sedaConsumers.set(seda.concurrentConsumers)
                 mySedaSize.set(mySeda!!.queueSize)
-                mySedaConsumers.set(mySeda!!.concurrentConsumers)
+                mySedaConsumers.set(mySeda.concurrentConsumers)
                 format.set(log!!.exchangeFormatter)
 
                 main.stop()
@@ -86,6 +83,6 @@ class IntegrationTest {
         assertThat(sedaConsumers.get()).isEqualTo(12)
         assertThat(mySedaSize.get()).isEqualTo(4321)
         assertThat(mySedaConsumers.get()).isEqualTo(21)
-        assertThat(format.get()).isNotNull()
+        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
index d3be5de..9d9a328 100644
--- 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
@@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test
 
 class LogExtensionTest {
     @Test
-    @Throws(Exception::class)
     fun `invoke extension method - formatter`()  {
         val ctx = DefaultCamelContext()
 
diff --git a/runtime/kotlin/src/test/resources/log4j2-test.xml b/runtime/kotlin/src/test/resources/log4j2-test.xml
index 84eda6d..a505fd9 100644
--- a/runtime/kotlin/src/test/resources/log4j2-test.xml
+++ b/runtime/kotlin/src/test/resources/log4j2-test.xml
@@ -4,15 +4,13 @@
     <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>
+    <Null name="NONE"/>
   </Appenders>
 
   <Loggers>
     <Root level="INFO">
-      <!--<AppenderRef ref="STDOUT"/>-->
-      <AppenderRef ref="FILE"/>
+      <!-- <AppenderRef ref="STDOUT"/> -->
+      <AppenderRef ref="NONE"/>
     </Root>
   </Loggers>
 
diff --git a/runtime/kotlin/src/test/resources/routes-new.kts b/runtime/kotlin/src/test/resources/routes-new.kts
new file mode 100644
index 0000000..af6ac29
--- /dev/null
+++ b/runtime/kotlin/src/test/resources/routes-new.kts
@@ -0,0 +1,2 @@
+
+println("test")
\ No newline at end of file
diff --git a/runtime/pom.xml b/runtime/pom.xml
index 2748ccd..10bc293 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -35,7 +35,7 @@
 
         <camel.version>2.22.1</camel.version>
         <junit.version>4.12</junit.version>
-        <junit-juniper.version>5.3.1</junit-juniper.version>
+        <junit-jupiter.version>5.3.1</junit-jupiter.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>
@@ -43,13 +43,14 @@
         <log4j2.version>2.11.1</log4j2.version>
         <slf4j.version>1.7.25</slf4j.version>
         <groovy.version>2.4.15</groovy.version>
-        <kotlin.version>1.2.71</kotlin.version>
+        <kotlin.version>1.3.0-rc-198</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>
         <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
+        <maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
     </properties>
 
     <dependencyManagement>
@@ -84,4 +85,29 @@
         <module>dependency-lister</module>
     </modules>
 
+    <!-- ************************** -->
+    <!-- kotlin 1.3                 -->
+    <!-- ************************** -->
+
+    <repositories>
+        <repository>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>bintray-kotlin-maven</id>
+            <name>bintray</name>
+            <url>https://dl.bintray.com/kotlin/kotlin-eap</url>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>bintray-kotlin-maven</id>
+            <name>bintray-plugins</name>
+            <url>https://dl.bintray.com/kotlin/kotlin-eap</url>
+        </pluginRepository>
+    </pluginRepositories>
+
 </project>