From a32bab5cd22bc2f8a4432a0e7722efc0b1ba8c47 Mon Sep 17 00:00:00 2001 From: lburgazzoli Date: Mon, 1 Oct 2018 14:45:47 +0200 Subject: [PATCH] Add DSL to bind object to camel registry --- runtime/catalog-builder/pom.xml | 20 ++- runtime/dependency-lister/pom.xml | 18 +++ runtime/groovy/pom.xml | 18 +++ .../camel/k/groovy/GroovyRoutesLoader.java | 95 +++++++++++++- .../k/groovy/ComponentConfigurationTest.java | 54 ++++++++ .../org/apache/camel/k/groovy/RestTest.java | 54 ++++++++ ...LoadersTest.java => RoutesLoaderTest.java} | 5 +- .../camel/k/groovy/RuntimeRegistryTest.java | 54 ++++++++ .../groovy/src/test/resources/log4j2-test.xml | 19 +++ .../resources/routes-with-bindings.groovy | 8 ++ ...routes-with-component-configuration.groovy | 7 ++ .../test/resources/routes-with-rest.groovy | 13 ++ runtime/jvm/pom.xml | 18 +++ .../org/apache/camel/k/jvm/Application.java | 20 +-- .../org/apache/camel/k/jvm/RoutesLoader.java | 3 +- .../org/apache/camel/k/jvm/RoutesLoaders.java | 9 +- .../java/org/apache/camel/k/jvm/Runtime.java | 117 ++++++++++++++++++ .../apache/camel/k/jvm/RuntimeRegistry.java | 97 +++++++++++++++ .../org/apache/camel/k/jvm/dsl/Scripting.java | 47 ------- .../apache/camel/k/jvm/PropertiesTest.java | 23 ++-- .../apache/camel/k/jvm/RoutesLoadersTest.java | 10 +- runtime/kotlin/pom.xml | 18 +++ .../camel/k/kotlin/KotlinRoutesLoader.java | 5 +- .../camel/k/kotlin/RoutesLoadersTest.java | 3 +- .../camel/k/kotlin/RuntimeRegistryTest.java | 51 ++++++++ .../test/resources/routes-with-bindings.kts | 9 ++ runtime/kotlin/src/test/resources/routes.kts | 15 --- runtime/pom.xml | 26 +++- 28 files changed, 725 insertions(+), 111 deletions(-) create mode 100644 runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java create mode 100644 runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java rename runtime/groovy/src/test/java/org/apache/camel/k/groovy/{RoutesLoadersTest.java => RoutesLoaderTest.java} (92%) create mode 100644 runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java create mode 100644 runtime/groovy/src/test/resources/log4j2-test.xml create mode 100644 runtime/groovy/src/test/resources/routes-with-bindings.groovy create mode 100644 runtime/groovy/src/test/resources/routes-with-component-configuration.groovy create mode 100644 runtime/groovy/src/test/resources/routes-with-rest.groovy create mode 100644 runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java create mode 100644 runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java delete mode 100644 runtime/jvm/src/main/java/org/apache/camel/k/jvm/dsl/Scripting.java create mode 100644 runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java create mode 100644 runtime/kotlin/src/test/resources/routes-with-bindings.kts diff --git a/runtime/catalog-builder/pom.xml b/runtime/catalog-builder/pom.xml index 261d0cfbd0..931bef8c28 100644 --- a/runtime/catalog-builder/pom.xml +++ b/runtime/catalog-builder/pom.xml @@ -1,4 +1,22 @@ + @@ -16,7 +34,7 @@ org.codehaus.gmavenplus gmavenplus-plugin - 1.6 + ${gmavenplus-plugin.version} get-syndesis-version diff --git a/runtime/dependency-lister/pom.xml b/runtime/dependency-lister/pom.xml index 0bd8e915a5..c0262ee262 100644 --- a/runtime/dependency-lister/pom.xml +++ b/runtime/dependency-lister/pom.xml @@ -1,4 +1,22 @@ + diff --git a/runtime/groovy/pom.xml b/runtime/groovy/pom.xml index a3fb4782de..5fdc4fd6f4 100644 --- a/runtime/groovy/pom.xml +++ b/runtime/groovy/pom.xml @@ -1,4 +1,22 @@ + diff --git a/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java b/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java index ee8a5129e0..125cd26538 100644 --- a/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java +++ b/runtime/groovy/src/main/java/org/apache/camel/k/groovy/GroovyRoutesLoader.java @@ -19,16 +19,26 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.lang.reflect.Array; import java.util.Collections; import java.util.List; import groovy.lang.Binding; +import groovy.lang.Closure; +import groovy.lang.GroovyObjectSupport; import groovy.lang.GroovyShell; import groovy.util.DelegatingScript; +import org.apache.camel.CamelContext; +import org.apache.camel.Component; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.k.jvm.Language; import org.apache.camel.k.jvm.RoutesLoader; -import org.apache.camel.k.jvm.dsl.Scripting; +import org.apache.camel.k.jvm.RuntimeRegistry; +import org.apache.camel.k.jvm.dsl.Components; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.model.rest.RestConfigurationDefinition; +import org.apache.camel.model.rest.RestDefinition; +import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ResourceHelper; import org.codehaus.groovy.control.CompilerConfiguration; @@ -39,7 +49,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { @@ -54,10 +64,89 @@ public void configure() throws Exception { DelegatingScript script = (DelegatingScript) sh.parse(reader); // set the delegate target - script.setDelegate(new Scripting(this)); + script.setDelegate(new Scripting(registry, this)); script.run(); } } }; } + + + public static class Scripting { + private final RuntimeRegistry registry; + + public final CamelContext context; + public final Components components; + public final RouteBuilder builder; + + public Scripting(RuntimeRegistry registry, RouteBuilder builder) { + this.registry = registry; + this.context = builder.getContext(); + this.components = new Components(this.context); + this.builder = builder; + } + + public Component component(String name, Closure callable) { + final Component component = context.getComponent(name, true); + + callable.setResolveStrategy(Closure.DELEGATE_ONLY); + callable.setDelegate(new GroovyObjectSupport() { + public Object invokeMethod(String name, Object arg) { + if (arg == null) { + return super.invokeMethod(name, arg); + } + if (!arg.getClass().isArray()) { + return super.invokeMethod(name, arg); + } + + try { + IntrospectionSupport.setProperty(component, name, Array.get(arg, 0), true); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return component; + } + }); + + return callable.call(); + } + + public RouteDefinition from(String endpoint) { + return builder.from(endpoint); + } + + public RestDefinition rest() { + return builder.rest(); + } + + public RestDefinition rest(Closure callable) { + callable.setResolveStrategy(Closure.DELEGATE_ONLY); + callable.setDelegate(builder.rest()); + return callable.call(); + } + + public RestConfigurationDefinition restConfiguration() { + return builder.restConfiguration(); + } + + public void restConfiguration(Closure callable) { + callable.setResolveStrategy(Closure.DELEGATE_ONLY); + callable.setDelegate(builder.restConfiguration()); + callable.call(); + } + + public RestConfigurationDefinition restConfiguration(String component, Closure callable) { + callable.setResolveStrategy(Closure.DELEGATE_ONLY); + callable.setDelegate(builder.restConfiguration(component)); + return callable.call(); + } + + public RuntimeRegistry registry(Closure callable) { + callable.setResolveStrategy(Closure.DELEGATE_ONLY); + callable.setDelegate(registry); + + return callable.call(); + } + } } diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java new file mode 100644 index 0000000000..2589039ed4 --- /dev/null +++ b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/ComponentConfigurationTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.k.groovy; + + +import org.apache.camel.CamelContext; +import org.apache.camel.Component; +import org.apache.camel.k.jvm.Runtime; +import org.apache.camel.main.MainListenerSupport; +import org.apache.camel.main.MainSupport; +import org.junit.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +public class ComponentConfigurationTest { + @Test + public void testLoadRouteWithComponentConfiguration() throws Exception { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.load("classpath:routes-with-component-configuration.groovy", null); + runtime.addMainListener(new MainListenerSupport() { + @Override + public void afterStart(MainSupport main) { + try { + CamelContext context = main.getCamelContexts().get(0); + Component component = context.getComponent("seda"); + + assertThat(component).isNotNull(); + assertThat(component).hasFieldOrPropertyWithValue("queueSize", 1234); + + main.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + runtime.run(); + } +} diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java new file mode 100644 index 0000000000..09d9341619 --- /dev/null +++ b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RestTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.k.groovy; + + +import org.apache.camel.CamelContext; +import org.apache.camel.k.jvm.Runtime; +import org.apache.camel.main.MainListenerSupport; +import org.apache.camel.main.MainSupport; +import org.junit.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +public class RestTest { + @Test + public void testLoadRouteWithRest() throws Exception { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.load("classpath:routes-with-rest.groovy", null); + runtime.addMainListener(new MainListenerSupport() { + @Override + public void afterStart(MainSupport main) { + try { + CamelContext context = main.getCamelContexts().get(0); + + assertThat(context.getRestConfiguration()).hasFieldOrPropertyWithValue("host", "my-host"); + assertThat(context.getRestConfiguration()).hasFieldOrPropertyWithValue("port", 9192); + assertThat(context.getRestConfiguration("undertow", false)).hasFieldOrPropertyWithValue("host", "my-undertow-host"); + assertThat(context.getRestConfiguration("undertow", false)).hasFieldOrPropertyWithValue("port", 9193); + + main.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + runtime.run(); + } +} diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoadersTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java similarity index 92% rename from runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoadersTest.java rename to runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java index 8a64faaf31..909338384d 100644 --- a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoadersTest.java +++ b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RoutesLoaderTest.java @@ -21,18 +21,19 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.k.jvm.RoutesLoader; import org.apache.camel.k.jvm.RoutesLoaders; +import org.apache.camel.k.jvm.RuntimeRegistry; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.ToDefinition; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; -public class RoutesLoadersTest { +public class RoutesLoaderTest { @Test public void testLoadGroovy() throws Exception { String resource = "classpath:routes.groovy"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(GroovyRoutesLoader.class); assertThat(builder).isNotNull(); diff --git a/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java new file mode 100644 index 0000000000..f9d50f5067 --- /dev/null +++ b/runtime/groovy/src/test/java/org/apache/camel/k/groovy/RuntimeRegistryTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.k.groovy; + + +import org.apache.camel.CamelContext; +import org.apache.camel.k.jvm.Runtime; +import org.apache.camel.main.MainListenerSupport; +import org.apache.camel.main.MainSupport; +import org.apache.camel.spi.Registry; +import org.junit.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +public class RuntimeRegistryTest { + @Test + public void testLoadRouteWithBindings() throws Exception { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.load("classpath:routes-with-bindings.groovy", null); + runtime.addMainListener(new MainListenerSupport() { + @Override + public void afterStart(MainSupport main) { + try { + CamelContext context = main.getCamelContexts().get(0); + Registry registry = context.getRegistry(); + + assertThat(registry.lookup("myEntry1")).isEqualTo("myRegistryEntry1"); + assertThat(registry.lookup("myEntry2")).isEqualTo("myRegistryEntry2"); + + main.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + runtime.run(); + } +} diff --git a/runtime/groovy/src/test/resources/log4j2-test.xml b/runtime/groovy/src/test/resources/log4j2-test.xml new file mode 100644 index 0000000000..092e4fffd9 --- /dev/null +++ b/runtime/groovy/src/test/resources/log4j2-test.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/groovy/src/test/resources/routes-with-bindings.groovy b/runtime/groovy/src/test/resources/routes-with-bindings.groovy new file mode 100644 index 0000000000..30df96a020 --- /dev/null +++ b/runtime/groovy/src/test/resources/routes-with-bindings.groovy @@ -0,0 +1,8 @@ + +registry { + bind 'myEntry1', 'myRegistryEntry1' + bind 'myEntry2', 'myRegistryEntry2' +} + +from('timer:tick') + .to('log:info') \ No newline at end of file diff --git a/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy b/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy new file mode 100644 index 0000000000..31ff8b96ef --- /dev/null +++ b/runtime/groovy/src/test/resources/routes-with-component-configuration.groovy @@ -0,0 +1,7 @@ + +component('seda') { + queueSize 1234 +} + +from('timer:tick') + .to('log:info') \ No newline at end of file diff --git a/runtime/groovy/src/test/resources/routes-with-rest.groovy b/runtime/groovy/src/test/resources/routes-with-rest.groovy new file mode 100644 index 0000000000..f0187e4edd --- /dev/null +++ b/runtime/groovy/src/test/resources/routes-with-rest.groovy @@ -0,0 +1,13 @@ + +restConfiguration { + host 'my-host' + port '9192' +} + +restConfiguration('undertow') { + host 'my-undertow-host' + port '9193' +} + +from('timer:tick') + .to('log:info') \ No newline at end of file diff --git a/runtime/jvm/pom.xml b/runtime/jvm/pom.xml index 6251e75990..fdb80f7cd3 100644 --- a/runtime/jvm/pom.xml +++ b/runtime/jvm/pom.xml @@ -1,4 +1,22 @@ + diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java index 6ec328b8c8..c7560471ad 100644 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java @@ -20,8 +20,6 @@ import org.apache.camel.CamelContext; import org.apache.camel.Component; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.main.Main; import org.apache.camel.main.MainListenerSupport; import org.apache.camel.support.LifecycleStrategySupport; import org.apache.camel.util.IntrospectionSupport; @@ -64,20 +62,10 @@ public static void main(String[] args) throws Exception { throw new IllegalStateException("No valid resource found in " + Constants.ENV_CAMEL_K_ROUTES_URI + " environment variable"); } - RoutesLoader loader = RoutesLoaders.loaderFor(resource, language); - RouteBuilder routes = loader.load(resource); - - if (routes == null) { - throw new IllegalStateException("Unable to load route from: " + resource); - } - - LOGGER.info("Routes: {}", resource); - LOGGER.info("Language: {}", language); - - Main main = new Main(); - main.addMainListener(new ComponentPropertiesBinder()); - main.addRouteBuilder(routes); - main.run(); + Runtime runtime = new Runtime(); + runtime.load(resource, language); + runtime.addMainListener(new ComponentPropertiesBinder()); + runtime.run(); } // ******************************* diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java index 641f08cf9a..10cdaf8784 100644 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java @@ -31,9 +31,10 @@ public interface RoutesLoader { /** * Creates a camel {@link RouteBuilder} from the given resource. * + * @param registry the runtime registry. * @param resource the location fo the resource to load. * @return the RouteBuilder. * @throws Exception */ - RouteBuilder load(String resource) throws Exception; + RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception; } diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java index 2581d48529..1d69c8e90e 100644 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java @@ -60,7 +60,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { String path = resource; path = StringUtils.removeStart(path, SCHEME_CLASSPATH); path = StringUtils.removeEnd(path, ".class"); @@ -82,7 +82,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { @@ -111,7 +111,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { @@ -125,6 +125,7 @@ public void configure() throws Exception { bindings.put("builder", this); bindings.put("context", context); bindings.put("components", new Components(context)); + bindings.put("registry", registry); bindings.put("from", (Function) uri -> from(uri)); bindings.put("rest", (Supplier) () -> rest()); bindings.put("restConfiguration", (Supplier) () -> restConfiguration()); @@ -144,7 +145,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java new file mode 100644 index 0000000000..c9a70c2d3d --- /dev/null +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java @@ -0,0 +1,117 @@ +/** + * 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.jvm; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.properties.PropertiesComponent; +import org.apache.camel.impl.CompositeRegistry; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.main.MainSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Runtime extends MainSupport { + private static final Logger LOGGER = LoggerFactory.getLogger(Runtime.class); + + private final ConcurrentMap contextMap; + private final RuntimeRegistry registry = new RuntimeRegistry(); + + public Runtime() { + this.contextMap = new ConcurrentHashMap<>(); + } + + public void load(String resource, String language) throws Exception { + final RoutesLoader loader = RoutesLoaders.loaderFor(resource, language); + final RouteBuilder routes = loader.load(registry, resource); + + if (routes == null) { + throw new IllegalStateException("Unable to load route from: " + resource); + } + + LOGGER.info("Routes: {}", resource); + LOGGER.info("Language: {}", language); + + addRouteBuilder(routes); + } + + public RuntimeRegistry getRegistry() { + return registry; + } + + public CamelContext getOrCreateCamelContext() { + return contextMap.computeIfAbsent("camel-1", key -> { + DefaultCamelContext camelContext = new DefaultCamelContext(); + + CompositeRegistry registry = new CompositeRegistry(); + registry.addRegistry(this.registry); + registry.addRegistry(camelContext.getRegistry()); + + camelContext.setRegistry(registry); + + return camelContext; + }); + } + + public void setPropertyPlaceholderLocations(String location) { + PropertiesComponent pc = new PropertiesComponent(); + pc.setLocation(location); + + getRegistry().bind("properties", pc); + } + + @Override + protected ProducerTemplate findOrCreateCamelTemplate() { + return getCamelContexts().size() > 0 ? getCamelContexts().get(0).createProducerTemplate() : null; + } + + @Override + protected Map getCamelContextMap() { + getOrCreateCamelContext(); + + return contextMap; + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + postProcessContext(); + if (!getCamelContexts().isEmpty()) { + try { + getCamelContexts().get(0).start(); + } finally { + if (getCamelContexts().get(0).isVetoStarted()) { + completed(); + } + } + } + } + + @Override + protected void doStop() throws Exception { + super.doStop(); + + if (!getCamelContexts().isEmpty()) { + getCamelContexts().get(0).stop(); + } + } +} diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java new file mode 100644 index 0000000000..f837186396 --- /dev/null +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeRegistry.java @@ -0,0 +1,97 @@ +/** + * 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.jvm; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + +import org.apache.camel.NoSuchBeanException; +import org.apache.camel.spi.Registry; + +public class RuntimeRegistry implements Registry { + private final ConcurrentMap registry; + + public RuntimeRegistry() { + this.registry = new ConcurrentHashMap<>(); + } + + public void bind(String name, Object bean) { + this.registry.put(name, bean); + } + + @Override + public Object lookupByName(String name) { + return registry.get(name); + } + + @Override + public T lookupByNameAndType(String name, Class type) { + final Object answer = lookupByName(name); + + if (answer != null) { + try { + return type.cast(answer); + } catch (Throwable t) { + throw new NoSuchBeanException( + name, + "Found bean: " + name + " in RuntimeRegistry: " + this + " of type: " + answer.getClass().getName() + " expected type was: " + type, + t + ); + } + } + + return null; + } + + @Override + public Map findByTypeWithName(Class type) { + final Map result = new HashMap<>(); + + registry.entrySet().stream() + .filter(entry -> type.isInstance(entry.getValue())) + .forEach(entry -> result.put(entry.getKey(), type.cast(entry.getValue()))); + + return result; + } + + @Override + public Set findByType(Class type) { + return registry.values().stream() + .filter(type::isInstance) + .map(type::cast) + .collect(Collectors.toSet()); + } + + @Override + public Object lookup(String name) { + return lookupByName(name); + } + + @Override + public T lookup(String name, Class type) { + return lookupByNameAndType(name, type); + } + + @Override + public Map lookupByType(Class type) { + return findByTypeWithName(type); + } +} diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/dsl/Scripting.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/dsl/Scripting.java deleted file mode 100644 index 3988290e28..0000000000 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/dsl/Scripting.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.k.jvm.dsl; - -import org.apache.camel.CamelContext; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.model.RouteDefinition; -import org.apache.camel.model.rest.RestConfigurationDefinition; -import org.apache.camel.model.rest.RestDefinition; - -public class Scripting { - public final RouteBuilder builder; - public final CamelContext context; - public final Components components; - - public Scripting(RouteBuilder builder) { - this.builder = builder; - this.context = builder.getContext(); - this.components = new Components(builder.getContext()); - } - - public RouteDefinition from(String endpoint) { - return builder.from(endpoint); - } - - public RestDefinition rest() { - return builder.rest(); - } - - public RestConfigurationDefinition restConfiguration() { - return builder.restConfiguration(); - } -} diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java index 2bfba135ce..f77e4171e5 100644 --- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java +++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java @@ -20,7 +20,6 @@ import org.apache.camel.CamelContext; import org.apache.camel.component.seda.SedaComponent; -import org.apache.camel.main.Main; import org.apache.camel.main.MainListenerSupport; import org.apache.camel.main.MainSupport; import org.junit.Test; @@ -34,10 +33,10 @@ public void testSystemProperties() throws Exception { System.setProperty("my.property", "my.value"); try { - Main main = new Main(); - main.setDuration(5); - main.addMainListener(new Application.ComponentPropertiesBinder()); - main.addMainListener(new MainListenerSupport() { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.addMainListener(new Application.ComponentPropertiesBinder()); + runtime.addMainListener(new MainListenerSupport() { @Override public void afterStart(MainSupport main) { try { @@ -53,7 +52,7 @@ public void afterStart(MainSupport main) { } }); - main.run(); + runtime.run(); } finally { System.getProperties().remove("my.property"); } @@ -69,11 +68,11 @@ public void testComponentConfiguration() throws Exception { System.setProperty("camel.component.my-seda.queueSize", Integer.toString(queueSize2)); try { - Main main = new Main(); - main.setDuration(5); - main.bind("my-seda", new SedaComponent()); - main.addMainListener(new Application.ComponentPropertiesBinder()); - main.addMainListener(new MainListenerSupport() { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.getRegistry().bind("my-seda", new SedaComponent()); + runtime.addMainListener(new Application.ComponentPropertiesBinder()); + runtime.addMainListener(new MainListenerSupport() { @Override public void afterStart(MainSupport main) { try { @@ -89,7 +88,7 @@ public void afterStart(MainSupport main) { } }); - main.run(); + runtime.run(); } finally { System.getProperties().remove("camel.component.seda.queueSize"); } diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java index 54b492b7b8..c58f2a46f3 100644 --- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java +++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java @@ -31,7 +31,7 @@ public class RoutesLoadersTest { public void testLoadClass() throws Exception { String resource = "classpath:" + MyRoutes.class.getName() + ".class"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(RoutesLoaders.JavaClass.class); assertThat(builder).isNotNull(); @@ -48,7 +48,7 @@ public void testLoadClass() throws Exception { public void testLoadJava() throws Exception { String resource = "classpath:MyRoutes.java"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(RoutesLoaders.JavaSource.class); assertThat(builder).isNotNull(); @@ -65,7 +65,7 @@ public void testLoadJava() throws Exception { public void testLoadJavaScript() throws Exception { String resource = "classpath:routes.js"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(RoutesLoaders.JavaScript.class); assertThat(builder).isNotNull(); @@ -82,7 +82,7 @@ public void testLoadJavaScript() throws Exception { public void testLoadJavaScriptWithCustomExtension() throws Exception { String resource = "classpath:routes.mytype"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, "js"); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(RoutesLoaders.JavaScript.class); assertThat(builder).isNotNull(); @@ -99,7 +99,7 @@ public void testLoadJavaScriptWithCustomExtension() throws Exception { public void testLoadXml() throws Exception { String resource = "classpath:routes.xml"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(RoutesLoaders.Xml.class); assertThat(builder).isNotNull(); diff --git a/runtime/kotlin/pom.xml b/runtime/kotlin/pom.xml index 9036f76504..c78c96b338 100644 --- a/runtime/kotlin/pom.xml +++ b/runtime/kotlin/pom.xml @@ -1,4 +1,22 @@ + diff --git a/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java b/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java index 0b887efaac..3759371b15 100644 --- a/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java +++ b/runtime/kotlin/src/main/java/org/apache/camel/k/kotlin/KotlinRoutesLoader.java @@ -27,6 +27,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.k.jvm.RuntimeRegistry; import org.apache.camel.k.jvm.dsl.Components; import org.apache.camel.k.jvm.Language; import org.apache.camel.k.jvm.RoutesLoader; @@ -40,7 +41,7 @@ public List getSupportedLanguages() { } @Override - public RouteBuilder load(String resource) throws Exception { + public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { @@ -52,6 +53,7 @@ public void configure() throws Exception { // Exposed to the underlying script, but maybe better to have // a nice dsl bindings.put("builder", this); + bindings.put("registry", registry); bindings.put("context", context); bindings.put("components", new Components(context)); @@ -62,6 +64,7 @@ public void configure() throws Exception { builder.append("val builder = bindings[\"builder\"] as org.apache.camel.builder.RouteBuilder").append('\n'); builder.append("val context = bindings[\"context\"] as org.apache.camel.CamelContext").append('\n'); builder.append("val components = bindings[\"components\"] as org.apache.camel.k.jvm.dsl.Components").append('\n'); + builder.append("val registry = bindings[\"registry\"] as org.apache.camel.k.jvm.RuntimeRegistry").append('\n'); // create aliases for common functions builder.append("fun from(uri: String): org.apache.camel.model.RouteDefinition = builder.from(uri)").append('\n'); diff --git a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java index 5c23d67f58..ecf3c51ef5 100644 --- a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java +++ b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RoutesLoadersTest.java @@ -21,6 +21,7 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.k.jvm.RoutesLoader; import org.apache.camel.k.jvm.RoutesLoaders; +import org.apache.camel.k.jvm.RuntimeRegistry; import org.apache.camel.model.ProcessDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.ToDefinition; @@ -34,7 +35,7 @@ public class RoutesLoadersTest { public void testLoadKotlin() throws Exception { String resource = "classpath:routes.kts"; RoutesLoader loader = RoutesLoaders.loaderFor(resource, null); - RouteBuilder builder = loader.load(resource); + RouteBuilder builder = loader.load(new RuntimeRegistry(), resource); assertThat(loader).isInstanceOf(KotlinRoutesLoader.class); assertThat(builder).isNotNull(); diff --git a/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java new file mode 100644 index 0000000000..aa826aec69 --- /dev/null +++ b/runtime/kotlin/src/test/java/org/apache/camel/k/kotlin/RuntimeRegistryTest.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.k.kotlin; + +import org.apache.camel.CamelContext; +import org.apache.camel.k.jvm.Runtime; +import org.apache.camel.main.MainListenerSupport; +import org.apache.camel.main.MainSupport; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RuntimeRegistryTest { + @Test + public void testLoadRouteWithBindings() throws Exception { + Runtime runtime = new Runtime(); + runtime.setDuration(5); + runtime.load("classpath:routes-with-bindings.kts", null); + runtime.addMainListener(new MainListenerSupport() { + @Override + public void afterStart(MainSupport main) { + try { + CamelContext context = main.getCamelContexts().get(0); + Object value = context.getRegistry().lookup("myEntry"); + + assertThat(value).isEqualTo("myRegistryEntry"); + + main.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + runtime.run(); + } +} diff --git a/runtime/kotlin/src/test/resources/routes-with-bindings.kts b/runtime/kotlin/src/test/resources/routes-with-bindings.kts new file mode 100644 index 0000000000..368bf69569 --- /dev/null +++ b/runtime/kotlin/src/test/resources/routes-with-bindings.kts @@ -0,0 +1,9 @@ + +registry.bind("myEntry", "myRegistryEntry") + + +from("timer:tick") + .process().message { + m -> m.headers["MyHeader"] = "MyHeaderValue" + } + .to("log:info") \ No newline at end of file diff --git a/runtime/kotlin/src/test/resources/routes.kts b/runtime/kotlin/src/test/resources/routes.kts index 22b0e149f0..5bf9c94616 100644 --- a/runtime/kotlin/src/test/resources/routes.kts +++ b/runtime/kotlin/src/test/resources/routes.kts @@ -1,19 +1,4 @@ -// ******************** -// -// setup -// -// ******************** - -//val builder = bindings["builder"] as org.apache.camel.builder.RouteBuilder -//fun from(uri: String): org.apache.camel.model.RouteDefinition = builder.from(uri) - -// ******************** -// -// routes -// -// ******************** - from("timer:tick") .process().message { m -> m.headers["MyHeader"] = "MyHeaderValue" diff --git a/runtime/pom.xml b/runtime/pom.xml index 8278b4f4b9..3cd3c78566 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -1,4 +1,22 @@ + @@ -11,7 +29,7 @@ UTF-8 - + 1.8 1.8 @@ -19,15 +37,17 @@ 4.12 0.9.9 2.6 - 3.8 + 3.8.1 3.11.1 - 2.11.0 + 2.11.1 1.7.25 2.5.2 1.2.71 1.23 + 1.6.1 3.5.40 + 3.8.0