You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2021/03/16 21:28:43 UTC
[camel] branch master updated: dsl: add support for Kotlin
This is an automated email from the ASF dual-hosted git repository.
lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new 9315e56 dsl: add support for Kotlin
9315e56 is described below
commit 9315e561b9cdaae9250dee5fa4a88b79af7cd1ab
Author: Luca Burgazzoli <lb...@gmail.com>
AuthorDate: Tue Mar 16 15:16:41 2021 +0100
dsl: add support for Kotlin
---
bom/camel-bom/pom.xml | 5 +
dsl/camel-kotlin-dsl/pom.xml | 232 +++++++++++++++++++++
.../services/org/apache/camel/routes-loader/kts | 2 +
dsl/camel-kotlin-dsl/src/main/docs/kotlin-dsl.adoc | 13 ++
.../dsl/kotlin/KotlinCompilationConfiguration.kt | 47 +++++
.../org/apache/camel/dsl/kotlin/KotlinConstants.kt | 20 ++
.../org/apache/camel/dsl/kotlin/KotlinDSL.kt | 96 +++++++++
.../camel/dsl/kotlin/KotlinRoutesBuilderLoader.kt | 104 +++++++++
.../camel/dsl/kotlin/model/BeansConfiguration.kt | 46 ++++
.../camel/dsl/kotlin/model/CamelConfiguration.kt | 41 ++++
.../dsl/kotlin/model/ComponentsConfiguration.kt | 47 +++++
.../dsl/kotlin/model/DataFormatsConfiguration.kt | 40 ++++
.../dsl/kotlin/model/LanguagesConfiguration.kt | 40 ++++
.../dsl/kotlin/model/RegistryConfiguration.kt | 26 +++
.../camel/dsl/kotlin/model/RestConfiguration.kt | 33 +++
.../dsl/kotlin/model/RestVerbConfiguration.kt | 45 ++++
...org.apache.camel.dsl.kotlin.KotlinDSL.classname | 0
.../dsl/kotlin/KotlinRoutesBuilderLoaderTest.kt | 199 ++++++++++++++++++
.../org/apache/camel/dsl/kotlin/support/MyBean.kt | 21 ++
.../src/test/resources/log4j2-test.properties | 31 +++
.../src/test/resources/routes/routes-new.kts | 17 ++
.../test/resources/routes/routes-with-beans.kts | 33 +++
.../routes-with-components-configuration-error.kts | 27 +++
.../routes-with-components-configuration.kts | 42 ++++
.../routes-with-dataformats-configuration.kts | 31 +++
.../resources/routes/routes-with-endpoint-dsl.kts | 21 ++
.../resources/routes/routes-with-error-handler.kts | 25 +++
.../routes/routes-with-languages-configuration.kts | 30 +++
.../src/test/resources/routes/routes-with-rest.kts | 45 ++++
.../src/test/resources/routes/routes.kts | 21 ++
dsl/pom.xml | 1 +
parent/pom.xml | 6 +
32 files changed, 1387 insertions(+)
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index ac519b2..11d9b30 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1144,6 +1144,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-kotlin-dsl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-kudu</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/dsl/camel-kotlin-dsl/pom.xml b/dsl/camel-kotlin-dsl/pom.xml
new file mode 100644
index 0000000..c445f48
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/pom.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>dsl</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-kotlin-dsl</artifactId>
+ <packaging>jar</packaging>
+ <name>Camel :: Kotlin DSL</name>
+ <description>Camel DSL with Kotlin</description>
+
+ <properties>
+ <firstVersion>3.9.0</firstVersion>
+ <sourcecheckExcludes>
+ **/resources/**/My*.java
+ </sourcecheckExcludes>
+ <sourcecheckExcludesComma>
+ ${sourcecheckExcludes},
+ </sourcecheckExcludesComma>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-endpointdsl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-script-util</artifactId>
+ <version>${kotlin-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <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>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-main</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-direct</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-rest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-languages</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-bean</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-log</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-telegram</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-seda</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-jcl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>${kotlin-version}</version>
+ <configuration>
+ <jvmTarget>${jdk.version}</jvmTarget>
+ </configuration>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <jvmTarget>${jdk.version}</jvmTarget>
+ <sourceDirs>
+ <sourceDir>src/main/kotlin</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <goals>
+ <goal>test-compile</goal>
+ </goals>
+ <configuration>
+ <jvmTarget>${jdk.version}</jvmTarget>
+ <sourceDirs>
+ <sourceDir>src/test/kotlin</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <!-- Replacing default-compile as it is treated specially by maven -->
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <!-- Replacing default-testCompile as it is treated specially by maven -->
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>java-compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>java-test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/kts b/dsl/camel-kotlin-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/kts
new file mode 100644
index 0000000..fa0fdbc
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/kts
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.dsl.kotlin.KotlinRoutesBuilderLoader
diff --git a/dsl/camel-kotlin-dsl/src/main/docs/kotlin-dsl.adoc b/dsl/camel-kotlin-dsl/src/main/docs/kotlin-dsl.adoc
new file mode 100644
index 0000000..166f545
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/docs/kotlin-dsl.adoc
@@ -0,0 +1,13 @@
+[[kotlin-dsl-other]]
+= Kotlin DSL
+:docTitle: Kotlin Dsl
+:artifactId: camel-kotlin-dsl
+:description: Camel DSL with Kotlin
+:supportLevel: Experimental
+:since: 3.
+:supportLevel: Preview
+include::{cq-version}@camel-quarkus:ROOT:partial$reference/others/kotlin-dsl.adoc[opts=optional]
+//Manually maintained attributes
+:group: DSL
+
+See https://camel.apache.org/manual/latest/dsl.html
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinCompilationConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinCompilationConfiguration.kt
new file mode 100644
index 0000000..805cd18
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinCompilationConfiguration.kt
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin
+
+import kotlin.script.experimental.api.*
+import kotlin.script.experimental.jvm.dependenciesFromClassloader
+import kotlin.script.experimental.jvm.jvm
+
+class KotlinCompilationConfiguration : ScriptCompilationConfiguration(
+{
+ defaultImports(
+ "org.apache.camel",
+ "org.apache.camel.spi"
+ )
+
+ jvm {
+ //
+ // The Kotlin script compiler does not inherit
+ // the classpath by default.
+ //
+ dependenciesFromClassloader(wholeClasspath = true)
+
+ //
+ // Scripts have to be compiled with the same
+ // jvm target level as the loader.
+ //
+ compilerOptions.append("-jvm-target")
+ compilerOptions.append(JVM_TARGET)
+ }
+ ide {
+ acceptedLocations(ScriptAcceptedLocation.Everywhere)
+ }
+})
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinConstants.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinConstants.kt
new file mode 100644
index 0000000..5c4050f
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinConstants.kt
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin
+
+const val EXTENSION = "kts"
+const val JVM_TARGET = "1.8"
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinDSL.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinDSL.kt
new file mode 100644
index 0000000..0054999
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinDSL.kt
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin
+
+import org.apache.camel.Exchange
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.builder.BuilderSupport
+import org.apache.camel.builder.EndpointConsumerBuilder
+import org.apache.camel.builder.ErrorHandlerBuilder
+import org.apache.camel.builder.endpoint.EndpointBuilderFactory
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder
+import org.apache.camel.dsl.kotlin.model.BeansConfiguration
+import org.apache.camel.dsl.kotlin.model.CamelConfiguration
+import org.apache.camel.dsl.kotlin.model.RestConfiguration
+import org.apache.camel.model.*
+import org.apache.camel.model.rest.RestDefinition
+import kotlin.script.experimental.annotations.KotlinScript
+
+@KotlinScript(fileExtension = EXTENSION, compilationConfiguration = KotlinCompilationConfiguration::class)
+abstract class KotlinDSL(
+ private val builder : EndpointRouteBuilder) : BuilderSupport(builder.context), EndpointBuilderFactory {
+
+ fun rest(): RestDefinition {
+ return builder.rest()
+ }
+
+ fun rest(block: RestConfiguration.() -> Unit) {
+ RestConfiguration(builder).block()
+ }
+
+ fun beans(block: BeansConfiguration.() -> Unit) {
+ BeansConfiguration(context).block()
+ }
+
+ fun camel(block: CamelConfiguration.() -> Unit) {
+ CamelConfiguration(context).block()
+ }
+
+ fun from(uri: String): RouteDefinition {
+ return builder.from(uri)
+ }
+
+ fun from(endpoint: EndpointConsumerBuilder): RouteDefinition {
+ return builder.from(endpoint)
+ }
+
+ fun intercept() : InterceptDefinition {
+ return builder.intercept()
+ }
+
+ fun onException(exception: Class<out Throwable>) : OnExceptionDefinition {
+ return builder.onException(exception)
+ }
+
+ fun onCompletion() : OnCompletionDefinition {
+ return builder.onCompletion()
+ }
+
+ fun interceptFrom() : InterceptFromDefinition {
+ return builder.interceptFrom()
+ }
+
+ fun interceptFrom(uri: String) : InterceptFromDefinition{
+ return builder.interceptFrom(uri)
+ }
+
+ fun interceptSendToEndpoint(uri: String) : InterceptSendToEndpointDefinition {
+ return builder.interceptSendToEndpoint(uri)
+ }
+
+ fun errorHandler(handler: ErrorHandlerBuilder) {
+ builder.errorHandler(handler)
+ }
+
+ 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/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoader.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoader.kt
new file mode 100644
index 0000000..e916b18
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoader.kt
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin
+
+import org.apache.camel.Experimental
+import org.apache.camel.ExtendedCamelContext
+import org.apache.camel.RoutesBuilder
+import org.apache.camel.RuntimeCamelException
+import org.apache.camel.api.management.ManagedAttribute
+import org.apache.camel.api.management.ManagedResource
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder
+import org.apache.camel.spi.Resource
+import org.apache.camel.spi.StartupStepRecorder
+import org.apache.camel.spi.annotations.RoutesLoader
+import org.apache.camel.support.RoutesBuilderLoaderSupport
+import org.slf4j.LoggerFactory
+import java.io.Reader
+import java.lang.Exception
+import kotlin.script.experimental.api.*
+import kotlin.script.experimental.host.toScriptSource
+import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
+import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
+
+@Experimental
+@ManagedResource(description = "Managed KotlinRoutesBuilderLoader")
+@RoutesLoader(EXTENSION)
+class KotlinRoutesBuilderLoader : RoutesBuilderLoaderSupport() {
+ var recorder: StartupStepRecorder? = null
+
+ @Throws(Exception::class)
+ override fun doBuild() {
+ super.doBuild()
+
+ if (camelContext != null) {
+ this.recorder = camelContext.adapt(ExtendedCamelContext::class.java).startupStepRecorder
+ }
+ }
+
+ @ManagedAttribute(description = "Supported file extension")
+ override fun getSupportedExtension(): String {
+ return EXTENSION
+ }
+
+ @Throws(Exception::class)
+ override fun loadRoutesBuilder(resource: Resource): RoutesBuilder? {
+ val step = if (recorder != null) recorder!!.beginStep(KotlinRoutesBuilderLoader::class.java, resource.location, "Compiling RouteBuilder") else null
+
+ try {
+ return EndpointRouteBuilder.loadEndpointRoutesBuilder(resource) {
+ reader, builder -> load(reader, builder)
+ }
+ } finally {
+ recorder?.endStep(step)
+ }
+ }
+
+ private fun load(reader: Reader, builder: EndpointRouteBuilder) {
+ val host = BasicJvmScriptingHost()
+ val config = createJvmCompilationConfigurationFromTemplate<KotlinDSL>()
+
+ val result = host.eval(
+ reader.readText().toScriptSource(),
+ config,
+ ScriptEvaluationConfiguration {
+ //
+ // Arguments used to initialize the script base class (IntegrationConfiguration)
+ //
+ constructorArgs(builder)
+ }
+ )
+
+ // ensure evaluation errors propagation
+ when(val rv = result.valueOrNull()?.returnValue) {
+ is ResultValue.Error -> throw RuntimeCamelException(rv.error)
+ }
+
+ if (result.reports.isNotEmpty()) {
+ val logger = LoggerFactory.getLogger(KotlinRoutesBuilderLoader::class.java)
+ for (report in result.reports) {
+ when (report.severity) {
+ ScriptDiagnostic.Severity.FATAL -> logger.error(report.message, report.exception)
+ ScriptDiagnostic.Severity.ERROR -> logger.error(report.message, report.exception)
+ ScriptDiagnostic.Severity.WARNING -> logger.warn(report.message, report.exception)
+ ScriptDiagnostic.Severity.INFO -> logger.info(report.message)
+ ScriptDiagnostic.Severity.DEBUG -> logger.debug(report.message)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/BeansConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/BeansConfiguration.kt
new file mode 100644
index 0000000..0edc573
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/BeansConfiguration.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.dsl.kotlin.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.Exchange
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.builder.endpoint.EndpointBuilderFactory
+
+class BeansConfiguration(
+ val context: CamelContext) : EndpointBuilderFactory {
+
+ inline fun <reified T : Any> bean(name: String, block: T.() -> Unit) {
+ val bean = context.injector.newInstance(T::class.java)
+ bean.block()
+
+ context.registry.bind(name, T::class.java, bean)
+ }
+
+ inline fun bean(name: String, crossinline function: () -> Any ) {
+ context.registry.bind(name, function())
+ }
+
+ fun processor(name: String, fn: (Exchange) -> Unit) {
+ context.registry.bind(name, Processor { exchange -> fn(exchange) } )
+ }
+
+ fun predicate(name: String, fn: (Exchange) -> Boolean) {
+ context.registry.bind(name, Predicate { exchange -> fn(exchange) } )
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/CamelConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/CamelConfiguration.kt
new file mode 100644
index 0000000..6e65fdf
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/CamelConfiguration.kt
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.CamelContext
+
+class CamelConfiguration (
+ private val context: CamelContext) {
+
+ fun components(block: ComponentsConfiguration.() -> Unit): ComponentsConfiguration {
+ val delegate = ComponentsConfiguration(context)
+ delegate.block()
+ return delegate
+ }
+
+ fun languages(block: LanguagesConfiguration.() -> Unit): LanguagesConfiguration {
+ val delegate = LanguagesConfiguration(context)
+ delegate.block()
+ return delegate
+ }
+
+ fun dataFormats(block: DataFormatsConfiguration.() -> Unit): DataFormatsConfiguration {
+ val delegate = DataFormatsConfiguration(context)
+ delegate.block()
+ return delegate
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/ComponentsConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/ComponentsConfiguration.kt
new file mode 100644
index 0000000..ad47723
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/ComponentsConfiguration.kt
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+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 target = context.getComponent(name, true, false)
+ var bind = false
+
+ if (target != null && !T::class.java.isInstance(target)) {
+ throw IllegalArgumentException("Type mismatch, expected: ${T::class.java}, got: ${target.javaClass}")
+ }
+
+ // if the component is not found, let's create a new one. This is
+ // equivalent to create a new named component, useful to create
+ // multiple instances of the same component but with different setup
+ if (target == null) {
+ target = context.injector.newInstance(T::class.java)
+ bind = true
+ }
+
+ block.invoke(target as T)
+
+ if (bind) {
+ context.registry.bind(name, T::class.java, target)
+ }
+
+ return target
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/DataFormatsConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/DataFormatsConfiguration.kt
new file mode 100644
index 0000000..a5f8d0d
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/DataFormatsConfiguration.kt
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.spi.DataFormat
+
+class DataFormatsConfiguration(val context: CamelContext) {
+ inline fun <reified T : DataFormat> dataFormat(name: String, block: T.() -> Unit) : T {
+ var target = context.registry.lookupByNameAndType(name, T::class.java)
+ var bind = false
+
+ if (target == null) {
+ target = context.injector.newInstance(T::class.java)
+ bind = true
+ }
+
+ block.invoke(target)
+
+ if (bind) {
+ context.registry.bind(name, T::class.java, target)
+ }
+
+ return target
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/LanguagesConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/LanguagesConfiguration.kt
new file mode 100644
index 0000000..b26046d
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/LanguagesConfiguration.kt
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.CamelContext
+import org.apache.camel.spi.Language
+
+class LanguagesConfiguration(val context: CamelContext) {
+ inline fun <reified T : Language> language(name: String, block: T.() -> Unit) : T {
+ var target = context.registry.lookupByNameAndType(name, T::class.java)
+ var bind = false
+
+ if (target == null) {
+ target = context.injector.newInstance(T::class.java)
+ bind = true
+ }
+
+ block.invoke(target)
+
+ if (bind) {
+ context.registry.bind(name, T::class.java, target)
+ }
+
+ return target
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RegistryConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RegistryConfiguration.kt
new file mode 100644
index 0000000..ca394de
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RegistryConfiguration.kt
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.spi.Registry
+
+
+class RegistryConfiguration(val registry: Registry) {
+ fun bind(name: String, value: Any) {
+ registry.bind(name, value)
+ }
+}
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestConfiguration.kt
new file mode 100644
index 0000000..ee734aa
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestConfiguration.kt
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.model.rest.RestConfigurationDefinition
+
+class RestConfiguration(
+ private val builder: RouteBuilder) : RestVerbConfiguration(builder, builder.rest()) {
+
+ fun configuration(block: RestConfigurationDefinition.() -> Unit) {
+ val delegate = builder.restConfiguration()
+ delegate.block()
+ }
+
+ fun path(path: String, block: RestVerbConfiguration.() -> Unit) {
+ RestVerbConfiguration(builder, path).block()
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestVerbConfiguration.kt b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestVerbConfiguration.kt
new file mode 100644
index 0000000..57d50ba
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/main/kotlin/org/apache/camel/dsl/kotlin/model/RestVerbConfiguration.kt
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.model
+
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.model.rest.RestDefinition
+
+open class RestVerbConfiguration(
+ private val builder: RouteBuilder,
+ private val definition: RestDefinition) {
+
+ constructor(builder: RouteBuilder, path: String): this(builder, builder.rest(path))
+
+ fun get(path: String, block: RestDefinition.() -> Unit) = definition.get(path).block()
+ fun get(block: RestDefinition.() -> Unit) = definition.get().block()
+
+ fun post(path: String, block: RestDefinition.() -> Unit) = definition.post(path).block()
+ fun post(block: RestDefinition.() -> Unit) = definition.post().block()
+
+ fun delete(path: String, block: RestDefinition.() -> Unit) = definition.delete(path).block()
+ fun delete(block: RestDefinition.() -> Unit) = definition.delete().block()
+
+ fun head(path: String, block: RestDefinition.() -> Unit) = definition.head(path).block()
+ fun head(block: RestDefinition.() -> Unit) = definition.head().block()
+
+ fun put(path: String, block: RestDefinition.() -> Unit) = definition.put(path).block()
+ fun put(block: RestDefinition.() -> Unit) = definition.put().block()
+
+ fun patch(path: String, block: RestDefinition.() -> Unit) = definition.patch(path).block()
+ fun patch(block: RestDefinition.() -> Unit) = definition.patch().block()
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/main/resources/META-INF/kotlin/script/templates/org.apache.camel.dsl.kotlin.KotlinDSL.classname b/dsl/camel-kotlin-dsl/src/main/resources/META-INF/kotlin/script/templates/org.apache.camel.dsl.kotlin.KotlinDSL.classname
new file mode 100644
index 0000000..e69de29
diff --git a/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoaderTest.kt b/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoaderTest.kt
new file mode 100644
index 0000000..d3b7819
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/KotlinRoutesBuilderLoaderTest.kt
@@ -0,0 +1,199 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin
+
+import org.apache.camel.Predicate
+import org.apache.camel.Processor
+import org.apache.camel.RuntimeCamelException
+import org.apache.camel.component.jackson.JacksonDataFormat
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.component.seda.SedaComponent
+import org.apache.camel.dsl.kotlin.support.MyBean
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.language.bean.BeanLanguage
+import org.apache.camel.model.ProcessDefinition
+import org.apache.camel.model.ToDefinition
+import org.apache.camel.model.rest.GetVerbDefinition
+import org.apache.camel.model.rest.PostVerbDefinition
+import org.apache.camel.processor.FatalFallbackErrorHandler
+import org.apache.camel.support.DefaultHeaderFilterStrategy
+import org.assertj.core.api.Assertions.assertThat
+import org.assertj.core.api.Assertions.assertThatExceptionOfType
+import org.junit.jupiter.api.Test
+
+class KotlinRoutesBuilderLoaderTest {
+
+ @Test
+ fun `load routes`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ val routes = ctx.routeDefinitions
+
+ assertThat(routes).hasSize(1)
+ assertThat(routes[0].input.endpointUri).isEqualTo("timer:tick")
+ assertThat(routes[0].outputs[0]).isInstanceOf(ProcessDefinition::class.java)
+ assertThat(routes[0].outputs[1]).isInstanceOf(ToDefinition::class.java)
+ }
+
+ @Test
+ fun `load routes with endpoint dsl`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-endpoint-dsl.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ val routes = ctx.routeDefinitions
+
+ assertThat(routes).hasSize(1)
+ assertThat(routes[0].input.endpointUri).isEqualTo("timer://tick?period=1s")
+ assertThat(routes[0].outputs[0]).isInstanceOfSatisfying(ToDefinition::class.java) {
+ assertThat(it.endpointUri).isEqualTo("log://info")
+ }
+ }
+
+
+ @Test
+ fun `load integration with rest`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-rest.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ assertThat(ctx.restConfiguration.host).isEqualTo("my-host")
+ assertThat(ctx.restConfiguration.port).isEqualTo(9192)
+ assertThat(ctx.restDefinitions.size).isEqualTo(2)
+
+ with(ctx.restDefinitions.find { it.path == "/my/path" }) {
+ assertThat(this?.verbs).hasSize(1)
+
+ with(this?.verbs?.get(0) as GetVerbDefinition) {
+ assertThat(uri).isEqualTo("/get")
+ assertThat(consumes).isEqualTo("application/json")
+ assertThat(produces).isEqualTo("application/json")
+ assertThat(to).hasFieldOrPropertyWithValue("endpointUri", "direct:get")
+ }
+ }
+
+ with(ctx.restDefinitions.find { it.path == "/post" }) {
+ assertThat(this?.verbs).hasSize(1)
+
+ with(this?.verbs?.get(0) as PostVerbDefinition) {
+ assertThat(uri).isNull()
+ assertThat(consumes).isEqualTo("application/json")
+ assertThat(produces).isEqualTo("application/json")
+ assertThat(to).hasFieldOrPropertyWithValue("endpointUri", "direct:post")
+ }
+ }
+ }
+
+ @Test
+ fun `load integration with beans`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-beans.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ assertThat(ctx.registry.findByType(MyBean::class.java)).hasSize(1)
+ assertThat(ctx.registry.lookupByName("myBean")).isInstanceOf(MyBean::class.java)
+ assertThat(ctx.registry.findByType(DefaultHeaderFilterStrategy::class.java)).hasSize(1)
+ assertThat(ctx.registry.lookupByName("filterStrategy")).isInstanceOf(DefaultHeaderFilterStrategy::class.java)
+ assertThat(ctx.registry.lookupByName("myProcessor")).isInstanceOf(Processor::class.java)
+ assertThat(ctx.registry.lookupByName("myPredicate")).isInstanceOf(Predicate::class.java)
+ }
+
+ @Test
+ fun `load integration with components configuration`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-components-configuration.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ val seda = ctx.getComponent("seda", SedaComponent::class.java)
+ val mySeda = ctx.getComponent("mySeda", SedaComponent::class.java)
+ val log = ctx.getComponent("log", LogComponent::class.java)
+
+ assertThat(seda.queueSize).isEqualTo(1234)
+ assertThat(seda.concurrentConsumers).isEqualTo(12)
+ assertThat(mySeda.queueSize).isEqualTo(4321)
+ assertThat(mySeda.concurrentConsumers).isEqualTo(21)
+ assertThat(log.exchangeFormatter).isNotNull
+ }
+
+ @Test
+ fun `load integration with components configuration error`() {
+ assertThatExceptionOfType(RuntimeCamelException::class.java)
+ .isThrownBy {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-components-configuration-error.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+ }
+ .withCauseInstanceOf(IllegalArgumentException::class.java)
+ .withMessageContaining("Type mismatch, expected: class org.apache.camel.component.log.LogComponent, got: class org.apache.camel.component.seda.SedaComponent");
+ }
+
+ @Test
+ fun `load integration with languages configuration`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-languages-configuration.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ val bean = ctx.resolveLanguage("bean") as BeanLanguage
+ assertThat(bean.beanType).isEqualTo(String::class.java)
+ assertThat(bean.method).isEqualTo("toUpperCase")
+
+ val mybean = ctx.resolveLanguage("my-bean") as BeanLanguage
+ assertThat(mybean.beanType).isEqualTo(String::class.java)
+ assertThat(mybean.method).isEqualTo("toLowerCase")
+ }
+
+ @Test
+ fun `load integration with dataformats configuration`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-dataformats-configuration.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+
+ val jackson = ctx.resolveDataFormat("json-jackson") as JacksonDataFormat
+ assertThat(jackson.unmarshalType).isEqualTo(Map::class.java)
+ assertThat(jackson.isPrettyPrint).isTrue()
+
+ val myjackson = ctx.resolveDataFormat("my-jackson") as JacksonDataFormat
+ assertThat(myjackson.unmarshalType).isEqualTo(String::class.java)
+ assertThat(myjackson.isPrettyPrint).isFalse()
+ }
+
+ @Test
+ fun `load integration with error handler`() {
+ val ctx = DefaultCamelContext()
+ val res = ctx.resourceLoader.resolveResource("/routes/routes-with-error-handler.kts")
+
+ ctx.routesLoader.loadRoutes(res)
+ ctx.start()
+
+ try {
+ assertThat(ctx.routes).hasSize(1)
+ assertThat(ctx.routes[0].getOnException("my-on-exception")).isInstanceOf(FatalFallbackErrorHandler::class.java)
+ } finally {
+ ctx.stop()
+ }
+ }
+}
diff --git a/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/support/MyBean.kt b/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/support/MyBean.kt
new file mode 100644
index 0000000..4748458
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/kotlin/org/apache/camel/dsl/kotlin/support/MyBean.kt
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.kotlin.support
+
+class MyBean {
+ var name: String = ""
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/log4j2-test.properties b/dsl/camel-kotlin-dsl/src/test/resources/log4j2-test.properties
new file mode 100644
index 0000000..163f7f8
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/log4j2-test.properties
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-kotlin-dsl-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
+#rootLogger.appenderRef.out.ref = out
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-new.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-new.kts
new file mode 100644
index 0000000..7f8b923
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-new.kts
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+println("test")
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-beans.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-beans.kts
new file mode 100644
index 0000000..7063f51
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-beans.kts
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+beans {
+ bean<org.apache.camel.dsl.kotlin.support.MyBean>("myBean") {
+ name = "test"
+ }
+
+ bean("filterStrategy") {
+ org.apache.camel.support.DefaultHeaderFilterStrategy()
+ }
+
+ processor("myProcessor") {
+ it.getIn().body = "Hello"
+ }
+
+ predicate("myPredicate") {
+ false
+ }
+}
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration-error.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration-error.kts
new file mode 100644
index 0000000..3c209b5
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration-error.kts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.Exchange
+
+camel {
+ components {
+ component<org.apache.camel.component.log.LogComponent>("seda") {
+ setExchangeFormatter {
+ e: Exchange -> "" + e.getIn().body
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration.kts
new file mode 100644
index 0000000..3fdf39c
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-components-configuration.kts
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.Exchange
+import org.apache.camel.component.log.LogComponent
+import org.apache.camel.component.seda.SedaComponent
+
+camel {
+ 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/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-dataformats-configuration.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-dataformats-configuration.kts
new file mode 100644
index 0000000..b5cc267
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-dataformats-configuration.kts
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.component.jackson.JacksonDataFormat
+
+camel {
+ dataFormats {
+ dataFormat<JacksonDataFormat>("json-jackson") {
+ unmarshalType = Map::class.java
+ isPrettyPrint = true
+ }
+
+ dataFormat<JacksonDataFormat>("my-jackson") {
+ unmarshalType = String::class.java
+ isPrettyPrint = false
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-endpoint-dsl.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-endpoint-dsl.kts
new file mode 100644
index 0000000..fc04af9
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-endpoint-dsl.kts
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var f = timer("tick").period("1s")
+var t = log("info")
+
+from(f)
+ .to(t)
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-error-handler.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-error-handler.kts
new file mode 100644
index 0000000..ed55f49
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-error-handler.kts
@@ -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.
+ */
+onException(IllegalArgumentException::class.java)
+ .id("my-on-exception")
+ .to("log:exception")
+
+from("timer:tick")
+ .process().message {
+ m -> m.headers["MyHeader"] = "MyHeaderValue"
+ }
+ .to("log:info")
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-languages-configuration.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-languages-configuration.kts
new file mode 100644
index 0000000..065497a
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-languages-configuration.kts
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.camel.language.bean.BeanLanguage
+
+camel {
+ languages {
+ language<BeanLanguage>("bean") {
+ beanType = String::class.java
+ method = "toUpperCase"
+ }
+ language<BeanLanguage>("my-bean") {
+ beanType = String::class.java
+ method = "toLowerCase"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-rest.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-rest.kts
new file mode 100644
index 0000000..d9dd70b
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes-with-rest.kts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+rest {
+ configuration {
+ host = "my-host"
+ port = "9192"
+ }
+
+ path("/my/path") {
+ get("/get") {
+ consumes("application/json")
+ produces("application/json")
+ to("direct:get")
+ }
+ }
+
+ post {
+ path("/post")
+ consumes("application/json")
+ produces("application/json")
+ to("direct:post")
+ }
+}
+
+
+
+from("timer:tick")
+ .process().message {
+ m -> m.headers["MyHeader"] = "MyHeaderValue"
+ }
+ .to("log:info")
diff --git a/dsl/camel-kotlin-dsl/src/test/resources/routes/routes.kts b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes.kts
new file mode 100644
index 0000000..7d28bb5
--- /dev/null
+++ b/dsl/camel-kotlin-dsl/src/test/resources/routes/routes.kts
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+from("timer:tick")
+ .process().message {
+ m -> m.headers["MyHeader"] = "MyHeaderValue"
+ }
+ .to("log:info")
\ No newline at end of file
diff --git a/dsl/pom.xml b/dsl/pom.xml
index 00e9a80..310cb36 100644
--- a/dsl/pom.xml
+++ b/dsl/pom.xml
@@ -40,6 +40,7 @@
<module>camel-xml-jaxb-dsl-test</module>
<module>camel-yaml-dsl</module>
<module>camel-js-dsl</module>
+ <module>camel-kotlin-dsl</module>
</modules>
<properties>
diff --git a/parent/pom.xml b/parent/pom.xml
index 97e2727..24aaa04 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -360,6 +360,7 @@
<jython-standalone-version>2.5.3</jython-standalone-version>
<jzlib-version>1.1.3</jzlib-version>
<kafka-version>2.7.0</kafka-version>
+ <kotlin-version>1.4.20</kotlin-version>
<kubernetes-client-version>5.1.1</kubernetes-client-version>
<kubernetes-model-version>5.1.1</kubernetes-model-version>
<kudu-version>1.14.0</kudu-version>
@@ -2708,6 +2709,11 @@
<artifactId>camel-js-dsl</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-kotlin-dsl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!-- camel catalog -->
<dependency>