diff --git a/camel-k-loader-groovy/pom.xml b/camel-k-loader-groovy/pom.xml index 75a893f55..6c58ec172 100644 --- a/camel-k-loader-groovy/pom.xml +++ b/camel-k-loader-groovy/pom.xml @@ -99,6 +99,16 @@ camel-properties test + + org.apache.camel + camel-bean + test + + + org.apache.camel + camel-jackson + test + diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/BeanConfiguration.groovy similarity index 65% rename from camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentConfiguration.groovy rename to camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/BeanConfiguration.groovy index 6d58fb2d2..5616e13cf 100644 --- a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentConfiguration.groovy +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/BeanConfiguration.groovy @@ -16,17 +16,19 @@ */ package org.apache.camel.k.loader.groovy.dsl +import groovy.util.logging.Slf4j +import org.apache.camel.CamelContext import org.apache.camel.ExtendedCamelContext import org.apache.camel.support.PropertyBindingSupport -import org.slf4j.Logger -import org.slf4j.LoggerFactory -class ComponentConfiguration { - private static final Logger LOG = LoggerFactory.getLogger(ComponentConfiguration.class); - private final org.apache.camel.Component component +@Slf4j +class BeanConfiguration { + private final CamelContext context + private final Object target - ComponentConfiguration(org.apache.camel.Component component) { - this.component = component + BeanConfiguration(CamelContext camelContext, Object target) { + this.context = camelContext + this.target = target } def methodMissing(String name, arguments) { @@ -38,13 +40,13 @@ class ComponentConfiguration { } else if (args.length == 1) { value = args[0] } else { - throw new IllegalArgumentException("Unable to set property '${name}' on component '${component.class.name}'") + throw new IllegalArgumentException("Unable to set property '${name}' on target '${target.class.name}'") } if (value instanceof Closure) { - def m = this.component.metaClass.getMetaMethod(name, Closure.class) + def m = this.target.metaClass.getMetaMethod(name, Closure.class) if (m) { - m.invoke(component, args) + m.invoke(target, args) // done return @@ -52,33 +54,34 @@ class ComponentConfiguration { } boolean bound = PropertyBindingSupport.build() - .withCamelContext(component.camelContext) - .withTarget(component) + .withCamelContext(context) + .withTarget(target) .withProperty(name, value) .bind() if (!bound) { - throw new MissingMethodException(name, this.component.class, args as Object[]) + throw new MissingMethodException(name, this.target.class, args as Object[]) } } def propertyMissing(String name, value) { boolean bound = PropertyBindingSupport.build() - .withCamelContext(component.camelContext) - .withTarget(component) + .withCamelContext(context) + .withTarget(target) .withProperty(name, value) .bind() if (!bound) { - throw new MissingPropertyException(name, this.component.class) + throw new MissingPropertyException(name, this.target.class) } } def propertyMissing(String name) { def props = new HashMap() - def context = component.getCamelContext().adapt(ExtendedCamelContext.class) - context.getBeanIntrospection().getProperties(component, props, null, false) + context.adapt(ExtendedCamelContext.class) + .getBeanIntrospection() + .getProperties(target, props, null, false) return props[name] } diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ContextConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/CamelConfiguration.groovy similarity index 73% rename from camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ContextConfiguration.groovy rename to camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/CamelConfiguration.groovy index 8cba11b6a..d7ba2264b 100644 --- a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ContextConfiguration.groovy +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/CamelConfiguration.groovy @@ -18,22 +18,28 @@ package org.apache.camel.k.loader.groovy.dsl import org.apache.camel.CamelContext -class ContextConfiguration { +class CamelConfiguration { private final CamelContext context - ContextConfiguration(CamelContext context) { + CamelConfiguration(CamelContext context) { this.context = context } - def registry(@DelegatesTo(RegistryConfiguration) Closure callable) { + def components(@DelegatesTo(ComponentsConfiguration) Closure callable) { callable.resolveStrategy = Closure.DELEGATE_FIRST - callable.delegate = new RegistryConfiguration(this.context.registry) + callable.delegate = new ComponentsConfiguration(context) callable.call() } - def components(@DelegatesTo(ComponentsConfiguration) Closure callable) { + def dataFormats(@DelegatesTo(DataFormatsConfiguration) Closure callable) { callable.resolveStrategy = Closure.DELEGATE_FIRST - callable.delegate = new ComponentsConfiguration(context) + callable.delegate = new DataFormatsConfiguration(context) + callable.call() + } + + def languages(@DelegatesTo(LanguagesConfiguration) Closure callable) { + callable.resolveStrategy = Closure.DELEGATE_FIRST + callable.delegate = new LanguagesConfiguration(context) callable.call() } } diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentsConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentsConfiguration.groovy index 4a5dff355..ed697986a 100644 --- a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentsConfiguration.groovy +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/ComponentsConfiguration.groovy @@ -16,9 +16,11 @@ */ package org.apache.camel.k.loader.groovy.dsl +import groovy.util.logging.Slf4j import org.apache.camel.CamelContext import org.apache.camel.Component +@Slf4j class ComponentsConfiguration { private final CamelContext context @@ -26,36 +28,42 @@ class ComponentsConfiguration { this.context = context } - def component(String name, @DelegatesTo(ComponentConfiguration) Closure callable) { - def component = context.getComponent(name, true, false) + def component(String name, Closure callable) { + def target = context.getComponent(name, true, false) + if (target == null) { + throw new IllegalArgumentException("Unable to find a component with name: ${name}") + } + // Just make sure the closure context is belong to component callable.resolveStrategy = Closure.DELEGATE_ONLY - callable.delegate = new ComponentConfiguration(component) + callable.delegate = new BeanConfiguration(context, target) callable.call() } - def component(String name, Class type, @DelegatesTo(ComponentConfiguration) Closure callable) { - def component = context.getComponent(name, true, false) + def component(String name, Class type, Closure callable) { + def target = context.getComponent(name, true, false) + def bind = false + + if (target != null && !type.isInstance(target)) { + throw new IllegalArgumentException("Type mismatch, expected: ${type} , got: ${target.class}") + } // if the component is not found, let's create a new one. This is // equivalent to create a new named component, useful to create // multiple instances of the same component but with different setup - if (component == null) { - component = context.injector.newInstance(type) - - // let's the camel context be aware of the new component - context.addComponent(name, component) + if (target == null) { + target = context.injector.newInstance(type) + bind = true } - if (type.isAssignableFrom(component.class)) { - // Just make sure the closure context is belong to component - callable.resolveStrategy = Closure.DELEGATE_ONLY - callable.delegate = new ComponentConfiguration(component) - callable.call() - return - } + // Just make sure the closure context is belong to component + callable.resolveStrategy = Closure.DELEGATE_ONLY + callable.delegate = new BeanConfiguration(context, target) + callable.call() - throw new IllegalArgumentException("Type mismatch, expected: " + type + ", got: " + component.class) + if (bind) { + context.registry.bind(name, type, target) + } } def methodMissing(String name, arguments) { @@ -74,7 +82,7 @@ class ComponentsConfiguration { def clos = args[1] if (type instanceof Class && Component.class.isAssignableFrom(type) && clos instanceof Closure) { - return component(name,type, clos) + return component(name, type, clos) } } } diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/DataFormatsConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/DataFormatsConfiguration.groovy new file mode 100644 index 000000000..e87f507ee --- /dev/null +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/DataFormatsConfiguration.groovy @@ -0,0 +1,92 @@ +/* + * 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.loader.groovy.dsl + +import org.apache.camel.CamelContext +import org.apache.camel.spi.DataFormat + +class DataFormatsConfiguration { + private final CamelContext context + + DataFormatsConfiguration(CamelContext context) { + this.context = context + } + + def dataFormat(String name, Closure callable) { + def target = context.resolveDataFormat(name) + if (target == null) { + throw new IllegalArgumentException("Unable to find a dataformat with name: ${name}") + } + + // Just make sure the closure context is belong to component + callable.resolveStrategy = Closure.DELEGATE_ONLY + callable.delegate = new BeanConfiguration(context, target) + callable.call() + + // let's the camel context be aware of the new dataformat + context.registry.bind(name, DataFormat.class, target) + } + + def dataFormat(String name, Class type, Closure callable) { + def target = context.registry.lookupByNameAndType(name, type) + def bind = false + + // if the dataformat is not found, let's create a new one. This is + // equivalent to create a new named dataformat, useful to create + // multiple instances of the same dataformat but with different setup + if (target == null) { + target = context.injector.newInstance(type) + + bind = true + } + + // Just make sure the closure context is belong to dataformat + callable.resolveStrategy = Closure.DELEGATE_ONLY + callable.delegate = new BeanConfiguration(context, target) + callable.call() + + if (bind) { + // let's the camel context be aware of the new dataformat + context.registry.bind(name, type, target) + } + } + + def methodMissing(String name, arguments) { + final Object[] args = arguments as Object[] + + if (args != null) { + if (args.length == 1) { + def clos = args[0] + + if (clos instanceof Closure) { + return dataFormat(name, clos) + } + } + if (args.length == 2) { + def type = args[0] + def clos = args[1] + + if (type instanceof Class && DataFormat.class.isAssignableFrom(type) && clos instanceof Closure) { + return dataFormat(name,type, clos) + } + } + } + + throw new MissingMethodException(name, this, args) + } + +} diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationConfiguration.groovy index ec4b89d85..1776ad8ff 100644 --- a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationConfiguration.groovy +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationConfiguration.groovy @@ -49,9 +49,9 @@ class IntegrationConfiguration extends BuilderSupport implements Support, Endpoi callable.call() } - def context(@DelegatesTo(ContextConfiguration) Closure callable) { + def camel(@DelegatesTo(CamelConfiguration) Closure callable) { callable.resolveStrategy = Closure.DELEGATE_FIRST - callable.delegate = new ContextConfiguration(context) + callable.delegate = new CamelConfiguration(context) callable.call() } diff --git a/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/LanguagesConfiguration.groovy b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/LanguagesConfiguration.groovy new file mode 100644 index 000000000..f694a1ea2 --- /dev/null +++ b/camel-k-loader-groovy/src/main/groovy/org/apache/camel/k/loader/groovy/dsl/LanguagesConfiguration.groovy @@ -0,0 +1,91 @@ +/* + * 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.loader.groovy.dsl + +import org.apache.camel.CamelContext +import org.apache.camel.spi.Language + +class LanguagesConfiguration { + private final CamelContext context + + LanguagesConfiguration(CamelContext context) { + this.context = context + } + + def language(String name, Closure callable) { + def target = context.resolveLanguage(name) + if (target == null) { + throw new IllegalArgumentException("Unable to find a language with name: ${name}") + } + + // Just make sure the closure context is belong to component + callable.resolveStrategy = Closure.DELEGATE_ONLY + callable.delegate = new BeanConfiguration(context, target) + callable.call() + + // let's the camel context be aware of the new dataformat + context.registry.bind(name, Language.class, target) + } + + def language(String name, Class type, Closure callable) { + def target = context.registry.lookupByNameAndType(name, type) + def bind = false + + // if the language is not found, let's create a new one. This is + // equivalent to create a new named language, useful to create + // multiple instances of the same language but with different setup + if (target == null) { + target = context.injector.newInstance(type) + + bind = true + } + + // Just make sure the closure context is belong to dataformat + callable.resolveStrategy = Closure.DELEGATE_ONLY + callable.delegate = new BeanConfiguration(context, target) + callable.call() + + if (bind) { + // let's the camel context be aware of the new dataformat + context.registry.bind(name, type, target) + } + } + + def methodMissing(String name, arguments) { + final Object[] args = arguments as Object[] + + if (args != null) { + if (args.length == 1) { + def clos = args[0] + + if (clos instanceof Closure) { + return language(name, clos) + } + } + if (args.length == 2) { + def type = args[0] + def clos = args[1] + + if (type instanceof Class && Language.class.isAssignableFrom(type) && clos instanceof Closure) { + return language(name,type, clos) + } + } + } + + throw new MissingMethodException(name, this, args) + } +} diff --git a/camel-k-loader-groovy/src/test/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationTest.groovy b/camel-k-loader-groovy/src/test/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationTest.groovy index 176132116..2bd60adb9 100644 --- a/camel-k-loader-groovy/src/test/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationTest.groovy +++ b/camel-k-loader-groovy/src/test/groovy/org/apache/camel/k/loader/groovy/dsl/IntegrationTest.groovy @@ -18,10 +18,12 @@ package org.apache.camel.k.loader.groovy.dsl import org.apache.camel.Predicate import org.apache.camel.Processor +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.impl.DefaultCamelContext import org.apache.camel.k.Runtime +import org.apache.camel.language.bean.BeanLanguage import org.apache.camel.model.ModelCamelContext import org.apache.camel.model.rest.GetVerbDefinition import org.apache.camel.model.rest.PostVerbDefinition @@ -108,19 +110,9 @@ class IntegrationTest extends Specification { context.registry.lookupByName('myPredicate') instanceof Predicate } - def "load integration with bindings"() { + def "load integration with components configuration"() { when: - forRoutes('classpath:routes-with-bindings.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) - - then: - context.registry.lookupByName('myEntry1') == 'myRegistryEntry1' - context.registry.lookupByName('myEntry2') == 'myRegistryEntry2' - context.registry.lookupByName('myEntry3') instanceof Processor - } - - def "load integration with component configuration"() { - when: - forRoutes('classpath:routes-with-component-configuration.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) + forRoutes('classpath:routes-with-components-configuration.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) then: with(context.getComponent('seda', SedaComponent)) { @@ -136,6 +128,36 @@ class IntegrationTest extends Specification { } } + def "load integration with languages configuration"() { + when: + forRoutes('classpath:routes-with-languages-configuration.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) + + then: + with(context.resolveLanguage('bean'), BeanLanguage) { + beanType == String.class + method == "toUpperCase" + } + with(context.resolveLanguage('myBean'), BeanLanguage) { + beanType == String.class + method == "toLowerCase" + } + } + + def "load integration with dataformats configuration"() { + when: + forRoutes('classpath:routes-with-dataformats-configuration.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) + + then: + with(context.resolveDataFormat('json-jackson'), JacksonDataFormat) { + unmarshalType == Map.class + prettyPrint == true + } + with(context.resolveDataFormat('my-jackson'), JacksonDataFormat) { + unmarshalType == String.class + prettyPrint == false + } + } + def "load integration with component error property configuration"() { when: forRoutes('classpath:routes-with-component-wrong-property-configuration.groovy').accept(Runtime.Phase.ConfigureRoutes, runtime) diff --git a/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-method-configuration.groovy b/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-method-configuration.groovy index f2b4fb63c..0496fe62e 100644 --- a/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-method-configuration.groovy +++ b/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-method-configuration.groovy @@ -16,7 +16,7 @@ */ import org.apache.camel.component.seda.SedaComponent -context { +camel { components { mySeda(SedaComponent) { // a wrong method name diff --git a/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-property-configuration.groovy b/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-property-configuration.groovy index 07a742215..e34832c4e 100644 --- a/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-property-configuration.groovy +++ b/camel-k-loader-groovy/src/test/resources/routes-with-component-wrong-property-configuration.groovy @@ -15,7 +15,7 @@ * limitations under the License. */ -context { +camel { components { seda { // a wrong property name diff --git a/camel-k-loader-groovy/src/test/resources/routes-with-component-configuration.groovy b/camel-k-loader-groovy/src/test/resources/routes-with-components-configuration.groovy similarity index 97% rename from camel-k-loader-groovy/src/test/resources/routes-with-component-configuration.groovy rename to camel-k-loader-groovy/src/test/resources/routes-with-components-configuration.groovy index abc4b0426..b7ef80d99 100644 --- a/camel-k-loader-groovy/src/test/resources/routes-with-component-configuration.groovy +++ b/camel-k-loader-groovy/src/test/resources/routes-with-components-configuration.groovy @@ -16,7 +16,7 @@ */ import org.apache.camel.component.seda.SedaComponent -context { +camel { components { seda { // set value as method @@ -28,7 +28,7 @@ context { mySeda(SedaComponent) { // set value as method - queueSize 4321 + queueSize = 4321 // set value as property concurrentConsumers = 21 diff --git a/camel-k-loader-groovy/src/test/resources/routes-with-dataformats-configuration.groovy b/camel-k-loader-groovy/src/test/resources/routes-with-dataformats-configuration.groovy new file mode 100644 index 000000000..68b55bfb1 --- /dev/null +++ b/camel-k-loader-groovy/src/test/resources/routes-with-dataformats-configuration.groovy @@ -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. + */ + +import org.apache.camel.component.jackson.JacksonDataFormat + +camel { + dataFormats { + dataFormat("json-jackson") { + unmarshalType = Map.class + prettyPrint = true + } + dataFormat("my-jackson", JacksonDataFormat) { + unmarshalType = String.class + prettyPrint = false + } + } +} + + +from('timer:tick') + .to('log:info') \ No newline at end of file diff --git a/camel-k-loader-groovy/src/test/resources/routes-with-bindings.groovy b/camel-k-loader-groovy/src/test/resources/routes-with-languages-configuration.groovy similarity index 75% rename from camel-k-loader-groovy/src/test/resources/routes-with-bindings.groovy rename to camel-k-loader-groovy/src/test/resources/routes-with-languages-configuration.groovy index b6941f7fa..707e057bc 100644 --- a/camel-k-loader-groovy/src/test/resources/routes-with-bindings.groovy +++ b/camel-k-loader-groovy/src/test/resources/routes-with-languages-configuration.groovy @@ -14,15 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -context { - registry { - myEntry1 = 'myRegistryEntry1' - myEntry2 = 'myRegistryEntry2' - myEntry3 = processor { - it.in.headers['test'] = 'value' + +import org.apache.camel.language.bean.BeanLanguage + +camel { + + languages { + bean { + beanType = String.class + method = "toUpperCase" + } + myBean(BeanLanguage) { + beanType = String.class + method = "toLowerCase" } } } + from('timer:tick') .to('log:info') \ No newline at end of file diff --git a/camel-k-loader-kotlin/pom.xml b/camel-k-loader-kotlin/pom.xml index bc74dc69f..b5ce0159b 100644 --- a/camel-k-loader-kotlin/pom.xml +++ b/camel-k-loader-kotlin/pom.xml @@ -107,6 +107,16 @@ camel-main test + + org.apache.camel + camel-bean + test + + + org.apache.camel + camel-jackson + test + diff --git a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ContextConfiguration.kt b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/CamelConfiguration.kt similarity index 73% rename from camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ContextConfiguration.kt rename to camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/CamelConfiguration.kt index 847c94581..cd42b971f 100644 --- a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ContextConfiguration.kt +++ b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/CamelConfiguration.kt @@ -17,20 +17,24 @@ package org.apache.camel.k.loader.kotlin.dsl import org.apache.camel.CamelContext -import org.apache.camel.spi.Registry -class ContextConfiguration ( - private val context: CamelContext, - private val registry: Registry) { +class CamelConfiguration ( + private val context: CamelContext) { - fun registry(block: RegistryConfiguration.() -> Unit): RegistryConfiguration { - val delegate = RegistryConfiguration(registry) + fun components(block: ComponentsConfiguration.() -> Unit): ComponentsConfiguration { + val delegate = ComponentsConfiguration(context) delegate.block() return delegate } - fun components(block: ComponentsConfiguration.() -> Unit): ComponentsConfiguration { - val delegate = ComponentsConfiguration(context) + 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 } diff --git a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ComponentsConfiguration.kt b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ComponentsConfiguration.kt index ea007810f..282083937 100644 --- a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ComponentsConfiguration.kt +++ b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/ComponentsConfiguration.kt @@ -21,23 +21,27 @@ import org.apache.camel.Component class ComponentsConfiguration(val context: CamelContext) { inline fun component(name: String, block: T.() -> Unit) : T { - var component = context.getComponent(name, true, false) + var target = context.getComponent(name, true, false) + var bind = false + + if (target != null && target !is T) { + 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 (component == null) { - component = T::class.java.newInstance() - - // let's the camel context be aware of the new component - context.addComponent(name, component) + if (target == null) { + target = context.injector.newInstance(T::class.java) + bind = true } - if (component is T) { - component.block() - return component + block.invoke(target as T) + + if (bind) { + context.registry.bind(name, T::class.java, target) } - throw IllegalArgumentException("Type mismatch, expected: " + T::class.java + ", got: " + component.javaClass) + return target } } \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/DataFormatsConfiguration.kt b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/DataFormatsConfiguration.kt new file mode 100644 index 000000000..c0fd4df71 --- /dev/null +++ b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/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.k.loader.kotlin.dsl + +import org.apache.camel.CamelContext +import org.apache.camel.spi.DataFormat + +class DataFormatsConfiguration(val context: CamelContext) { + inline fun 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/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationConfiguration.kt b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationConfiguration.kt index da2f45c9f..a02c39444 100644 --- a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationConfiguration.kt +++ b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationConfiguration.kt @@ -43,8 +43,8 @@ abstract class IntegrationConfiguration( BeansConfiguration(context).block() } - fun context(block: ContextConfiguration.() -> Unit) { - ContextConfiguration(context, registry).block() + fun camel(block: CamelConfiguration.() -> Unit) { + CamelConfiguration(context).block() } fun from(uri: String): RouteDefinition { diff --git a/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/LanguagesConfiguration.kt b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/LanguagesConfiguration.kt new file mode 100644 index 000000000..2afc1f9ea --- /dev/null +++ b/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/dsl/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.k.loader.kotlin.dsl + +import org.apache.camel.CamelContext +import org.apache.camel.spi.Language + +class LanguagesConfiguration(val context: CamelContext) { + inline fun 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/camel-k-loader-kotlin/src/test/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationTest.kt b/camel-k-loader-kotlin/src/test/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationTest.kt index 9f1416956..66702db16 100644 --- a/camel-k-loader-kotlin/src/test/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationTest.kt +++ b/camel-k-loader-kotlin/src/test/kotlin/org/apache/camel/k/loader/kotlin/dsl/IntegrationTest.kt @@ -18,11 +18,13 @@ package org.apache.camel.k.loader.kotlin.dsl import org.apache.camel.Predicate import org.apache.camel.Processor +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.impl.DefaultCamelContext import org.apache.camel.k.Runtime import org.apache.camel.k.listener.RoutesConfigurer.forRoutes +import org.apache.camel.language.bean.BeanLanguage import org.apache.camel.model.ModelCamelContext import org.apache.camel.model.rest.GetVerbDefinition import org.apache.camel.model.rest.PostVerbDefinition @@ -85,22 +87,11 @@ class IntegrationTest { } @Test - fun `load integration with binding`() { + fun `load integration with components configuration`() { val context = DefaultCamelContext() val runtime = Runtime.of(context) - forRoutes("classpath:routes-with-bindings.kts").accept(Runtime.Phase.ConfigureRoutes, runtime) - - assertThat(context.registry.lookupByName("my-entry")).isEqualTo("myRegistryEntry1") - assertThat(context.registry.lookupByName("my-proc")).isInstanceOf(Processor::class.java) - } - - @Test - fun `load integration with component configuration`() { - val context = DefaultCamelContext() - val runtime = Runtime.of(context) - - forRoutes("classpath:routes-with-component-configuration.kts").accept(Runtime.Phase.ConfigureRoutes, runtime) + forRoutes("classpath:routes-with-components-configuration.kts").accept(Runtime.Phase.ConfigureRoutes, runtime) val seda = context.getComponent("seda", SedaComponent::class.java) val mySeda = context.getComponent("mySeda", SedaComponent::class.java) @@ -113,6 +104,38 @@ class IntegrationTest { assertThat(log.exchangeFormatter).isNotNull } + @Test + fun `load integration with languages configuration`() { + val context = DefaultCamelContext() + val runtime = Runtime.of(context) + + forRoutes("classpath:routes-with-languages-configuration.kts").accept(Runtime.Phase.ConfigureRoutes, runtime) + + val bean = context.resolveLanguage("bean") as BeanLanguage + assertThat(bean.beanType).isEqualTo(String::class.java) + assertThat(bean.method).isEqualTo("toUpperCase") + + val mybean = context.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 context = DefaultCamelContext() + val runtime = Runtime.of(context) + + forRoutes("classpath:routes-with-dataformats-configuration.kts").accept(Runtime.Phase.ConfigureRoutes, runtime) + + val jackson = context.resolveDataFormat("json-jackson") as JacksonDataFormat + assertThat(jackson.unmarshalType).isEqualTo(Map::class.java) + assertThat(jackson.isPrettyPrint).isTrue() + + val myjackson = context.resolveDataFormat("my-jackson") as JacksonDataFormat + assertThat(myjackson.unmarshalType).isEqualTo(String::class.java) + assertThat(myjackson.isPrettyPrint).isFalse() + } + @Test fun `load integration with error handler`() { val context = DefaultCamelContext() diff --git a/camel-k-loader-kotlin/src/test/resources/routes-new.kts b/camel-k-loader-kotlin/src/test/resources/routes-new.kts index af6ac2946..7f8b9237c 100644 --- a/camel-k-loader-kotlin/src/test/resources/routes-new.kts +++ b/camel-k-loader-kotlin/src/test/resources/routes-new.kts @@ -1,2 +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/camel-k-loader-kotlin/src/test/resources/routes-with-beans.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-beans.kts index 2356dc92a..52f596f08 100644 --- a/camel-k-loader-kotlin/src/test/resources/routes-with-beans.kts +++ b/camel-k-loader-kotlin/src/test/resources/routes-with-beans.kts @@ -1,3 +1,19 @@ +/* + * 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("dataSource") { driverClassName = "org.h2.Driver" diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-bindings.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-bindings.kts deleted file mode 100644 index b4feaeb2b..000000000 --- a/camel-k-loader-kotlin/src/test/resources/routes-with-bindings.kts +++ /dev/null @@ -1,16 +0,0 @@ - -context { - registry { - bind("my-entry", "myRegistryEntry1") - bind("my-proc", processor { - e -> e.getIn().body = "Hello" - }) - } -} - - -from("timer:tick") - .process().message { - m -> m.headers["MyHeader"] = "MyHeaderValue" - } - .to("log:info") \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-component-configuration.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-component-configuration.kts deleted file mode 100644 index a93be0c04..000000000 --- a/camel-k-loader-kotlin/src/test/resources/routes-with-component-configuration.kts +++ /dev/null @@ -1,28 +0,0 @@ -import org.apache.camel.Exchange -import org.apache.camel.component.log.LogComponent -import org.apache.camel.component.seda.SedaComponent - -context { - - components { - - component("log") { - setExchangeFormatter { - e: Exchange -> "" + e.getIn().body - } - } - - component("seda") { - queueSize = 1234 - concurrentConsumers = 12 - } - - component("mySeda") { - queueSize = 4321 - concurrentConsumers = 21 - } - } -} - -from("timer:tick") - .to("log:info") \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-components-configuration.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-components-configuration.kts new file mode 100644 index 000000000..3fdf39c15 --- /dev/null +++ b/camel-k-loader-kotlin/src/test/resources/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("log") { + setExchangeFormatter { + e: Exchange -> "" + e.getIn().body + } + } + + component("seda") { + queueSize = 1234 + concurrentConsumers = 12 + } + + component("mySeda") { + queueSize = 4321 + concurrentConsumers = 21 + } + } +} + +from("timer:tick") + .to("log:info") \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-dataformats-configuration.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-dataformats-configuration.kts new file mode 100644 index 000000000..b5cc2673d --- /dev/null +++ b/camel-k-loader-kotlin/src/test/resources/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("json-jackson") { + unmarshalType = Map::class.java + isPrettyPrint = true + } + + dataFormat("my-jackson") { + unmarshalType = String::class.java + isPrettyPrint = false + } + } +} \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-error-handler.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-error-handler.kts index 6bc66788b..ed55f493c 100644 --- a/camel-k-loader-kotlin/src/test/resources/routes-with-error-handler.kts +++ b/camel-k-loader-kotlin/src/test/resources/routes-with-error-handler.kts @@ -1,4 +1,19 @@ - +/* + * 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") diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-languages-configuration.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-languages-configuration.kts new file mode 100644 index 000000000..065497a20 --- /dev/null +++ b/camel-k-loader-kotlin/src/test/resources/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("bean") { + beanType = String::class.java + method = "toUpperCase" + } + language("my-bean") { + beanType = String::class.java + method = "toLowerCase" + } + } +} \ No newline at end of file diff --git a/camel-k-loader-kotlin/src/test/resources/routes-with-rest.kts b/camel-k-loader-kotlin/src/test/resources/routes-with-rest.kts index 8d4d82ef4..37f28287a 100644 --- a/camel-k-loader-kotlin/src/test/resources/routes-with-rest.kts +++ b/camel-k-loader-kotlin/src/test/resources/routes-with-rest.kts @@ -1,4 +1,19 @@ - +/* + * 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" diff --git a/camel-k-loader-kotlin/src/test/resources/routes.kts b/camel-k-loader-kotlin/src/test/resources/routes.kts index 5bf9c9461..7d28bb5b9 100644 --- a/camel-k-loader-kotlin/src/test/resources/routes.kts +++ b/camel-k-loader-kotlin/src/test/resources/routes.kts @@ -1,4 +1,19 @@ - +/* + * 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"