Skip to content

Commit

Permalink
CAMEL-20333 camel-kotlin-api: moved all internal configuration to Rou…
Browse files Browse the repository at this point in the history
…teBuilder API, added intercepts and error handling
  • Loading branch information
iMashtak committed Jan 22, 2024
1 parent f838d47 commit c32dd0c
Show file tree
Hide file tree
Showing 15 changed files with 596 additions and 48 deletions.
5 changes: 5 additions & 0 deletions bom/camel-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,11 @@
<artifactId>camel-knative-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-kotlin-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-kotlin-dsl</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ js-dsl
jsh-dsl
jta
kamelet-main
kotlin-api
kotlin-dsl
leveldb
lra
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"other": {
"kind": "other",
"name": "kotlin-api",
"title": "Kotlin API",
"description": "Camel Kotlin API",
"deprecated": false,
"firstVersion": "4.4.0",
"label": "dsl",
"supportLevel": "Experimental",
"groupId": "org.apache.camel",
"artifactId": "camel-kotlin-api",
"version": "4.4.0-SNAPSHOT"
}
}
59 changes: 58 additions & 1 deletion dsl/camel-kotlin-api/src/main/docs/kotlin-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,63 @@ route {

== Defining beans

=== Direct object binding

You can just provide instance of any type for Camel context:

[source,kotlin]
----
val map = mapOf<String, String>()
camel(ctx) {
bean("myMap", map)
}
----

Or use supplier-function:

[source,kotlin]
----
camel(ctx) {
bean("myMap") {
mapOf<String, String>()
}
}
----

Or construct bean using builder:

[source,kotlin]
----
camel(ctx) {
bean<MyClass>("myBean") {
myField = "value"
}
}
----

=== Runtime object binding

Use other way is to use declarative approach of defining beans, without referencing beans at compile-time:

[source,kotlin]
----
class Example {
lateinit var map: MutableMap<String, String>
}
camel(ctx) {
bean("map", mutableMapOf(Pair("key", "value")))
bean {
name("test")
type("org.apache.camel.kotlin.Example")
property("map", "#map")
}
}
----

When you cross-reference beans like in example (bean `test` reference `map`) be sure you declare beans in the dependency order: first dependencies, last dependents.

== Using languages, expressions and predicates

There are a number of functions that provides Camel languages like `constant` or `simple` and a number of helper functions for building predicates/expressions like `body` or `header`. All of them are in the package `org.apache.camel.kotlin`.
Expand All @@ -261,7 +318,7 @@ body().which().isInstanceOf(String::class)

== Fallback to Java API

For each block except `camel` there is `def` field which provides common Java API. It can be used if some functionality is missing. Example:
For `camel` block there is `routeBuilder` field which can help to define any Camel entity using Java API. For each other block there is `def` field present. It can be used if some functionality is missing. Example:

[source,kotlin]
----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ import org.apache.camel.model.ModelCamelContext
annotation class CamelDslMarker

fun camel(camelContext: ModelCamelContext, i: RootDsl.() -> Unit) {
RootDsl(camelContext).apply(i)
RootDsl(camelContext).apply(i).build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class RegistryBeanDsl(
val def: RegistryBeanDefinition
) {

init {
def.properties = mutableMapOf()
}

fun name(name: String) {
def.name = name
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,38 @@
*/
package org.apache.camel.kotlin

import org.apache.camel.kotlin.model.InterceptDsl
import org.apache.camel.kotlin.model.InterceptFromDsl
import org.apache.camel.kotlin.model.InterceptSendToEndpointDsl
import org.apache.camel.kotlin.model.OnExceptionDsl
import org.apache.camel.kotlin.model.rest.RestDsl
import org.apache.camel.model.ModelCamelContext
import org.apache.camel.model.RouteDefinition
import org.apache.camel.model.app.RegistryBeanDefinition
import org.apache.camel.model.rest.RestConfigurationDefinition
import org.apache.camel.model.rest.RestDefinition
import org.apache.camel.support.PropertyBindingSupport
import kotlin.reflect.KClass

@CamelDslMarker
class RootDsl(
val ctx: ModelCamelContext
) {

val routeBuilder = RouteBuilderImpl(ctx)

internal fun build() {
routeBuilder.addRoutesToCamelContext(ctx)
}

fun route(i: RouteDsl.() -> Unit) {
val def = RouteDefinition()
val def = routeBuilder.routeCollection.route()
RouteDsl(def).apply(i)
ctx.addRouteDefinition(def)
}

fun bean(bean: String, value: Any) {
ctx.registry.bind(bean, value)
}

inline fun <reified T> bean(bean: String, i: T.() -> Unit) {
val instance = ctx.injector.newInstance(T::class.java)
instance.apply(i)
Expand All @@ -57,21 +70,31 @@ class RootDsl(
}

fun restConfiguration(i: RestConfigurationDefinition.() -> Unit) {
val def = RestConfigurationDefinition()
def.apply(i)
def.asRestConfiguration(ctx, ctx.restConfiguration)
if (def.apiContextPath != null) {
val apiDef = RestDefinition.asRouteApiDefinition(ctx, ctx.restConfiguration)
ctx.addRouteDefinition(apiDef)
}
routeBuilder.restConfiguration().apply(i)
}

fun rest(rest: String? = null, i: RestDsl.() -> Unit) {
val restDef = RestDefinition()
restDef.path = rest
val restDef = routeBuilder.rest(rest)
RestDsl(restDef).apply(i)
ctx.restDefinitions.add(restDef)
val routeDef = restDef.asRouteDefinition(ctx)
ctx.addRouteDefinitions(routeDef)
}

fun onException(vararg exceptions: KClass<out Throwable>, i: OnExceptionDsl.() -> Unit) {
val def = routeBuilder.onException(*exceptions.map { it.java }.toTypedArray())
OnExceptionDsl(def).apply(i)
}

fun intercept(i: InterceptDsl.() -> Unit) {
val def = routeBuilder.intercept()
InterceptDsl(def).apply(i)
}

fun interceptFrom(i: InterceptFromDsl.() -> Unit) {
val def = routeBuilder.interceptFrom()
InterceptFromDsl(def).apply(i)
}

fun interceptSendToEndpoint(uri: String, i: InterceptSendToEndpointDsl.() -> Unit) {
val def = routeBuilder.interceptSendToEndpoint(uri)
InterceptSendToEndpointDsl(def).apply(i)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package org.apache.camel.kotlin
import org.apache.camel.ErrorHandlerFactory
import org.apache.camel.ShutdownRoute
import org.apache.camel.ShutdownRunningTask
import org.apache.camel.kotlin.model.OnExceptionDsl
import org.apache.camel.model.RouteDefinition
import org.apache.camel.spi.RoutePolicy
import kotlin.reflect.KClass
Expand All @@ -38,6 +39,12 @@ class RouteDsl(
StepsDsl(def).apply(i)
}

fun onException(vararg exceptions: KClass<out Throwable>, i: OnExceptionDsl.() -> Unit) {
val onExceptionDef = def.onException(*exceptions.map { it.java }.toTypedArray())
OnExceptionDsl(onExceptionDef).apply(i)
onExceptionDef.end()
}

fun id(id: String) {
def.routeId(id)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.kotlin.model

import org.apache.camel.Predicate
import org.apache.camel.kotlin.CamelDslMarker
import org.apache.camel.kotlin.StepsDsl
import org.apache.camel.model.InterceptDefinition

@CamelDslMarker
class InterceptDsl(
val def: InterceptDefinition
) {

fun onWhen(onWhen: Predicate) {
def.`when`(onWhen)
}

fun outputs(i: StepsDsl.() -> Unit) {
StepsDsl(def).apply(i)
}
}
Original file line number Diff line number Diff line change
@@ -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.kotlin.model

import org.apache.camel.kotlin.CamelDslMarker
import org.apache.camel.kotlin.StepsDsl
import org.apache.camel.model.InterceptFromDefinition

@CamelDslMarker
class InterceptFromDsl(
val def: InterceptFromDefinition
) {

fun uri(uri: String) {
def.uri = uri
}

fun outputs(i: StepsDsl.() -> Unit) {
StepsDsl(def).apply(i)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.kotlin.model

import org.apache.camel.Predicate
import org.apache.camel.kotlin.CamelDslMarker
import org.apache.camel.kotlin.StepsDsl
import org.apache.camel.model.InterceptSendToEndpointDefinition

@CamelDslMarker
class InterceptSendToEndpointDsl(
val def: InterceptSendToEndpointDefinition
) {

fun outputs(i: StepsDsl.() -> Unit) {
StepsDsl(def).apply(i)
}

fun onWhen(onWhen: Predicate) {
def.`when`(onWhen)
}

fun skipSendToOriginalEndpoint(skipSendToOriginalEndpoint: Boolean) {
def.skipSendToOriginalEndpoint = skipSendToOriginalEndpoint.toString()
}

fun skipSendToOriginalEndpoint(skipSendToOriginalEndpoint: String) {
def.skipSendToOriginalEndpoint = skipSendToOriginalEndpoint.toString()
}

fun afterUri(afterUri: String) {
def.afterUri(afterUri)
}
}
Loading

0 comments on commit c32dd0c

Please sign in to comment.