You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/03/28 10:39:31 UTC

[camel] branch main updated (0cc2688 -> dcb4860)

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

davsclaus pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 0cc2688  Regen for commit 8716cbaaf790f83fc2a1bedc2f16c47c32e5c4a5
     new 8f142df  CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.
     new dcb4860  CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../camel/spi/ExtendedRoutesBuilderLoader.java     | 21 +++++++
 .../ResourceAware.java}                            | 28 +++++----
 .../camel/impl/engine/DefaultRoutesLoader.java     | 50 ++++++++++------
 .../org/apache/camel/builder/RouteBuilder.java     |  3 +-
 .../org/apache/camel/model/RouteDefinition.java    |  4 +-
 .../org/apache/camel/model/RoutesDefinition.java   |  3 +-
 .../apache/camel/main/DefaultRoutesCollector.java  | 46 +++++++--------
 .../org/apache/camel/support/ResourceSupport.java  |  7 ++-
 .../ExtendedRouteBuilderLoaderSupport.java}        | 31 ++++++----
 .../dsl/java/joor/JavaRoutesBuilderLoader.java     | 66 +++++++++++++++-------
 10 files changed, 173 insertions(+), 86 deletions(-)
 create mode 100644 core/camel-api/src/main/java/org/apache/camel/spi/ExtendedRoutesBuilderLoader.java
 copy core/camel-api/src/main/java/org/apache/camel/{health/HealthCheckAware.java => spi/ResourceAware.java} (61%)
 copy dsl/{camel-endpointdsl-support/src/main/java/org/apache/camel/endpointdsl/support/EndpointRouteBuilderLoaderSupport.java => camel-dsl-support/src/main/java/org/apache/camel/dsl/support/ExtendedRouteBuilderLoaderSupport.java} (52%)

[camel] 02/02: CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit dcb48602cac822360e1392ef551e8dbb32534a16
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 28 12:29:07 2022 +0200

    CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.
---
 .../apache/camel/main/DefaultRoutesCollector.java  | 46 +++++++++++-----------
 .../org/apache/camel/support/ResourceSupport.java  |  7 +++-
 .../dsl/java/joor/JavaRoutesBuilderLoader.java     | 12 +++++-
 3 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
index 3684825..4035e30 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
@@ -140,45 +140,45 @@ public class DefaultRoutesCollector implements RoutesCollector {
         final String[] includes = includePattern != null ? includePattern.split(",") : null;
         final String[] excludes = excludePattern != null ? excludePattern.split(",") : null;
 
-        if (includes == null) {
-            log.debug("Include patter is empty, no routes will be discovered from resources");
+        if (includes == null || ObjectHelper.equal("false", includePattern)) {
+            log.debug("Include pattern is empty/false, no routes will be discovered from resources");
             return answer;
         }
 
         StopWatch watch = new StopWatch();
-
-        if (ObjectHelper.equal("false", includePattern)) {
-            return answer;
-        }
-
+        Collection<Resource> accepted = new ArrayList<>();
         for (String include : includes) {
             log.debug("Loading additional RoutesBuilder from: {}", include);
             try {
                 for (Resource resource : resolver.findResources(include)) {
+                    // filter unwanted resources
                     if (!"false".equals(excludePattern) && AntPathMatcher.INSTANCE.anyMatch(excludes, resource.getLocation())) {
                         continue;
                     }
-
-                    Collection<RoutesBuilder> builders = ecc.getRoutesLoader().findRoutesBuilders(resource);
-                    if (builders.isEmpty()) {
-                        continue;
-                    }
-
-                    log.debug("Found {} route builder from location: {}", builders.size(), include);
-                    answer.addAll(builders);
+                    accepted.add(resource);
                 }
-            } catch (FileNotFoundException e) {
-                log.debug("No RoutesBuilder found in {}. Skipping detection.", include);
             } catch (Exception e) {
                 throw RuntimeCamelException.wrapRuntimeException(e);
             }
-            if (!answer.isEmpty()) {
-                log.debug("Loaded {} ({} millis) additional RoutesBuilder from: {}, pattern: {}", answer.size(), watch.taken(),
-                        include,
-                        includePattern);
-            } else {
-                log.debug("No additional RoutesBuilder discovered from: {}", includePattern);
+        }
+
+        try {
+            Collection<RoutesBuilder> builders = ecc.getRoutesLoader().findRoutesBuilders(accepted);
+            if (!builders.isEmpty()) {
+                log.debug("Found {} route builder from locations: {}", builders.size(), includes);
+                answer.addAll(builders);
             }
+        } catch (FileNotFoundException e) {
+            log.debug("No RoutesBuilder found in {}. Skipping detection.", includes);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeException(e);
+        }
+        if (!answer.isEmpty()) {
+            log.debug("Loaded {} ({} millis) additional RoutesBuilder from: {}, pattern: {}", answer.size(), watch.taken(),
+                    includes,
+                    includePattern);
+        } else {
+            log.debug("No additional RoutesBuilder discovered from: {}", includePattern);
         }
 
         return answer;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ResourceSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/ResourceSupport.java
index cbab7dd..5d49b00 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ResourceSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ResourceSupport.java
@@ -42,6 +42,11 @@ public abstract class ResourceSupport implements Resource {
 
     @Override
     public String toString() {
-        return "Resource[" + scheme + ":" + location + "]";
+        String prefix = scheme + ":";
+        if (location.startsWith(prefix)) {
+            return "Resource[" + location + "]";
+        } else {
+            return "Resource[" + prefix + location + "]";
+        }
     }
 }
diff --git a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
index a5d1d26..5ab24d6 100644
--- a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
+++ b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
@@ -36,14 +36,19 @@ import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
 import org.joor.Reflect;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @ManagedResource(description = "Managed JavaRoutesBuilderLoader")
 @RoutesLoader(JavaRoutesBuilderLoader.EXTENSION)
 public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
+
     public static final String EXTENSION = "java";
     public static final Pattern PACKAGE_PATTERN = Pattern.compile(
             "^\\s*package\\s+([a-zA-Z][\\.\\w]*)\\s*;.*$", Pattern.MULTILINE);
 
+    private static final Logger LOG = LoggerFactory.getLogger(JavaRoutesBuilderLoader.class);
+
     public JavaRoutesBuilderLoader() {
         super(EXTENSION);
     }
@@ -52,7 +57,10 @@ public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
     protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
         Collection<RoutesBuilder> answer = new ArrayList<>();
 
-        // TODO: when joor supports compiling in one unit
+        LOG.debug("Loading .java resources from: {}", resources);
+
+        // CAMEL-17784: joor to support compiling in one unit, then we can compile all resources at once
+
         for (Resource resource : resources) {
             try (InputStream is = resource.getInputStream()) {
                 if (is == null) {
@@ -61,9 +69,11 @@ public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
                 String content = IOHelper.loadText(is);
                 String name = determineName(resource, content);
 
+                LOG.debug("Compiling: {}", name);
                 Reflect ref = Reflect.compile(name, content).create();
                 Class<?> clazz = ref.type();
                 Object obj = ref.get();
+                LOG.debug("Compiled: {} -> {}", name, obj);
 
                 // inject context and resource
                 CamelContextAware.trySetCamelContext(obj, getCamelContext());

[camel] 01/02: CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8f142df68a6859f2c78b79369da58874ab09e31e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 28 11:57:10 2022 +0200

    CAMEL-17784: ExtendedRoutesBuilderLoader SPI which allows routes loader to load multiple routes in the same unit. In preparation for camel-java-joor-dsl to compile all java sources together.
---
 .../camel/spi/ExtendedRoutesBuilderLoader.java     | 21 ++++++++
 .../java/org/apache/camel/spi/ResourceAware.java   | 44 +++++++++++++++++
 .../camel/impl/engine/DefaultRoutesLoader.java     | 50 ++++++++++++-------
 .../org/apache/camel/builder/RouteBuilder.java     |  3 +-
 .../org/apache/camel/model/RouteDefinition.java    |  4 +-
 .../org/apache/camel/model/RoutesDefinition.java   |  3 +-
 .../support/ExtendedRouteBuilderLoaderSupport.java | 51 ++++++++++++++++++++
 .../dsl/java/joor/JavaRoutesBuilderLoader.java     | 56 ++++++++++++++--------
 8 files changed, 193 insertions(+), 39 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ExtendedRoutesBuilderLoader.java b/core/camel-api/src/main/java/org/apache/camel/spi/ExtendedRoutesBuilderLoader.java
new file mode 100644
index 0000000..3c3a016
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ExtendedRoutesBuilderLoader.java
@@ -0,0 +1,21 @@
+package org.apache.camel.spi;
+
+import java.util.Collection;
+
+import org.apache.camel.RoutesBuilder;
+
+/**
+ * An extended {@link RoutesBuilderLoader} that is capable of loading from multiple resources in one unit (such as
+ * compiling them together).
+ */
+public interface ExtendedRoutesBuilderLoader extends RoutesBuilderLoader {
+
+    /**
+     * Loads {@link RoutesBuilder} from multiple {@link Resource}s.
+     *
+     * @param  resources the resources to be loaded.
+     * @return           a set of loaded {@link RoutesBuilder}s
+     */
+    Collection<RoutesBuilder> loadRoutesBuilders(Collection<Resource> resources) throws Exception;
+
+}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ResourceAware.java b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceAware.java
new file mode 100644
index 0000000..f02b8dc
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ResourceAware.java
@@ -0,0 +1,44 @@
+/*
+ * 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.spi;
+
+/**
+ * An interface to represent an object which wishes to be injected with the {@link Resource}
+ */
+public interface ResourceAware {
+
+    /**
+     * Set the {@link Resource} resource if the object is an instance of {@link ResourceAware}.
+     */
+    static <T> T trySetResource(T object, Resource resource) {
+        if (resource != null && object instanceof ResourceAware) {
+            ((ResourceAware) object).setResource(resource);
+        }
+
+        return object;
+    }
+
+    /**
+     * Gets the {@link Resource}.
+     */
+    Resource getResource();
+
+    /**
+     * Sets the {@link Resource}.
+     */
+    void setResource(Resource resource);
+}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
index 0f4737f..4ff9f39 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
@@ -18,6 +18,7 @@ package org.apache.camel.impl.engine;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +30,7 @@ import org.apache.camel.CamelContextAware;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.StaticService;
+import org.apache.camel.spi.ExtendedRoutesBuilderLoader;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.ModelineFactory;
 import org.apache.camel.spi.Resource;
@@ -86,20 +88,44 @@ public class DefaultRoutesLoader extends ServiceSupport implements RoutesLoader,
     public Collection<RoutesBuilder> findRoutesBuilders(Collection<Resource> resources) throws Exception {
         List<RoutesBuilder> answer = new ArrayList<>(resources.size());
 
-        for (Resource resource : resources) {
-            RoutesBuilderLoader loader = resolveRoutesBuilderLoader(resource);
-
-            if (camelContext.isModeline()) {
-                ModelineFactory factory = camelContext.adapt(ExtendedCamelContext.class).getModelineFactory();
+        // first we need to parse for modeline to gather all the configurations
+        if (camelContext.isModeline()) {
+            ModelineFactory factory = camelContext.adapt(ExtendedCamelContext.class).getModelineFactory();
+            for (Resource resource : resources) {
+                RoutesBuilderLoader loader = resolveRoutesBuilderLoader(resource);
                 // gather resources for modeline
                 factory.parseModeline(resource);
                 // pre-parse before loading
                 loader.preParseRoute(resource);
             }
+        }
+
+        // now group resources by loader
+        Map<RoutesBuilderLoader, List<Resource>> groups = new LinkedHashMap<>();
+        for (Resource resource : resources) {
+            RoutesBuilderLoader loader = resolveRoutesBuilderLoader(resource);
+            List<Resource> list = groups.getOrDefault(loader, new ArrayList<Resource>());
+            list.add(resource);
+            groups.put(loader, list);
+        }
 
-            RoutesBuilder builder = loader.loadRoutesBuilder(resource);
-            if (builder != null) {
-                answer.add(builder);
+        // now load all the same resources for each loader
+        for (Map.Entry<RoutesBuilderLoader, List<Resource>> entry : groups.entrySet()) {
+            RoutesBuilderLoader loader = entry.getKey();
+            if (loader instanceof ExtendedRoutesBuilderLoader) {
+                // extended loader can load all resources ine one unit
+                ExtendedRoutesBuilderLoader extLoader = (ExtendedRoutesBuilderLoader) loader;
+                Collection<RoutesBuilder> builders = extLoader.loadRoutesBuilders(entry.getValue());
+                if (builders != null) {
+                    answer.addAll(builders);
+                }
+            } else {
+                for (Resource resource : entry.getValue()) {
+                    RoutesBuilder builder = loader.loadRoutesBuilder(resource);
+                    if (builder != null) {
+                        answer.add(builder);
+                    }
+                }
             }
         }
 
@@ -156,14 +182,6 @@ public class DefaultRoutesLoader extends ServiceSupport implements RoutesLoader,
         Set<String> answer = new LinkedHashSet<>();
         Collection<RoutesBuilder> builders = findRoutesBuilders(resources);
 
-        if (camelContext.isModeline()) {
-            ModelineFactory factory = camelContext.adapt(ExtendedCamelContext.class).getModelineFactory();
-            // gather resources for modeline
-            for (Resource resource : resources) {
-                factory.parseModeline(resource);
-            }
-        }
-
         for (RoutesBuilder builder : builders) {
             // update any existing routes
             Set<String> ids = builder.updateRoutesToCamelContext(getCamelContext());
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index 26411e97..d661d53 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -51,6 +51,7 @@ import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.OnCamelContextEvent;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceAware;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.support.LifecycleStrategySupport;
 import org.apache.camel.util.ObjectHelper;
@@ -64,7 +65,7 @@ import org.slf4j.LoggerFactory;
  * A <a href="http://camel.apache.org/dsl.html">Java DSL</a> which is used to build {@link Route} instances in a
  * {@link CamelContext} for smart routing.
  */
-public abstract class RouteBuilder extends BuilderSupport implements RoutesBuilder, Ordered {
+public abstract class RouteBuilder extends BuilderSupport implements RoutesBuilder, Ordered, ResourceAware {
     protected Logger log = LoggerFactory.getLogger(getClass());
 
     private Resource resource;
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index c7e2d3e..a0bd0c2 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -48,6 +48,7 @@ import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceAware;
 import org.apache.camel.spi.RoutePolicy;
 
 /**
@@ -58,7 +59,8 @@ import org.apache.camel.spi.RoutePolicy;
 @XmlType(propOrder = { "input", "inputType", "outputType", "outputs", "routeProperties" })
 @XmlAccessorType(XmlAccessType.PROPERTY)
 // must use XmlAccessType.PROPERTY as there is some custom logic needed to be executed in the setter methods
-public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute, PreconditionContainer {
+public class RouteDefinition extends OutputDefinition<RouteDefinition>
+        implements NamedRoute, PreconditionContainer, ResourceAware {
     private final AtomicBoolean prepared = new AtomicBoolean();
     private FromDefinition input;
     private String routeConfigurationId;
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 2ce18c6..f53235d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -33,6 +33,7 @@ import org.apache.camel.builder.EndpointConsumerBuilder;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceAware;
 import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.PatternHelper;
 import org.slf4j.Logger;
@@ -45,7 +46,7 @@ import org.slf4j.LoggerFactory;
 @XmlRootElement(name = "routes")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinition>
-        implements RouteContainer, CamelContextAware {
+        implements RouteContainer, CamelContextAware, ResourceAware {
 
     private static final Logger LOG = LoggerFactory.getLogger(RoutesDefinition.class);
 
diff --git a/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/ExtendedRouteBuilderLoaderSupport.java b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/ExtendedRouteBuilderLoaderSupport.java
new file mode 100644
index 0000000..870df61
--- /dev/null
+++ b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/ExtendedRouteBuilderLoaderSupport.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.dsl.support;
+
+import java.util.Collection;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.ExtendedRoutesBuilderLoader;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.RoutesBuilderLoader;
+
+/**
+ * Base class for {@link RoutesBuilderLoader} implementations.
+ */
+public abstract class ExtendedRouteBuilderLoaderSupport extends RouteBuilderLoaderSupport
+        implements ExtendedRoutesBuilderLoader {
+
+    protected ExtendedRouteBuilderLoaderSupport(String extension) {
+        super(extension);
+    }
+
+    @Override
+    protected RouteBuilder doLoadRouteBuilder(Resource resource) throws Exception {
+        // noop
+        return null;
+    }
+
+    @Override
+    public Collection<RoutesBuilder> loadRoutesBuilders(Collection<Resource> resources) throws Exception {
+        Collection<RoutesBuilder> answer = doLoadRoutesBuilders(resources);
+        return answer;
+    }
+
+    protected abstract Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception;
+
+}
diff --git a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
index c29e54d..a5d1d26 100644
--- a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
+++ b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
@@ -18,14 +18,19 @@ package org.apache.camel.dsl.java.joor;
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.RoutesBuilder;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.dsl.support.CompilePostProcessor;
-import org.apache.camel.dsl.support.RouteBuilderLoaderSupport;
+import org.apache.camel.dsl.support.ExtendedRouteBuilderLoaderSupport;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.ResourceAware;
 import org.apache.camel.spi.annotations.RoutesLoader;
 import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.util.FileUtil;
@@ -34,7 +39,7 @@ import org.joor.Reflect;
 
 @ManagedResource(description = "Managed JavaRoutesBuilderLoader")
 @RoutesLoader(JavaRoutesBuilderLoader.EXTENSION)
-public class JavaRoutesBuilderLoader extends RouteBuilderLoaderSupport {
+public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
     public static final String EXTENSION = "java";
     public static final Pattern PACKAGE_PATTERN = Pattern.compile(
             "^\\s*package\\s+([a-zA-Z][\\.\\w]*)\\s*;.*$", Pattern.MULTILINE);
@@ -44,29 +49,40 @@ public class JavaRoutesBuilderLoader extends RouteBuilderLoaderSupport {
     }
 
     @Override
-    public RouteBuilder doLoadRouteBuilder(Resource resource) throws Exception {
-        try (InputStream is = resource.getInputStream()) {
-            if (is == null) {
-                throw new FileNotFoundException(resource.getLocation());
-            }
-            String content = IOHelper.loadText(is);
-            String name = determineName(resource, content);
+    protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
+        Collection<RoutesBuilder> answer = new ArrayList<>();
 
-            Reflect ref = Reflect.compile(name, content).create();
-            Class<?> clazz = ref.type();
-            Object obj = ref.get();
+        // TODO: when joor supports compiling in one unit
+        for (Resource resource : resources) {
+            try (InputStream is = resource.getInputStream()) {
+                if (is == null) {
+                    throw new FileNotFoundException(resource.getLocation());
+                }
+                String content = IOHelper.loadText(is);
+                String name = determineName(resource, content);
 
-            // support custom annotation scanning post compilation
-            // such as to register custom beans, type converters, etc.
-            for (CompilePostProcessor pre : getCompilePostProcessors()) {
-                pre.postCompile(getCamelContext(), name, clazz, obj);
-            }
+                Reflect ref = Reflect.compile(name, content).create();
+                Class<?> clazz = ref.type();
+                Object obj = ref.get();
+
+                // inject context and resource
+                CamelContextAware.trySetCamelContext(obj, getCamelContext());
+                ResourceAware.trySetResource(obj, resource);
 
-            if (obj instanceof RouteBuilder) {
-                return (RouteBuilder) obj;
+                // support custom annotation scanning post compilation
+                // such as to register custom beans, type converters, etc.
+                for (CompilePostProcessor pre : getCompilePostProcessors()) {
+                    pre.postCompile(getCamelContext(), name, clazz, obj);
+                }
+
+                if (obj instanceof RouteBuilder) {
+                    RouteBuilder builder = (RouteBuilder) obj;
+                    answer.add(builder);
+                }
             }
-            return null;
         }
+
+        return answer;
     }
 
     private static String determineName(Resource resource, String content) {