[camel-k] branch master updated: chore(runtime): code cleanup

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[camel-k] branch master updated: chore(runtime): code cleanup

nferraro
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/master by this push:
     new 9ab0df1  chore(runtime): code cleanup
9ab0df1 is described below

commit 9ab0df192682e2a4dbb80f470766f4eced265d3c
Author: lburgazzoli <[hidden email]>
AuthorDate: Thu Dec 6 00:54:47 2018 +0100

    chore(runtime): code cleanup
---
 runtime/catalog-builder/pom.xml                    |  6 ++
 .../camel/k/groovy/GroovyRoutesLoader.groovy       |  9 +--
 .../org/apache/camel/k/groovy/LoaderTest.groovy    |  7 ++-
 .../java/org/apache/camel/k/jvm/Application.java   | 21 ++++---
 .../java/org/apache/camel/k/jvm/RoutesLoader.java  |  4 +-
 .../java/org/apache/camel/k/jvm/RoutesLoaders.java | 35 ++++--------
 .../main/java/org/apache/camel/k/jvm/Runtime.java  | 18 ++----
 .../org/apache/camel/k/jvm/RuntimeRegistry.java    | 20 +++++++
 .../org/apache/camel/k/jvm/RuntimeSupport.java     | 19 +++----
 .../apache/camel/k/jvm/SimpleRuntimeRegistry.java  | 19 -------
 .../main/java/org/apache/camel/k/jvm/Source.java   | 65 ++++++++++++++++++++++
 .../org/apache/camel/k/jvm/PropertiesTest.java     | 33 +++++++++++
 .../org/apache/camel/k/jvm/RoutesLoadersTest.java  | 49 ++++++++--------
 .../src/test/resources/conf.d/001/conf.properties  |  1 +
 .../src/test/resources/conf.d/002/conf.properties  |  2 +
 runtime/jvm/src/test/resources/conf.properties     |  2 +
 .../apache/camel/k/kotlin/KotlinRoutesLoader.kt    |  9 +--
 .../kotlin/org/apache/camel/k/kotlin/LoaderTest.kt |  7 ++-
 .../apache/camel/k/spring/boot/Application.java    | 61 ++++++++------------
 19 files changed, 230 insertions(+), 157 deletions(-)

diff --git a/runtime/catalog-builder/pom.xml b/runtime/catalog-builder/pom.xml
index 46d5707..9e0968d 100644
--- a/runtime/catalog-builder/pom.xml
+++ b/runtime/catalog-builder/pom.xml
@@ -69,6 +69,12 @@
             <scope>runtime</scope>
           </dependency>
           <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-ant</artifactId>
+            <version>${groovy.version}</version>
+            <scope>runtime</scope>
+          </dependency>
+          <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-core</artifactId>
             <version>${camel.version}</version>
diff --git a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
index 86cb7fe..6d08010 100644
--- a/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
+++ b/runtime/groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
@@ -19,10 +19,7 @@ package org.apache.camel.k.groovy
 
 import org.apache.camel.builder.RouteBuilder
 import org.apache.camel.k.groovy.dsl.IntegrationConfiguration
-import org.apache.camel.k.jvm.Language
-import org.apache.camel.k.jvm.RoutesLoader
-import org.apache.camel.k.jvm.RuntimeRegistry
-import org.apache.camel.k.jvm.URIResolver
+import org.apache.camel.k.jvm.*
 import org.codehaus.groovy.control.CompilerConfiguration
 
 class GroovyRoutesLoader implements RoutesLoader {
@@ -32,7 +29,7 @@ class GroovyRoutesLoader implements RoutesLoader {
     }
 
     @Override
-    RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
+    RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
         return new RouteBuilder() {
             @Override
             void configure() throws Exception {
@@ -41,7 +38,7 @@ class GroovyRoutesLoader implements RoutesLoader {
 
                 def cl = Thread.currentThread().getContextClassLoader()
                 def sh = new GroovyShell(cl, new Binding(), cc)
-                def is = URIResolver.resolve(context, resource)
+                def is = URIResolver.resolve(context, source.location)
 
                 is.withCloseable {
                     def reader = new InputStreamReader(is)
diff --git a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
index b7c7c95..ab3779c 100644
--- a/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
+++ b/runtime/groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
@@ -18,6 +18,7 @@ package org.apache.camel.k.groovy
 
 import org.apache.camel.k.jvm.RoutesLoaders
 import org.apache.camel.k.jvm.SimpleRuntimeRegistry
+import org.apache.camel.k.jvm.Source
 import org.apache.camel.model.ToDefinition
 import spock.lang.Specification
 
@@ -25,11 +26,11 @@ class LoaderTest extends Specification {
 
     def "load route from classpath"() {
         given:
-            def resource = "classpath:routes.groovy"
+            def source = Source.create("classpath:routes.groovy")
 
         when:
-            def loader = RoutesLoaders.loaderFor(resource, null)
-            def builder = loader.load(new SimpleRuntimeRegistry(), resource)
+            def loader = RoutesLoaders.loaderFor(source)
+            def builder = loader.load(new SimpleRuntimeRegistry(), source)
 
         then:
             loader instanceof GroovyRoutesLoader
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 69cbc96..917b566 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
@@ -16,8 +16,11 @@
  */
 package org.apache.camel.k.jvm;
 
+import java.util.Properties;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
+import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.main.MainListenerSupport;
 import org.apache.camel.support.LifecycleStrategySupport;
 import org.apache.camel.util.ObjectHelper;
@@ -25,12 +28,6 @@ import org.apache.camel.util.ObjectHelper;
 public class Application {
     static {
         //
-        // Load properties as system properties so they are accessible through
-        // camel's properties component as well as for runtime configuration.
-        //
-        RuntimeSupport.configureSystemProperties();
-
-        //
         // Configure the logging subsystem log4j2 using a subset of spring boot
         // conventions:
         //
@@ -55,6 +52,7 @@ public class Application {
         }
 
         Runtime runtime = new Runtime();
+        runtime.setProperties(RuntimeSupport.loadProperties());
         runtime.load(routes.split(",", -1));
         runtime.addMainListener(new ComponentPropertiesBinder());
         runtime.run();
@@ -69,11 +67,18 @@ public class Application {
     static class ComponentPropertiesBinder extends MainListenerSupport {
         @Override
         public void configure(CamelContext context) {
+            final PropertiesComponent component = context.getComponent("properties", PropertiesComponent.class);
+            final Properties properties = component.getInitialProperties();
+
+            if (properties == null) {
+                throw new IllegalStateException("PropertiesComponent has no properties");
+            }
+
             // Configure the camel context using properties in the form:
             //
             //     camel.context.${name} = ${value}
             //
-            RuntimeSupport.bindProperties(context, "camel.context.");
+            RuntimeSupport.bindProperties(properties, context, "camel.context.");
 
             context.addLifecycleStrategy(new LifecycleStrategySupport() {
                 @SuppressWarnings("unchecked")
@@ -85,7 +90,7 @@ public class Application {
                     //
                     //     camel.component.${scheme}.${name} = ${value}
                     //
-                    RuntimeSupport.bindProperties(component, "camel.component." + name + ".");
+                    RuntimeSupport.bindProperties(properties, component, "camel.component." + name + ".");
                 }
             });
         }
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 10cdaf8..faac8ed 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
@@ -32,9 +32,9 @@ 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.
+     * @param source the source to load.
      * @return the RouteBuilder.
      * @throws Exception
      */
-    RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception;
+    RouteBuilder load(RuntimeRegistry registry, Source source) 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 0d81738..1783de0 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
@@ -36,7 +36,6 @@ 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.ObjectHelper;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.joor.Reflect;
@@ -56,8 +55,8 @@ public final class RoutesLoaders {
         }
 
         @Override
-        public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
-            String path = resource;
+        public RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
+            String path = source.getLocation();
             path = StringUtils.removeStart(path, Constants.SCHEME_CLASSPATH);
             path = StringUtils.removeEnd(path, ".class");
 
@@ -78,12 +77,12 @@ public final class RoutesLoaders {
         }
 
         @Override
-        public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
+        public RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
             return new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
-                    try (InputStream is = URIResolver.resolve(getContext(), resource)) {
-                        String name = StringUtils.substringAfter(resource, ":");
+                    try (InputStream is = URIResolver.resolve(getContext(), source.getLocation())) {
+                        String name = StringUtils.substringAfter(source.getLocation(), ":");
                         name = StringUtils.removeEnd(name, ".java");
 
                         if (name.contains("/")) {
@@ -107,7 +106,7 @@ public final class RoutesLoaders {
         }
 
         @Override
-        public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
+        public RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
             return new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -126,7 +125,7 @@ public final class RoutesLoaders {
                     bindings.put("rest", (Supplier<RestDefinition>) () -> rest());
                     bindings.put("restConfiguration", (Supplier<RestConfigurationDefinition>) () -> restConfiguration());
 
-                    try (InputStream is = URIResolver.resolve(context, resource)) {
+                    try (InputStream is = URIResolver.resolve(context, source.getLocation())) {
                         engine.eval(new InputStreamReader(is), bindings);
                     }
                 }
@@ -141,11 +140,11 @@ public final class RoutesLoaders {
         }
 
         @Override
-        public RouteBuilder load(RuntimeRegistry registry, String resource) throws Exception {
+        public RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
             return new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
-                    try (InputStream is = URIResolver.resolve(getContext(), resource)) {
+                    try (InputStream is = URIResolver.resolve(getContext(), source.getLocation())) {
                         try {
                             setRouteCollection(
                                 getContext().loadRoutesDefinition(is)
@@ -168,23 +167,13 @@ public final class RoutesLoaders {
     }
 
 
-    public static RoutesLoader loaderFor(String resource, String languageName) {
-        if (!resource.startsWith(Constants.SCHEME_CLASSPATH) &&
-            !resource.startsWith(Constants.SCHEME_FILE) &&
-            !resource.startsWith(Constants.SCHEME_ENV)) {
-            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + resource);
-        }
-
-        Language language = ObjectHelper.isNotEmpty(languageName)
-            ? Language.fromLanguageName(languageName)
-            : Language.fromResource(resource);
-
+    public static RoutesLoader loaderFor(Source source) {
         for (RoutesLoader loader: ServiceLoader.load(RoutesLoader.class)) {
-            if (loader.getSupportedLanguages().contains(language)) {
+            if (loader.getSupportedLanguages().contains(source.getLanguage())) {
                 return loader;
             }
         }
 
-        throw new IllegalArgumentException("Unable to find loader for: resource=" + resource + " language=" + languageName);
+        throw new IllegalArgumentException("Unable to find loader for: " + source);
     }
 }
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
index ffa71a0..1e05e70 100644
--- 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
@@ -17,6 +17,7 @@
 package org.apache.camel.k.jvm;
 
 import java.util.Map;
+import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -27,8 +28,6 @@ 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.apache.camel.util.URISupport;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,14 +43,9 @@ public final class Runtime extends MainSupport {
 
     public void load(String[] routes) throws Exception {
         for (String route: routes) {
-            // determine location and language
-            final String location = StringUtils.substringBefore(route, "?");
-            final String query = StringUtils.substringAfter(route, "?");
-            final String language = (String)URISupport.parseQuery(query).get("language");
-
-            // load routes
-            final RoutesLoader loader = RoutesLoaders.loaderFor(location, language);
-            final RouteBuilder builder = loader.load(registry, location);
+            final Source source = Source.create(route);
+            final RoutesLoader loader = RoutesLoaders.loaderFor(source);
+            final RouteBuilder builder = loader.load(registry, source);
 
             if (builder == null) {
                 throw new IllegalStateException("Unable to load route from: " + route);
@@ -82,9 +76,9 @@ public final class Runtime extends MainSupport {
         });
     }
 
-    public void setPropertyPlaceholderLocations(String location) {
+    public void setProperties(Properties properties) {
         PropertiesComponent pc = new PropertiesComponent();
-        pc.setLocation(location);
+        pc.setInitialProperties(properties);
 
         getRegistry().bind("properties", pc);
     }
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
index 3b41e2b..7e13a28 100644
--- 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
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.k.jvm;
 
+import java.util.Map;
+
 import org.apache.camel.spi.Registry;
 
 public interface RuntimeRegistry extends Registry {
@@ -24,4 +26,22 @@ public interface RuntimeRegistry extends Registry {
      *
      */
     void bind(String name, Object bean);
+
+    @SuppressWarnings("deprecation")
+    @Override
+    default public Object lookup(String name) {
+        return lookupByName(name);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    default public <T> T lookup(String name, Class<T> type) {
+        return lookupByNameAndType(name, type);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    default public <T> Map<String, T> lookupByType(Class<T> type) {
+        return findByTypeWithName(type);
+    }
 }
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
index 423ee08..936e4d1 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
@@ -44,6 +44,11 @@ public final class RuntimeSupport {
     public static Properties loadProperties() {
         final String conf = System.getenv(Constants.ENV_CAMEL_K_CONF);
         final String confd = System.getenv(Constants.ENV_CAMEL_K_CONF_D);
+
+        return loadProperties(conf, confd);
+    }
+
+    public static Properties loadProperties(String conf, String confd) {
         final Properties properties = new Properties();
 
         // Main location
@@ -97,16 +102,9 @@ public final class RuntimeSupport {
         return properties;
     }
 
-    public static void configureSystemProperties() {
-        final Properties properties = loadProperties();
-
-        // TODO: sensitive info, maybe better to use properties component ...
-        System.getProperties().putAll(properties);
-    }
-
     public static void configureLogging() {
         final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        final Properties properties = System.getProperties();
+        final Properties properties = loadProperties();
 
         properties.entrySet().stream()
             .filter(entry -> entry.getKey() instanceof String)
@@ -125,10 +123,7 @@ public final class RuntimeSupport {
         );
     }
 
-    public static void bindProperties(Object target, String prefix) {
-        // Integration properties are defined as system properties
-        final Properties properties = System.getProperties();
-
+    public static void bindProperties(Properties properties, Object target, String prefix) {
         properties.entrySet().stream()
             .filter(entry -> entry.getKey() instanceof String)
             .filter(entry -> entry.getValue() != null)
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/SimpleRuntimeRegistry.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/SimpleRuntimeRegistry.java
index f09b331..1035b9c 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/SimpleRuntimeRegistry.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/SimpleRuntimeRegistry.java
@@ -24,7 +24,6 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Collectors;
 
 import org.apache.camel.NoSuchBeanException;
-import org.apache.camel.spi.Registry;
 
 public class SimpleRuntimeRegistry implements RuntimeRegistry {
     private final ConcurrentMap<String, Object> registry;
@@ -79,22 +78,4 @@ public class SimpleRuntimeRegistry implements RuntimeRegistry {
             .map(type::cast)
             .collect(Collectors.toSet());
     }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public Object lookup(String name) {
-        return lookupByName(name);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public <T> T lookup(String name, Class<T> type) {
-        return lookupByNameAndType(name, type);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public <T> Map<String, T> lookupByType(Class<T> type) {
-        return findByTypeWithName(type);
-    }
 }
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Source.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Source.java
new file mode 100644
index 0000000..d4344eb
--- /dev/null
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Source.java
@@ -0,0 +1,65 @@
+/**
+ * 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 org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.apache.commons.lang3.StringUtils;
+
+public class Source {
+    private final String location;
+    private final Language language;
+
+    private Source(String location, Language language) {
+        this.location = location;
+        this.language = language;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public Language getLanguage() {
+        return language;
+    }
+
+    @Override
+    public String toString() {
+        return "Source{" +
+            "location='" + location + '\'' +
+            ", language=" + language +
+            '}';
+    }
+
+    public static Source create(String uri) throws Exception {
+        final String location = StringUtils.substringBefore(uri, "?");
+        final String query = StringUtils.substringAfter(uri, "?");
+        final String languageName = (String) URISupport.parseQuery(query).get("language");
+
+        if (!location.startsWith(Constants.SCHEME_CLASSPATH) &&
+            !location.startsWith(Constants.SCHEME_FILE) &&
+            !location.startsWith(Constants.SCHEME_ENV)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + uri);
+        }
+
+        Language language = ObjectHelper.isNotEmpty(languageName)
+            ? Language.fromLanguageName(languageName)
+            : Language.fromResource(location);
+
+        return new Source(location, language);
+    }
+}
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 ffb727e..6ae8324 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
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.k.jvm;
 
+import java.util.Properties;
 import java.util.concurrent.ThreadLocalRandom;
 
 import org.apache.camel.CamelContext;
@@ -29,11 +30,41 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class PropertiesTest {
 
     @Test
+    public void testLoadProperties() throws Exception {
+        Properties properties = RuntimeSupport.loadProperties("src/test/resources/conf.properties", "src/test/resources/conf.d");
+
+        Runtime runtime = new Runtime();
+        runtime.setProperties(properties);
+        runtime.setDuration(5);
+        runtime.addMainListener(new Application.ComponentPropertiesBinder());
+        runtime.addMainListener(new MainListenerSupport() {
+            @Override
+            public void afterStart(MainSupport main) {
+                try {
+                    CamelContext context = main.getCamelContexts().get(0);
+
+                    assertThat(context.resolvePropertyPlaceholders("{{root.key}}")).isEqualTo("root.value");
+                    assertThat(context.resolvePropertyPlaceholders("{{001.key}}")).isEqualTo("001.value");
+                    assertThat(context.resolvePropertyPlaceholders("{{002.key}}")).isEqualTo("002.value");
+                    assertThat(context.resolvePropertyPlaceholders("{{a.key}}")).isEqualTo("a.002");
+
+                    main.stop();
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        runtime.run();
+    }
+
+    @Test
     public void testSystemProperties() throws Exception {
         System.setProperty("my.property", "my.value");
 
         try {
             Runtime runtime = new Runtime();
+            runtime.setProperties(System.getProperties());
             runtime.setDuration(5);
             runtime.addMainListener(new Application.ComponentPropertiesBinder());
             runtime.addMainListener(new MainListenerSupport() {
@@ -68,6 +99,7 @@ public class PropertiesTest {
 
         try {
             Runtime runtime = new Runtime();
+            runtime.setProperties(System.getProperties());
             runtime.setDuration(5);
             runtime.getRegistry().bind("my-seda", new SedaComponent());
             runtime.addMainListener(new Application.ComponentPropertiesBinder());
@@ -101,6 +133,7 @@ public class PropertiesTest {
 
         try {
             Runtime runtime = new Runtime();
+            runtime.setProperties(System.getProperties());
             runtime.setDuration(5);
             runtime.getRegistry().bind("my-seda", new SedaComponent());
             runtime.addMainListener(new Application.ComponentPropertiesBinder());
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 92ec897..eb84ed1 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
@@ -16,10 +16,8 @@
  */
 package org.apache.camel.k.jvm;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
-
 import java.util.List;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.model.ProcessDefinition;
 import org.apache.camel.model.RouteDefinition;
@@ -27,13 +25,16 @@ import org.apache.camel.model.SetBodyDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.junit.jupiter.api.Test;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
+
 public class RoutesLoadersTest {
 
     @Test
     public void testLoadClass() throws Exception {
-        String resource = "classpath:" + MyRoutes.class.getName() + ".class";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:" + MyRoutes.class.getName() + ".class");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.JavaClass.class);
         assertThat(builder).isNotNull();
@@ -48,9 +49,9 @@ public class RoutesLoadersTest {
 
     @Test
     public void testLoadJava() throws Exception {
-        String resource = "classpath:MyRoutes.java";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:MyRoutes.java");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.JavaSource.class);
         assertThat(builder).isNotNull();
@@ -66,9 +67,9 @@ public class RoutesLoadersTest {
 
     @Test
     public void testLoadJavaWithNestedClass() throws Exception {
-        String resource = "classpath:MyRoutesWithNestedClass.java";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:MyRoutesWithNestedClass.java");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.JavaSource.class);
         assertThat(builder).isNotNull();
@@ -86,9 +87,9 @@ public class RoutesLoadersTest {
 
     @Test
     public void testLoadJavaScript() throws Exception {
-        String resource = "classpath:routes.js";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:routes.js");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.JavaScript.class);
         assertThat(builder).isNotNull();
@@ -103,9 +104,9 @@ public class RoutesLoadersTest {
 
     @Test
     public void testLoadJavaScriptWithCustomExtension() throws Exception {
-        String resource = "classpath:routes.mytype";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, "js");
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:routes.mytype?language=js");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.JavaScript.class);
         assertThat(builder).isNotNull();
@@ -120,9 +121,9 @@ public class RoutesLoadersTest {
 
     @Test
     public void testLoadXml() throws Exception {
-        String resource = "classpath:routes.xml";
-        RoutesLoader loader = RoutesLoaders.loaderFor(resource, null);
-        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), resource);
+        Source source = Source.create("classpath:routes.xml");
+        RoutesLoader loader = RoutesLoaders.loaderFor(source);
+        RouteBuilder builder = loader.load(new SimpleRuntimeRegistry(), source);
 
         assertThat(loader).isInstanceOf(RoutesLoaders.Xml.class);
         assertThat(builder).isNotNull();
@@ -138,21 +139,21 @@ public class RoutesLoadersTest {
     @Test
     public void testResourceWithoutScheme() {
         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
-            () -> RoutesLoaders.loaderFor("routes.js", null)
+            () -> Source.create("routes.js")
         );
     }
 
     @Test
     public void testResourceWithIllegalScheme() {
         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
-            () -> RoutesLoaders.loaderFor("http:routes.js", null)
+            () -> Source.create("http:routes.js")
         );
     }
 
     @Test
     public void testUnsupportedLanguage() {
         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
-            () -> RoutesLoaders.loaderFor("  test", null)
+            () -> Source.create("  test")
         );
     }
 
diff --git a/runtime/jvm/src/test/resources/conf.d/001/conf.properties b/runtime/jvm/src/test/resources/conf.d/001/conf.properties
new file mode 100644
index 0000000..f0832c7
--- /dev/null
+++ b/runtime/jvm/src/test/resources/conf.d/001/conf.properties
@@ -0,0 +1 @@
+001.key = 001.value
\ No newline at end of file
diff --git a/runtime/jvm/src/test/resources/conf.d/002/conf.properties b/runtime/jvm/src/test/resources/conf.d/002/conf.properties
new file mode 100644
index 0000000..dfa6ce1
--- /dev/null
+++ b/runtime/jvm/src/test/resources/conf.d/002/conf.properties
@@ -0,0 +1,2 @@
+002.key = 002.value
+a.key = a.002
\ No newline at end of file
diff --git a/runtime/jvm/src/test/resources/conf.properties b/runtime/jvm/src/test/resources/conf.properties
new file mode 100644
index 0000000..4486a9d
--- /dev/null
+++ b/runtime/jvm/src/test/resources/conf.properties
@@ -0,0 +1,2 @@
+root.key = root.value
+a.key = a.root
\ No newline at end of file
diff --git a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
index afbeb4f..2eb8f21 100644
--- a/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
+++ b/runtime/kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
@@ -17,10 +17,7 @@
 package org.apache.camel.k.kotlin
 
 import org.apache.camel.builder.RouteBuilder
-import org.apache.camel.k.jvm.Language
-import org.apache.camel.k.jvm.RoutesLoader
-import org.apache.camel.k.jvm.RuntimeRegistry
-import org.apache.camel.k.jvm.URIResolver
+import org.apache.camel.k.jvm.*
 import org.apache.camel.k.kotlin.dsl.IntegrationConfiguration
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
@@ -45,7 +42,7 @@ class KotlinRoutesLoader : RoutesLoader {
     }
 
     @Throws(Exception::class)
-    override fun load(registry: RuntimeRegistry, resource: String): RouteBuilder {
+    override fun load(registry: RuntimeRegistry, source: Source): RouteBuilder? {
         return object : RouteBuilder() {
             @Throws(Exception::class)
             override fun configure() {
@@ -57,7 +54,7 @@ class KotlinRoutesLoader : RoutesLoader {
 
                 LOGGER.info("JAVA_HOME is set to {}", javaHome)
 
-                URIResolver.resolve(context, resource).use { `is` ->
+                URIResolver.resolve(context, source.location).use { `is` ->
                     val result = host.eval(
                         InputStreamReader(`is`).readText().toScriptSource(),
                         ScriptCompilationConfiguration {
diff --git a/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
index 00dfcea..0783b27 100644
--- a/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
+++ b/runtime/kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
@@ -18,6 +18,7 @@ package org.apache.camel.k.kotlin
 
 import org.apache.camel.k.jvm.RoutesLoaders
 import org.apache.camel.k.jvm.SimpleRuntimeRegistry
+import org.apache.camel.k.jvm.Source
 import org.apache.camel.model.ProcessDefinition
 import org.apache.camel.model.ToDefinition
 import org.assertj.core.api.Assertions.assertThat
@@ -27,9 +28,9 @@ class LoaderTest {
 
     @Test
     fun `load route from classpath`() {
-        val resource = "classpath:routes.kts"
-        val loader = RoutesLoaders.loaderFor(resource, null)
-        val builder = loader.load(SimpleRuntimeRegistry(), resource)
+        var source = Source.create("classpath:routes.kts")
+        val loader = RoutesLoaders.loaderFor(source)
+        val builder = loader.load(SimpleRuntimeRegistry(), source)
 
         assertThat(loader).isInstanceOf(KotlinRoutesLoader::class.java)
         assertThat(builder).isNotNull()
diff --git a/runtime/spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java b/runtime/spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
index 9ff694c..0fe24ff 100644
--- a/runtime/spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
+++ b/runtime/spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
@@ -27,10 +27,10 @@ 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.k.jvm.RuntimeSupport;
+import org.apache.camel.k.jvm.Source;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
 import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.URISupport;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.SpringApplication;
@@ -74,11 +74,10 @@ public class Application {
     }
 
     @Bean
-    public RouteBuilder routes(ConfigurableApplicationContext applicationContext) throws Exception {
-        return new RouteBuilder() {
+    public CamelContextConfiguration routesConfiguration(ConfigurableApplicationContext applicationContext) throws Exception {
+        return new CamelContextConfiguration() {
             @Override
-            public void configure() throws Exception {
-                final CamelContext context = getContext();
+            public void beforeApplicationStart(CamelContext context) {
                 final RuntimeRegistry registry = new RuntimeApplicationContextRegistry(applicationContext, context.getRegistry());
                 final String routes = System.getenv(Constants.ENV_CAMEL_K_ROUTES);
 
@@ -86,25 +85,28 @@ public class Application {
                     throw new IllegalStateException("No valid routes found in " + Constants.ENV_CAMEL_K_ROUTES + " environment variable");
                 }
 
-                for (String route: routes.split(",")) {
-                    // determine location and language
-                    final String location = StringUtils.substringBefore(route, "?");
-                    final String query = StringUtils.substringAfter(route, "?");
-                    final String language = (String) URISupport.parseQuery(query).get("language");
+                try {
+                    for (String route : routes.split(",")) {
+                        final Source source = Source.create(route);
+                        final RoutesLoader loader = RoutesLoaders.loaderFor(source);
+                        final RouteBuilder builder = loader.load(registry, source);
 
-                    // load routes
-                    final RoutesLoader loader = RoutesLoaders.loaderFor(location, language);
-                    final RouteBuilder builder = loader.load(registry, location);
+                        if (builder == null) {
+                            throw new IllegalStateException("Unable to load route from: " + route);
+                        }
 
-                    if (builder == null) {
-                        throw new IllegalStateException("Unable to load route from: " + route);
-                    }
-
-                    LOGGER.info("Routes: {}", route);
+                        LOGGER.info("Routes: {}", route);
 
-                    context.addRoutes(builder);
+                        context.addRoutes(builder);
+                    }
+                } catch (Exception e) {
+                    throw new IllegalStateException(e);
                 }
             }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+            }
         };
     }
 
@@ -142,25 +144,6 @@ public class Application {
         public <T> Set<T> findByType(Class<T> type) {
             return registry.findByType(type);
         }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public Object lookup(String name) {
-            return registry.lookup(name);
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public <T> T lookup(String name, Class<T> type) {
-            return registry.lookup(name, type);
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public <T> Map<String, T> lookupByType(Class<T> type) {
-            return registry.lookupByType(type);
-        }
-
         @Override
         public void bind(String name, Object bean) {
             applicationContext.getBeanFactory().registerSingleton(name, bean);