You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2021/02/03 12:14:23 UTC

[camel] 01/04: CAMEL-15560: generic route loader

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

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

commit 9ce4322e19f88022c37c1af3e4bd38caf127a2d5
Author: Luca Burgazzoli <lb...@gmail.com>
AuthorDate: Tue Feb 2 12:34:56 2021 +0100

    CAMEL-15560: generic route loader
---
 .../java/org/apache/camel/CamelContextAware.java   |  35 ++-
 .../org/apache/camel/ExtendedCamelContext.java     |  14 ++
 .../main/java/org/apache/camel/spi/Resource.java   |  30 +++
 .../{Resource.java => RoutesBuilderLoader.java}    |  20 +-
 .../camel/spi/XMLRoutesDefinitionLoader.java       |   3 +
 .../camel/impl/engine/AbstractCamelContext.java    |  23 ++
 .../apache/camel/impl/engine/DefaultResource.java  |   7 +
 .../impl/engine/DefaultRoutesBuilderLoader.java    |  88 +++++++
 .../camel/impl/engine/SimpleCamelContext.java      |   6 +
 .../camel/impl/ExtendedCamelContextConfigurer.java |   6 +
 .../camel/impl/lw/LightweightCamelContext.java     |  11 +
 .../impl/lw/LightweightRuntimeCamelContext.java    |  11 +
 .../DefaultPackageScanResourceResolverTest.java    |  39 ++-
 .../apache/camel/model/LoadRestFromXmlTest.java    |  33 ++-
 .../apache/camel/model/LoadRouteFromXmlTest.java   |  34 ++-
 .../MainConfigurationPropertiesConfigurer.java     |  30 +--
 .../camel-main-configuration-metadata.json         |   5 +-
 core/camel-main/src/main/docs/main.adoc            |   5 +-
 .../org/apache/camel/main/BaseMainSupport.java     |  47 +---
 .../camel/main/DefaultConfigurationConfigurer.java |   2 +-
 .../camel/main/DefaultConfigurationProperties.java | 276 ++++++++++++---------
 .../apache/camel/main/DefaultRoutesCollector.java  | 152 +++---------
 .../org/apache/camel/main/RoutesCollector.java     |  39 +--
 .../org/apache/camel/main/RoutesConfigurer.java    | 131 +++++-----
 .../main/support/MockRestConsumerFactory.java}     |  38 +--
 .../apache/camel/main/xml/MainXmlRestsTest.java    |  63 +++--
 .../apache/camel/main/xml/MainXmlTemplateTest.java |  38 ++-
 .../org/apache/camel/main/xml/MainXmlTest.java     |  41 ++-
 .../management/mbean/ManagedCamelContextMBean.java |   2 +
 .../api/management/mbean/ManagedRouteMBean.java    |   1 +
 .../java/org/apache/camel/util/AntPathMatcher.java |  25 +-
 .../services/org/apache/camel/routes-loaders/xml   |   2 +
 .../camel/xml/in/XmlRoutesBuilderLoader.java       |  74 ++++++
 .../services/org/apache/camel/routes-loaders/xml   |   2 +
 .../java/org/apache/camel/xml/jaxb/JaxbHelper.java | 103 ++++++++
 .../xml/jaxb/JaxbXMLRoutesDefinitionLoader.java    | 114 +--------
 .../camel/xml/jaxb/JaxbXmlRoutesBuilderLoader.java |  72 ++++++
 .../src/main/resources/META-INF/LICENSE.txt        | 203 +++++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  15 ++
 39 files changed, 1205 insertions(+), 635 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContextAware.java b/core/camel-api/src/main/java/org/apache/camel/CamelContextAware.java
index 6d30d56..abbe2e0 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContextAware.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContextAware.java
@@ -22,11 +22,15 @@ package org.apache.camel;
 public interface CamelContextAware {
 
     /**
-     * Injects the {@link CamelContext}
-     *
-     * @param camelContext the Camel context
+     * Set the {@link CamelContext} context if the object is an instance of {@link CamelContextAware}.
      */
-    void setCamelContext(CamelContext camelContext);
+    static <T> T trySetCamelContext(T object, CamelContext camelContext) {
+        if (object instanceof CamelContextAware) {
+            ((CamelContextAware) object).setCamelContext(camelContext);
+        }
+
+        return object;
+    }
 
     /**
      * Get the {@link CamelContext}
@@ -36,14 +40,27 @@ public interface CamelContextAware {
     CamelContext getCamelContext();
 
     /**
-     * Set the {@link CamelContext} context if the object is an instance of {@link CamelContextAware}.
+     * Injects the {@link CamelContext}
+     *
+     * @param camelContext the Camel context
      */
-    static <T> T trySetCamelContext(T object, CamelContext camelContext) {
-        if (object instanceof CamelContextAware) {
-            ((CamelContextAware) object).setCamelContext(camelContext);
+    void setCamelContext(CamelContext camelContext);
+
+    /**
+     * Get the {@link CamelContext} adapted to the specialized type.
+     * <p/>
+     *
+     * @param  type the type to adapt to
+     * @return      this {@link CamelContext} adapted to the given type
+     *
+     * @see         CamelContext#adapt(Class)
+     */
+    default <T extends CamelContext> T getCamelContext(Class<T> type) {
+        if (getCamelContext() == null) {
+            return null;
         }
 
-        return object;
+        return getCamelContext().adapt(type);
     }
 
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index 6a392ad..6934821 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -59,6 +59,7 @@ import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteFactory;
 import org.apache.camel.spi.RouteStartupOrder;
+import org.apache.camel.spi.RoutesBuilderLoader;
 import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.UnitOfWorkFactory;
 import org.apache.camel.spi.UriFactoryResolver;
@@ -599,10 +600,23 @@ public interface ExtendedCamelContext extends CamelContext {
 
     /**
      * Gets the {@link XMLRoutesDefinitionLoader} to be used.
+     *
+     * @deprecated use {@link #getRoutesBuilderLoader()}
      */
+    @Deprecated
     XMLRoutesDefinitionLoader getXMLRoutesDefinitionLoader();
 
     /**
+     * Sets a custom {@link RoutesBuilderLoader} to be used.
+     */
+    void setRoutesBuilderLoader(RoutesBuilderLoader routesBuilderLoader);
+
+    /**
+     * Gets the {@link RoutesBuilderLoader} to be used.
+     */
+    RoutesBuilderLoader getRoutesBuilderLoader();
+
+    /**
      * Sets a custom {@link ModelToXMLDumper} to be used.
      */
     void setModelToXMLDumper(ModelToXMLDumper modelToXMLDumper);
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java b/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
index 60298b8..bcfb8f0 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
@@ -34,4 +34,34 @@ public interface Resource {
      * Each invocation must return a new {@link InputStream} instance.
      */
     InputStream getInputStream() throws IOException;
+
+    /**
+     * Finds a resource with a given name.
+     *
+     * @see Class#getResourceAsStream(String)
+     *
+     */
+    static Resource fromClasspath(String location) {
+        return fromClasspath(Resource.class, location);
+    }
+
+    /**
+     * Finds a resource with a given name.
+     *
+     * @see Class#getResourceAsStream(String)
+     *
+     */
+    static Resource fromClasspath(Class<?> type, String location) {
+        return new Resource() {
+            @Override
+            public String getLocation() {
+                return location;
+            }
+
+            @Override
+            public InputStream getInputStream() throws IOException {
+                return type.getResourceAsStream(location);
+            }
+        };
+    }
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
similarity index 62%
copy from core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
copy to core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
index 60298b8..0f844bc 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
@@ -16,22 +16,22 @@
  */
 package org.apache.camel.spi;
 
-import java.io.IOException;
-import java.io.InputStream;
+import org.apache.camel.RoutesBuilder;
 
 /**
- * Describe a resource, such as a file or class path resource.
+ * SPI for loading {@link RoutesBuilder} from a {@link Resource}.
  */
-public interface Resource {
+public interface RoutesBuilderLoader {
     /**
-     * The location of the resource.
+     * Service factory base path for language specific loaders.
      */
-    String getLocation();
+    String LOADERS_FACTORY_PATH = "META-INF/services/org/apache/camel/routes-loaders/";
 
     /**
-     * Returns an input stream that reads from the underlying resource.
-     * </p>
-     * Each invocation must return a new {@link InputStream} instance.
+     * Loads {@link RoutesBuilder} from {@link Resource}.
+     *
+     * @param  resource the resource to be loaded.
+     * @return          a {@link RoutesBuilder}
      */
-    InputStream getInputStream() throws IOException;
+    RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception;
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/XMLRoutesDefinitionLoader.java b/core/camel-api/src/main/java/org/apache/camel/spi/XMLRoutesDefinitionLoader.java
index 581025e..ab3f1e8 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/XMLRoutesDefinitionLoader.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/XMLRoutesDefinitionLoader.java
@@ -22,7 +22,10 @@ import org.apache.camel.CamelContext;
 
 /**
  * SPI for loading routes/rests from XML input streams and parsing this to model definition classes.
+ *
+ * @deprecated sue {@link RoutesBuilderLoader}
  */
+@Deprecated
 public interface XMLRoutesDefinitionLoader {
 
     /**
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 7866ac0..89d3828 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -141,6 +141,7 @@ import org.apache.camel.spi.RouteFactory;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RouteStartupOrder;
 import org.apache.camel.spi.RouteTemplateParameterSource;
+import org.apache.camel.spi.RoutesBuilderLoader;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
@@ -283,6 +284,7 @@ public abstract class AbstractCamelContext extends BaseService
     private volatile BeanProxyFactory beanProxyFactory;
     private volatile BeanProcessorFactory beanProcessorFactory;
     private volatile XMLRoutesDefinitionLoader xmlRoutesDefinitionLoader;
+    private volatile RoutesBuilderLoader routesBuilderLoader;
     private volatile ModelToXMLDumper modelToXMLDumper;
     private volatile RestBindingJaxbDataFormatFactory restBindingJaxbDataFormatFactory;
     private volatile RuntimeCamelCatalog runtimeCamelCatalog;
@@ -4536,6 +4538,7 @@ public abstract class AbstractCamelContext extends BaseService
         this.headersMapFactory = doAddService(headersMapFactory);
     }
 
+    @Override
     public XMLRoutesDefinitionLoader getXMLRoutesDefinitionLoader() {
         if (xmlRoutesDefinitionLoader == null) {
             synchronized (lock) {
@@ -4547,10 +4550,28 @@ public abstract class AbstractCamelContext extends BaseService
         return xmlRoutesDefinitionLoader;
     }
 
+    @Override
     public void setXMLRoutesDefinitionLoader(XMLRoutesDefinitionLoader xmlRoutesDefinitionLoader) {
         this.xmlRoutesDefinitionLoader = doAddService(xmlRoutesDefinitionLoader);
     }
 
+    @Override
+    public RoutesBuilderLoader getRoutesBuilderLoader() {
+        if (routesBuilderLoader == null) {
+            synchronized (lock) {
+                if (routesBuilderLoader == null) {
+                    setRoutesBuilderLoader(createRoutesBuilderLoader());
+                }
+            }
+        }
+        return routesBuilderLoader;
+    }
+
+    @Override
+    public void setRoutesBuilderLoader(RoutesBuilderLoader routesBuilderLoader) {
+        this.routesBuilderLoader = doAddService(routesBuilderLoader);
+    }
+
     public ModelToXMLDumper getModelToXMLDumper() {
         if (modelToXMLDumper == null) {
             synchronized (lock) {
@@ -4768,6 +4789,8 @@ public abstract class AbstractCamelContext extends BaseService
 
     protected abstract XMLRoutesDefinitionLoader createXMLRoutesDefinitionLoader();
 
+    protected abstract RoutesBuilderLoader createRoutesBuilderLoader();
+
     protected abstract ModelToXMLDumper createModelToXMLDumper();
 
     protected abstract RestBindingJaxbDataFormatFactory createRestBindingJaxbDataFormatFactory();
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java
index 9fa2c51..437a303 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultResource.java
@@ -59,4 +59,11 @@ public class DefaultResource implements Resource {
     public int hashCode() {
         return Objects.hash(getLocation());
     }
+
+    @Override
+    public String toString() {
+        return "DefaultResource{" +
+               "location='" + location + '\'' +
+               '}';
+    }
 }
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesBuilderLoader.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesBuilderLoader.java
new file mode 100644
index 0000000..007ec35
--- /dev/null
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesBuilderLoader.java
@@ -0,0 +1,88 @@
+/*
+ * 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.impl.engine;
+
+import java.util.Optional;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.spi.FactoryFinderResolver;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.RoutesBuilderLoader;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.ObjectHelper;
+
+public class DefaultRoutesBuilderLoader implements RoutesBuilderLoader, CamelContextAware {
+    private CamelContext camelContext;
+
+    public DefaultRoutesBuilderLoader() {
+    }
+
+    public DefaultRoutesBuilderLoader(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception {
+        // language is derived from the file extension
+        final String language = FileUtil.onlyExt(resource.getLocation(), true);
+
+        if (ObjectHelper.isEmpty(language)) {
+            throw new IllegalArgumentException("Unable to determine language for resource: " + resource.getLocation());
+        }
+
+        return getLoader(language).loadRoutesBuilder(resource);
+    }
+
+    private RoutesBuilderLoader getLoader(String language) {
+        RoutesBuilderLoader answer = getCamelContext().getRegistry().lookupByNameAndType(language, RoutesBuilderLoader.class);
+
+        if (answer == null) {
+            final ExtendedCamelContext ecc = getCamelContext(ExtendedCamelContext.class);
+            final FactoryFinderResolver ffr = ecc.getFactoryFinderResolver();
+            final ClassResolver cr = ecc.getClassResolver();
+            final FactoryFinder finder = ffr.resolveBootstrapFactoryFinder(cr, RoutesBuilderLoader.LOADERS_FACTORY_PATH);
+
+            final BaseServiceResolver<RoutesBuilderLoader> resolver
+                    = new BaseServiceResolver<>(language, RoutesBuilderLoader.class, finder);
+            final Optional<RoutesBuilderLoader> loader
+                    = resolver.resolve(ecc);
+
+            if (loader.isPresent()) {
+                return CamelContextAware.trySetCamelContext(loader.get(), ecc);
+            } else {
+                throw new IllegalArgumentException("Unable to fina a RoutesBuilderLoader for language " + language);
+            }
+        }
+
+        return answer;
+    }
+}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 4c0918e..c998750 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -65,6 +65,7 @@ import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
 import org.apache.camel.spi.RestRegistryFactory;
 import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteFactory;
+import org.apache.camel.spi.RoutesBuilderLoader;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.Tracer;
@@ -411,6 +412,11 @@ public class SimpleCamelContext extends AbstractCamelContext {
     }
 
     @Override
+    protected RoutesBuilderLoader createRoutesBuilderLoader() {
+        return new DefaultRoutesBuilderLoader();
+    }
+
+    @Override
     protected ModelToXMLDumper createModelToXMLDumper() {
         BaseServiceResolver<ModelToXMLDumper> resolver
                 = new BaseServiceResolver<>(ModelToXMLDumper.FACTORY, ModelToXMLDumper.class, getBootstrapFactoryFinder());
diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
index 339319e..43ed602 100644
--- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
+++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
@@ -135,6 +135,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         case "RouteController": target.setRouteController(property(camelContext, org.apache.camel.spi.RouteController.class, value)); return true;
         case "routefactory":
         case "RouteFactory": target.setRouteFactory(property(camelContext, org.apache.camel.spi.RouteFactory.class, value)); return true;
+        case "routesbuilderloader":
+        case "RoutesBuilderLoader": target.setRoutesBuilderLoader(property(camelContext, org.apache.camel.spi.RoutesBuilderLoader.class, value)); return true;
         case "runtimecamelcatalog":
         case "RuntimeCamelCatalog": target.setRuntimeCamelCatalog(property(camelContext, org.apache.camel.catalog.RuntimeCamelCatalog.class, value)); return true;
         case "runtimeendpointregistry":
@@ -300,6 +302,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         case "RouteController": return org.apache.camel.spi.RouteController.class;
         case "routefactory":
         case "RouteFactory": return org.apache.camel.spi.RouteFactory.class;
+        case "routesbuilderloader":
+        case "RoutesBuilderLoader": return org.apache.camel.spi.RoutesBuilderLoader.class;
         case "runtimecamelcatalog":
         case "RuntimeCamelCatalog": return org.apache.camel.catalog.RuntimeCamelCatalog.class;
         case "runtimeendpointregistry":
@@ -466,6 +470,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com
         case "RouteController": return target.getRouteController();
         case "routefactory":
         case "RouteFactory": return target.getRouteFactory();
+        case "routesbuilderloader":
+        case "RoutesBuilderLoader": return target.getRoutesBuilderLoader();
         case "runtimecamelcatalog":
         case "RuntimeCamelCatalog": return target.getRuntimeCamelCatalog();
         case "runtimeendpointregistry":
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 8e9ed83..6cb4d71 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -123,6 +123,7 @@ import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteFactory;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RouteStartupOrder;
+import org.apache.camel.spi.RoutesBuilderLoader;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
@@ -1465,6 +1466,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public void setRoutesBuilderLoader(RoutesBuilderLoader routesBuilderLoader) {
+        getExtendedCamelContext().setRoutesBuilderLoader(routesBuilderLoader);
+    }
+
+    @Override
+    public RoutesBuilderLoader getRoutesBuilderLoader() {
+        return getExtendedCamelContext().getRoutesBuilderLoader();
+    }
+
+    @Override
     public void setModelToXMLDumper(ModelToXMLDumper modelToXMLDumper) {
         getExtendedCamelContext().setModelToXMLDumper(modelToXMLDumper);
     }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index bac7d62..f5867e0 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -120,6 +120,7 @@ import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteFactory;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RouteStartupOrder;
+import org.apache.camel.spi.RoutesBuilderLoader;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
@@ -1751,6 +1752,16 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat
     }
 
     @Override
+    public void setRoutesBuilderLoader(RoutesBuilderLoader routesBuilderLoader) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public RoutesBuilderLoader getRoutesBuilderLoader() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void registerEndpointCallback(EndpointStrategy strategy) {
         throw new UnsupportedOperationException();
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolverTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolverTest.java
index 8a0a0df..24c08f0 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolverTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolverTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.impl.engine;
 
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -24,35 +23,32 @@ import java.util.stream.Collectors;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.spi.Resource;
-import org.apache.camel.util.IOHelper;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class DefaultPackageScanResourceResolverTest {
-    private static Set<String> loadRouteIDs(CamelContext context, String path) {
-        return loadRouteDefinitions(context, path).stream().map(RouteDefinition::getId).collect(Collectors.toSet());
+    private static Set<String> loadRouteIDs(String path) throws Exception {
+        DefaultCamelContext ctx = new DefaultCamelContext(false);
+        for (RoutesBuilder builder : loadRouteDefinitions(ctx, path)) {
+            ctx.addRoutes(builder);
+        }
+        return ctx.getRouteDefinitions().stream().map(RouteDefinition::getId).collect(Collectors.toSet());
     }
 
-    private static List<RouteDefinition> loadRouteDefinitions(CamelContext context, String path) {
-        List<RouteDefinition> answer = new ArrayList<>();
+    private static List<RoutesBuilder> loadRouteDefinitions(CamelContext context, String path) {
+        List<RoutesBuilder> answer = new ArrayList<>();
 
         ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
         try {
             for (Resource resource : ecc.getPackageScanResourceResolver().findResources(path)) {
-                InputStream is = resource.getInputStream();
-                try {
-                    RoutesDefinition routes
-                            = (RoutesDefinition) ecc.getXMLRoutesDefinitionLoader().loadRoutesDefinition(ecc, is);
-                    if (routes != null) {
-                        answer.addAll(routes.getRoutes());
-                    }
-                } finally {
-                    IOHelper.close(is);
+                RoutesBuilder builder = ecc.getRoutesBuilderLoader().loadRoutesBuilder(resource);
+                if (builder != null) {
+                    answer.add(builder);
                 }
             }
         } catch (Exception e) {
@@ -63,16 +59,15 @@ public class DefaultPackageScanResourceResolverTest {
     }
 
     @Test
-    public void testFileResourcesScan() {
-        DefaultCamelContext ctx = new DefaultCamelContext(false);
+    public void testFileResourcesScan() throws Exception {
 
-        assertThat(loadRouteIDs(ctx, "file:src/test/resources/org/apache/camel/impl/engine/**/*.xml"))
+        assertThat(loadRouteIDs("file:src/test/resources/org/apache/camel/impl/engine/**/*.xml"))
                 .containsOnly("dummy-a", "scan-a", "dummy-b", "scan-b");
-        assertThat(loadRouteIDs(ctx, "file:src/test/resources/org/apache/camel/impl/engine/a?/*.xml"))
+        assertThat(loadRouteIDs("file:src/test/resources/org/apache/camel/impl/engine/a?/*.xml"))
                 .containsOnly("dummy-a", "scan-a");
-        assertThat(loadRouteIDs(ctx, "file:src/test/resources/org/apache/camel/impl/engine/b?/*.xml"))
+        assertThat(loadRouteIDs("file:src/test/resources/org/apache/camel/impl/engine/b?/*.xml"))
                 .containsOnly("dummy-b", "scan-b");
-        assertThat(loadRouteIDs(ctx, "file:src/test/resources/org/apache/camel/impl/engine/c?/*.xml"))
+        assertThat(loadRouteIDs("file:src/test/resources/org/apache/camel/impl/engine/c?/*.xml"))
                 .isEmpty();
     }
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/LoadRestFromXmlTest.java b/core/camel-core/src/test/java/org/apache/camel/model/LoadRestFromXmlTest.java
index 426516d..0700d0d 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/LoadRestFromXmlTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/LoadRestFromXmlTest.java
@@ -20,12 +20,14 @@ import java.io.InputStream;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.component.rest.DummyRestConsumerFactory;
 import org.apache.camel.component.rest.DummyRestProcessorFactory;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.Resource;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -42,7 +44,7 @@ public class LoadRestFromXmlTest extends ContextTestSupport {
     }
 
     @Test
-    public void testLoadRestFromXml() throws Exception {
+    public void testLoadRestsDefinitionFromXml() throws Exception {
         assertNotNull(context.getRoute("foo"), "Existing foo route should be there");
 
         assertEquals(2, context.getRoutes().size());
@@ -69,6 +71,35 @@ public class LoadRestFromXmlTest extends ContextTestSupport {
         bar.assertIsSatisfied();
     }
 
+    @Test
+    public void testLoadRoutesBuilderFromXml() throws Exception {
+        assertNotNull(context.getRoute("foo"), "Existing foo route should be there");
+
+        assertEquals(2, context.getRoutes().size());
+
+        // test that existing route works
+        MockEndpoint foo = getMockEndpoint("mock:foo");
+        foo.expectedBodiesReceived("Hello World");
+        template.sendBody("direct:foo", "Hello World");
+        foo.assertIsSatisfied();
+
+        // load rest from XML and add them to the existing camel context
+        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
+        Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRest.xml");
+        RoutesBuilder routes = ecc.getRoutesBuilderLoader().loadRoutesBuilder(resource);
+
+        context.addRoutes(routes);
+
+        assertNotNull(context.getRoute("route1"), "Loaded rest route should be there");
+        assertEquals(3, context.getRoutes().size());
+
+        // test that loaded route works
+        MockEndpoint bar = getMockEndpoint("mock:bar");
+        bar.expectedBodiesReceived("Bye World");
+        template.sendBody("seda:get-say-hello-bar", "Bye World");
+        bar.assertIsSatisfied();
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/LoadRouteFromXmlTest.java b/core/camel-core/src/test/java/org/apache/camel/model/LoadRouteFromXmlTest.java
index 3e9a197..9b49251 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/LoadRouteFromXmlTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/LoadRouteFromXmlTest.java
@@ -20,8 +20,10 @@ import java.io.InputStream;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Resource;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -30,7 +32,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 public class LoadRouteFromXmlTest extends ContextTestSupport {
 
     @Test
-    public void testLoadRouteFromXml() throws Exception {
+    public void testLoadRoutesDefinitionFromXml() throws Exception {
         assertNotNull(context.getRoute("foo"), "Existing foo route should be there");
         assertEquals(1, context.getRoutes().size());
 
@@ -58,6 +60,36 @@ public class LoadRouteFromXmlTest extends ContextTestSupport {
         bar.assertIsSatisfied();
     }
 
+    @Test
+    public void testLoadRoutesBuilderFromXml() throws Exception {
+        assertNotNull(context.getRoute("foo"), "Existing foo route should be there");
+        assertEquals(1, context.getRoutes().size());
+
+        // test that existing route works
+        MockEndpoint foo = getMockEndpoint("mock:foo");
+        foo.expectedBodiesReceived("Hello World");
+        template.sendBody("direct:foo", "Hello World");
+        foo.assertIsSatisfied();
+
+        // START SNIPPET: e1
+        // load route from XML and add them to the existing camel context
+        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
+        Resource resource = Resource.fromClasspath(LoadRouteFromXmlTest.class, "barRoute.xml");
+        RoutesBuilder routes = ecc.getRoutesBuilderLoader().loadRoutesBuilder(resource);
+
+        context.addRoutes(routes);
+        // END SNIPPET: e1
+
+        assertNotNull(context.getRoute("bar"), "Loaded bar route should be there");
+        assertEquals(2, context.getRoutes().size());
+
+        // test that loaded route works
+        MockEndpoint bar = getMockEndpoint("mock:bar");
+        bar.expectedBodiesReceived("Bye World");
+        template.sendBody("direct:bar", "Bye World");
+        bar.assertIsSatisfied();
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index ca7cbbd..98f902c 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -133,6 +133,10 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "RoutesBuilders": target.setRoutesBuilders(property(camelContext, java.util.List.class, value)); return true;
         case "routescollectorenabled":
         case "RoutesCollectorEnabled": target.setRoutesCollectorEnabled(property(camelContext, boolean.class, value)); return true;
+        case "routesexcludepattern":
+        case "RoutesExcludePattern": target.setRoutesExcludePattern(property(camelContext, java.lang.String.class, value)); return true;
+        case "routesincludepattern":
+        case "RoutesIncludePattern": target.setRoutesIncludePattern(property(camelContext, java.lang.String.class, value)); return true;
         case "shutdownloginflightexchangesontimeout":
         case "ShutdownLogInflightExchangesOnTimeout": target.setShutdownLogInflightExchangesOnTimeout(property(camelContext, boolean.class, value)); return true;
         case "shutdownnowontimeout":
@@ -189,12 +193,6 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "UseDataType": target.setUseDataType(property(camelContext, boolean.class, value)); return true;
         case "usemdclogging":
         case "UseMdcLogging": target.setUseMdcLogging(property(camelContext, boolean.class, value)); return true;
-        case "xmlrests":
-        case "XmlRests": target.setXmlRests(property(camelContext, java.lang.String.class, value)); return true;
-        case "xmlroutetemplates":
-        case "XmlRouteTemplates": target.setXmlRouteTemplates(property(camelContext, java.lang.String.class, value)); return true;
-        case "xmlroutes":
-        case "XmlRoutes": target.setXmlRoutes(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -314,6 +312,10 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "RoutesBuilders": return java.util.List.class;
         case "routescollectorenabled":
         case "RoutesCollectorEnabled": return boolean.class;
+        case "routesexcludepattern":
+        case "RoutesExcludePattern": return java.lang.String.class;
+        case "routesincludepattern":
+        case "RoutesIncludePattern": return java.lang.String.class;
         case "shutdownloginflightexchangesontimeout":
         case "ShutdownLogInflightExchangesOnTimeout": return boolean.class;
         case "shutdownnowontimeout":
@@ -370,12 +372,6 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "UseDataType": return boolean.class;
         case "usemdclogging":
         case "UseMdcLogging": return boolean.class;
-        case "xmlrests":
-        case "XmlRests": return java.lang.String.class;
-        case "xmlroutetemplates":
-        case "XmlRouteTemplates": return java.lang.String.class;
-        case "xmlroutes":
-        case "XmlRoutes": return java.lang.String.class;
         default: return null;
         }
     }
@@ -496,6 +492,10 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "RoutesBuilders": return target.getRoutesBuilders();
         case "routescollectorenabled":
         case "RoutesCollectorEnabled": return target.isRoutesCollectorEnabled();
+        case "routesexcludepattern":
+        case "RoutesExcludePattern": return target.getRoutesExcludePattern();
+        case "routesincludepattern":
+        case "RoutesIncludePattern": return target.getRoutesIncludePattern();
         case "shutdownloginflightexchangesontimeout":
         case "ShutdownLogInflightExchangesOnTimeout": return target.isShutdownLogInflightExchangesOnTimeout();
         case "shutdownnowontimeout":
@@ -552,12 +552,6 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "UseDataType": return target.isUseDataType();
         case "usemdclogging":
         case "UseMdcLogging": return target.isUseMdcLogging();
-        case "xmlrests":
-        case "XmlRests": return target.getXmlRests();
-        case "xmlroutetemplates":
-        case "XmlRouteTemplates": return target.getXmlRouteTemplates();
-        case "xmlroutes":
-        case "XmlRoutes": return target.getXmlRoutes();
         default: return null;
         }
     }
diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 52e54cd..5a85bd6 100644
--- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -66,6 +66,8 @@
     { "name": "camel.main.routesBuilderClasses", "description": "Sets classes names that implement RoutesBuilder .", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
     { "name": "camel.main.routesBuilders", "description": "Sets the RoutesBuilder instances.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "object", "javaType": "java.util.List" },
     { "name": "camel.main.routesCollectorEnabled", "description": "Whether the routes collector is enabled or not. When enabled Camel will auto-discover routes (RouteBuilder instances from the registry and also load additional XML routes from the file system. The routes collector is default enabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
+    { "name": "camel.main.routesExcludePattern", "description": "Used for exclusive filtering of routes from directories. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma, as example, to exclude all the routes from a directory whose name contains foo use: &#42;&#42;\/foo.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType":  [...]
+    { "name": "camel.main.routesIncludePattern", "description": "Used for inclusive filtering of routes from directories. This is used to retrieve the initial list of resource which can be filtered using the exclusive filter. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma, as example, to include all the routes from a directory whose name contains foo use: &#42;&#42;\/foo.", "sourceType": "org.apache.camel.main.DefaultConfigurationProper [...]
     { "name": "camel.main.shutdownLogInflightExchangesOnTimeout", "description": "Sets whether to log information about the inflight Exchanges which are still running during a shutdown which didn't complete without the given timeout. This requires to enable the option inflightRepositoryBrowseEnabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.main.shutdownNowOnTimeout", "description": "Sets whether to force shutdown of all consumers when a timeout occurred and thus not all consumers was shutdown within that period. You should have good reasons to set this option to false as it means that the routes keep running and is halted abruptly when CamelContext has been shutdown.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.main.shutdownRoutesInReverseOrder", "description": "Sets whether routes should be shutdown in reverse or the same order as they were started.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
@@ -94,9 +96,6 @@
     { "name": "camel.main.useBreadcrumb", "description": "Set whether breadcrumb is enabled. The default value is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" },
     { "name": "camel.main.useDataType", "description": "Whether to enable using data type on Camel messages. Data type are automatic turned on if one ore more routes has been explicit configured with input and output types. Otherwise data type is default off.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" },
     { "name": "camel.main.useMdcLogging", "description": "To turn on MDC logging", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" },
-    { "name": "camel.main.xmlRests", "description": "Directory to scan for adding additional XML rests. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;\/&#42;camel&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific the exact name for each  [...]
-    { "name": "camel.main.xmlRoutes", "description": "Directory to scan for adding additional XML routes. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;\/&#42;camel&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific the exact name for eac [...]
-    { "name": "camel.main.xmlRouteTemplates", "description": "Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;\/&#42;template-&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific t [...]
     { "name": "camel.faulttolerance.bulkheadEnabled", "description": "Whether bulkhead is enabled or not on the circuit breaker. Default is false.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": false },
     { "name": "camel.faulttolerance.bulkheadExecutorServiceRef", "description": "References to a custom thread pool to use when bulkhead is enabled.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
     { "name": "camel.faulttolerance.bulkheadMaxConcurrentCalls", "description": "Configures the max amount of concurrent calls the bulkhead will support. Default value is 10.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "integer", "javaType": "java.lang.Integer", "defaultValue": 10 },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index e5a8888..acf9bfb 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -78,6 +78,8 @@ The following table lists all the options:
 | *camel.main.routesBuilder{zwsp}Classes* | Sets classes names that implement RoutesBuilder . |  | String
 | *camel.main.routesBuilders* | Sets the RoutesBuilder instances. |  | List
 | *camel.main.routesCollector{zwsp}Enabled* | Whether the routes collector is enabled or not. When enabled Camel will auto-discover routes (RouteBuilder instances from the registry and also load additional XML routes from the file system. The routes collector is default enabled. | true | boolean
+| *camel.main.routesExclude{zwsp}Pattern* | Used for exclusive filtering of routes from directories. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma, as example, to exclude all the routes from a directory whose name contains foo use: &#42;&#42;/foo. |  | String
+| *camel.main.routesInclude{zwsp}Pattern* | Used for inclusive filtering of routes from directories. This is used to retrieve the initial list of resource which can be filtered using the exclusive filter. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma, as example, to include all the routes from a directory whose name contains foo use: &#42;&#42;/foo. | classpath:camel/*.xml,classpath:camel-template/*.xml,classpath:camel-rest/*.xml | String
 | *camel.main.shutdownLogInflight{zwsp}ExchangesOnTimeout* | Sets whether to log information about the inflight Exchanges which are still running during a shutdown which didn't complete without the given timeout. This requires to enable the option inflightRepositoryBrowseEnabled. | true | boolean
 | *camel.main.shutdownNowOn{zwsp}Timeout* | Sets whether to force shutdown of all consumers when a timeout occurred and thus not all consumers was shutdown within that period. You should have good reasons to set this option to false as it means that the routes keep running and is halted abruptly when CamelContext has been shutdown. | true | boolean
 | *camel.main.shutdownRoutesIn{zwsp}ReverseOrder* | Sets whether routes should be shutdown in reverse or the same order as they were started. | true | boolean
@@ -106,9 +108,6 @@ The following table lists all the options:
 | *camel.main.useBreadcrumb* | Set whether breadcrumb is enabled. The default value is false. |  | boolean
 | *camel.main.useDataType* | Whether to enable using data type on Camel messages. Data type are automatic turned on if one ore more routes has been explicit configured with input and output types. Otherwise data type is default off. |  | boolean
 | *camel.main.useMdcLogging* | To turn on MDC logging |  | boolean
-| *camel.main.xmlRests* | Directory to scan for adding additional XML rests. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific the exact name for each XML file is faster as no cla [...]
-| *camel.main.xmlRoutes* | Directory to scan for adding additional XML routes. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific the exact name for each XML file is faster as no c [...]
-| *camel.main.xmlRouteTemplates* | Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false. Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;template-&#42;.xml Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you specific the exact name for each XML f [...]
 | *camel.faulttolerance.bulkhead{zwsp}Enabled* | Whether bulkhead is enabled or not on the circuit breaker. Default is false. | false | Boolean
 | *camel.faulttolerance.bulkhead{zwsp}ExecutorServiceRef* | References to a custom thread pool to use when bulkhead is enabled. |  | String
 | *camel.faulttolerance.bulkhead{zwsp}MaxConcurrentCalls* | Configures the max amount of concurrent calls the bulkhead will support. Default value is 10. | 10 | Integer
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 3101034..a881ad8 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -39,7 +39,6 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.NoSuchLanguageException;
-import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.health.HealthCheck;
 import org.apache.camel.health.HealthCheckConfiguration;
@@ -275,47 +274,6 @@ public abstract class BaseMainSupport extends BaseService {
         listeners.remove(listener);
     }
 
-    protected void loadRouteBuilders(CamelContext camelContext) throws Exception {
-        // lets use Camel's bean post processor on any existing route builder classes
-        // so the instance has some support for dependency injection
-        CamelBeanPostProcessor postProcessor = camelContext.adapt(ExtendedCamelContext.class).getBeanPostProcessor();
-        for (RoutesBuilder routeBuilder : mainConfigurationProperties.getRoutesBuilders()) {
-            postProcessor.postProcessBeforeInitialization(routeBuilder, routeBuilder.getClass().getName());
-            postProcessor.postProcessAfterInitialization(routeBuilder, routeBuilder.getClass().getName());
-        }
-
-        if (mainConfigurationProperties.getRoutesBuilderClasses() != null) {
-            String[] routeClasses = mainConfigurationProperties.getRoutesBuilderClasses().split(",");
-            for (String routeClass : routeClasses) {
-                Class<RoutesBuilder> routeClazz = camelContext.getClassResolver().resolveClass(routeClass, RoutesBuilder.class);
-                if (routeClazz == null) {
-                    LOG.warn("Unable to resolve class: {}", routeClass);
-                    continue;
-                }
-
-                // lets use Camel's injector so the class has some support for dependency injection
-                RoutesBuilder builder = camelContext.getInjector().newInstance(routeClazz);
-
-                mainConfigurationProperties.addRoutesBuilder(builder);
-            }
-        }
-
-        if (mainConfigurationProperties.getPackageScanRouteBuilders() != null) {
-            String[] pkgs = mainConfigurationProperties.getPackageScanRouteBuilders().split(",");
-            Set<Class<?>> set = camelContext.adapt(ExtendedCamelContext.class)
-                    .getPackageScanClassResolver()
-                    .findImplementations(RoutesBuilder.class, pkgs);
-            for (Class<?> routeClazz : set) {
-                Object builder = camelContext.getInjector().newInstance(routeClazz);
-                if (builder instanceof RoutesBuilder) {
-                    mainConfigurationProperties.addRoutesBuilder((RoutesBuilder) builder);
-                } else {
-                    LOG.warn("Class {} is not a RouteBuilder class", routeClazz);
-                }
-            }
-        }
-    }
-
     protected void loadConfigurations(CamelContext camelContext) throws Exception {
         // lets use Camel's bean post processor on any existing configuration classes
         // so the instance has some support for dependency injection
@@ -515,11 +473,8 @@ public abstract class BaseMainSupport extends BaseService {
     }
 
     protected void configureRoutes(CamelContext camelContext) throws Exception {
-        // try to load the route builders
-        loadRouteBuilders(camelContext);
-
         // then configure and add the routes
-        RoutesConfigurer configurer = new RoutesConfigurer(routesCollector, mainConfigurationProperties.getRoutesBuilders());
+        RoutesConfigurer configurer = new RoutesConfigurer(routesCollector);
         configurer.configureRoutes(camelContext, mainConfigurationProperties);
     }
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index aa9c6b9..9c3be48 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -89,7 +89,7 @@ public final class DefaultConfigurationConfigurer {
      * @param camelContext the camel context
      * @param config       the configuration
      */
-    public static void configure(CamelContext camelContext, DefaultConfigurationProperties config) throws Exception {
+    public static void configure(CamelContext camelContext, DefaultConfigurationProperties<?> config) throws Exception {
         ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
 
         if (config.getStartupRecorder() != null) {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
index abcc616..b0fbf9e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.main;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.Experimental;
 import org.apache.camel.LoggingLevel;
 import org.apache.camel.ManagementStatisticsLevel;
@@ -86,9 +85,8 @@ public abstract class DefaultConfigurationProperties<T> {
     private boolean routesCollectorEnabled = true;
     private String javaRoutesIncludePattern;
     private String javaRoutesExcludePattern;
-    private String xmlRoutes = "classpath:camel/*.xml";
-    private String xmlRouteTemplates = "classpath:camel-template/*.xml";
-    private String xmlRests = "classpath:camel-rest/*.xml";
+    private String routesIncludePattern = "classpath:camel/*.xml,classpath:camel-template/*.xml,classpath:camel-rest/*.xml";
+    private String routesExcludePattern;
     private boolean lightweight;
     // route controller
     @Metadata(defaultValue = "DEBUG")
@@ -838,7 +836,7 @@ public abstract class DefaultConfigurationProperties<T> {
 
     /**
      * Whether the routes collector is enabled or not.
-     * 
+     *
      * When enabled Camel will auto-discover routes (RouteBuilder instances from the registry and also load additional
      * XML routes from the file system.
      *
@@ -883,66 +881,96 @@ public abstract class DefaultConfigurationProperties<T> {
         this.javaRoutesExcludePattern = javaRoutesExcludePattern;
     }
 
-    public String getXmlRoutes() {
-        return xmlRoutes;
-    }
-
-    /**
-     * Directory to scan for adding additional XML routes. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
-     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public void setXmlRoutes(String xmlRoutes) {
-        this.xmlRoutes = xmlRoutes;
-    }
-
-    public String getXmlRouteTemplates() {
-        return xmlRouteTemplates;
-    }
-
-    /**
-     * Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
-     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;template-&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public void setXmlRouteTemplates(String xmlRouteTemplates) {
-        this.xmlRouteTemplates = xmlRouteTemplates;
-    }
-
-    public String getXmlRests() {
-        return xmlRests;
-    }
-
-    /**
-     * Directory to scan for adding additional XML rests. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
-     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public void setXmlRests(String xmlRests) {
-        this.xmlRests = xmlRests;
-    }
-
+    public String getRoutesIncludePattern() {
+        return routesIncludePattern;
+    }
+
+    /**
+     * Used for inclusive filtering of routes from directories. This is used to retrieve the initial list of resource
+     * which can be filtered using the exclusive filter. The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma, as example, to include all the routes from a directory
+     * whose name contains foo use: &#42;&#42;/*foo*.
+     */
+    public void setRoutesIncludePattern(String routesIncludePattern) {
+        this.routesIncludePattern = routesIncludePattern;
+    }
+
+    public String getRoutesExcludePattern() {
+        return routesExcludePattern;
+    }
+
+    /**
+     * Used for exclusive filtering of routes from directories. The exclusive filtering takes precedence over inclusive
+     * filtering. The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma, as example, to exclude all the routes from a directory
+     * whose name contains foo use: &#42;&#42;/*foo*.
+     */
+    public void setRoutesExcludePattern(String routesExcludePattern) {
+        this.routesExcludePattern = routesExcludePattern;
+    }
+
+    //    public String getXmlRoutes() {
+    //        return xmlRoutes;
+    //    }
+    //
+    //    /**
+    //     * Directory to scan for adding additional XML routes. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
+    //     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public void setXmlRoutes(String xmlRoutes) {
+    //        this.xmlRoutes = xmlRoutes;
+    //    }
+    //
+    //    public String getXmlRouteTemplates() {
+    //        return xmlRouteTemplates;
+    //    }
+    //
+    //    /**
+    //     * Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
+    //     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;template-&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public void setXmlRouteTemplates(String xmlRouteTemplates) {
+    //        this.xmlRouteTemplates = xmlRouteTemplates;
+    //    }
+    //
+    //    public String getXmlRests() {
+    //        return xmlRests;
+    //    }
+    //
+    //    /**
+    //     * Directory to scan for adding additional XML rests. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
+    //     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public void setXmlRests(String xmlRests) {
+    //        this.xmlRests = xmlRests;
+    //    }
+    //
     @Experimental
     public boolean isLightweight() {
         return lightweight;
@@ -1793,60 +1821,70 @@ public abstract class DefaultConfigurationProperties<T> {
         return (T) this;
     }
 
-    /**
-     * Directory to scan for adding additional XML routes. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: By default classpath is
-     * assumed if no prefix is specified.
-     *
-     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public T withXmlRoutes(String xmlRoutes) {
-        this.xmlRoutes = xmlRoutes;
-        return (T) this;
-    }
-
-    /**
-     * Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
-     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;template-&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public T withXmlRouteTemplates(String xmlRouteTemplates) {
-        this.xmlRouteTemplates = xmlRouteTemplates;
-        return (T) this;
-    }
-
-    /**
-     * Directory to scan for adding additional XML rests. You can turn this off by setting the value to false.
-     *
-     * Files can be loaded from either classpath or file by prefixing with classpath: or file: By default classpath is
-     * assumed if no prefix is specified.
-     *
-     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
-     *
-     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
-     * specific the exact name for each XML file is faster as no classpath scanning is needed.
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    public T withXmlRests(String xmlRests) {
-        this.xmlRests = xmlRests;
-        return (T) this;
-    }
+    public T withRoutesIncludePattern(String routesIncludePattern) {
+        this.routesIncludePattern = routesIncludePattern;
+        return (T) this;
+    }
+
+    public T withRoutesExcludePattern(String routesExcludePattern) {
+        this.routesExcludePattern = routesExcludePattern;
+        return (T) this;
+    }
+
+    //    /**
+    //     * Directory to scan for adding additional XML routes. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: By default classpath is
+    //     * assumed if no prefix is specified.
+    //     *
+    //     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public T withXmlRoutes(String xmlRoutes) {
+    //        this.xmlRoutes = xmlRoutes;
+    //        return (T) this;
+    //    }
+    //
+    //    /**
+    //     * Directory to scan for adding additional XML route templates. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: Wildcards is supported
+    //     * using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;template-&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public T withXmlRouteTemplates(String xmlRouteTemplates) {
+    //        this.xmlRouteTemplates = xmlRouteTemplates;
+    //        return (T) this;
+    //    }
+    //
+    //    /**
+    //     * Directory to scan for adding additional XML rests. You can turn this off by setting the value to false.
+    //     *
+    //     * Files can be loaded from either classpath or file by prefixing with classpath: or file: By default classpath is
+    //     * assumed if no prefix is specified.
+    //     *
+    //     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+    //     *
+    //     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where as if you
+    //     * specific the exact name for each XML file is faster as no classpath scanning is needed.
+    //     *
+    //     * Multiple directories can be specified and separated by comma, such as:
+    //     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+    //     */
+    //    public T withXmlRests(String xmlRests) {
+    //        this.xmlRests = xmlRests;
+    //        return (T) this;
+    //    }
 
     /*
      * Configure the context to be lightweight.  This will trigger some optimizations
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 d82b34b..1dc1522 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
@@ -17,7 +17,6 @@
 package org.apache.camel.main;
 
 import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -30,13 +29,9 @@ import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.LambdaRouteBuilder;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.model.RouteTemplatesDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.Resource;
 import org.apache.camel.util.AntPathMatcher;
-import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StopWatch;
 import org.slf4j.Logger;
@@ -50,11 +45,12 @@ public class DefaultRoutesCollector implements RoutesCollector {
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
     @Override
-    public List<RoutesBuilder> collectRoutesFromRegistry(
+    public Collection<RoutesBuilder> collectRoutesFromRegistry(
             CamelContext camelContext,
-            String excludePattern, String includePattern) {
-        final List<RoutesBuilder> routes = new ArrayList<>();
+            String excludePattern,
+            String includePattern) {
 
+        final List<RoutesBuilder> routes = new ArrayList<>();
         final AntPathMatcher matcher = new AntPathMatcher();
 
         Set<LambdaRouteBuilder> lrbs = camelContext.getRegistry().findByType(LambdaRouteBuilder.class);
@@ -113,135 +109,53 @@ public class DefaultRoutesCollector implements RoutesCollector {
     }
 
     @Override
-    public List<RouteTemplatesDefinition> collectXmlRouteTemplatesFromDirectory(CamelContext camelContext, String directory)
-            throws Exception {
-        ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
-        PackageScanResourceResolver resolver = ecc.getPackageScanResourceResolver();
-
-        List<RouteTemplatesDefinition> answer = new ArrayList<>();
-
-        StopWatch watch = new StopWatch();
-        int count = 0;
-        String[] parts = directory.split(",");
-        for (String part : parts) {
-            log.debug("Loading additional Camel XML route templates from: {}", part);
-            try {
-                Collection<Resource> resources = resolver.findResources(part);
-                for (Resource resource : resources) {
-                    InputStream is = resource.getInputStream();
-                    try {
-                        log.debug("Found XML route templates from location: {}", part);
-                        RouteTemplatesDefinition templates = (RouteTemplatesDefinition) ecc.getXMLRoutesDefinitionLoader()
-                                .loadRouteTemplatesDefinition(ecc, is);
-                        if (templates != null) {
-                            answer.add(templates);
-                            count += templates.getRouteTemplates().size();
-                        }
-                    } finally {
-                        IOHelper.close(is);
-                    }
-                }
-            } catch (FileNotFoundException e) {
-                log.debug("No XML route templates found in {}. Skipping XML route templates detection.", part);
-            } catch (Exception e) {
-                throw RuntimeCamelException.wrapRuntimeException(e);
-            }
-            if (count > 0) {
-                log.info("Loaded {} ({} millis) additional Camel XML route templates from: {}", count, watch.taken(),
-                        directory);
-            } else {
-                log.debug("No additional Camel XML route templates discovered from: {}", directory);
-            }
+    public Collection<RoutesBuilder> collectRoutesFromDirectory(
+            CamelContext camelContext,
+            String excludePattern,
+            String includePattern) {
+
+        final ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
+        final PackageScanResourceResolver resolver = ecc.getPackageScanResourceResolver();
+        final List<RoutesBuilder> answer = new ArrayList<>();
+        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");
+            return answer;
         }
 
-        return answer;
-
-    }
-
-    @Override
-    public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) {
-        ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
-        PackageScanResourceResolver resolver = ecc.getPackageScanResourceResolver();
-
-        List<RoutesDefinition> answer = new ArrayList<>();
-
         StopWatch watch = new StopWatch();
         int count = 0;
-        String[] parts = directory.split(",");
-        for (String part : parts) {
-            log.debug("Loading additional Camel XML routes from: {}", part);
+
+        for (String include : includes) {
+            log.debug("Loading additional RoutesBuilder from: {}", include);
             try {
-                Collection<Resource> resources = resolver.findResources(part);
-                for (Resource resource : resources) {
-                    InputStream is = resource.getInputStream();
-                    try {
-                        log.debug("Found XML routes from location: {}", part);
-                        RoutesDefinition routes
-                                = (RoutesDefinition) ecc.getXMLRoutesDefinitionLoader().loadRoutesDefinition(ecc, is);
-                        if (routes != null) {
-                            answer.add(routes);
-                            count += routes.getRoutes().size();
-                        }
-                    } finally {
-                        IOHelper.close(is);
+                for (Resource resource : resolver.findResources(include)) {
+                    if (AntPathMatcher.INSTANCE.anyMatch(excludes, resource.getLocation())) {
+                        continue;
                     }
-                }
-            } catch (FileNotFoundException e) {
-                log.debug("No XML routes found in {}. Skipping XML routes detection.", part);
-            } catch (Exception e) {
-                throw RuntimeCamelException.wrapRuntimeException(e);
-            }
-            if (count > 0) {
-                log.info("Loaded {} ({} millis) additional Camel XML routes from: {}", count, watch.taken(), directory);
-            } else {
-                log.debug("No additional Camel XML routes discovered from: {}", directory);
-            }
-        }
 
-        return answer;
-    }
-
-    @Override
-    public List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) {
-        ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
-        PackageScanResourceResolver resolver = camelContext.adapt(ExtendedCamelContext.class).getPackageScanResourceResolver();
-
-        List<RestsDefinition> answer = new ArrayList<>();
-
-        StopWatch watch = new StopWatch();
-        int count = 0;
-        String[] parts = directory.split(",");
-        for (String part : parts) {
-            log.debug("Loading additional Camel XML rests from: {}", part);
-            try {
-                Collection<Resource> resources = resolver.findResources(part);
-                for (Resource resource : resources) {
-                    InputStream is = resource.getInputStream();
-                    try {
-                        log.debug("Found XML rest from location: {}", part);
-                        RestsDefinition rests
-                                = (RestsDefinition) ecc.getXMLRoutesDefinitionLoader().loadRestsDefinition(ecc, is);
-                        if (rests != null) {
-                            answer.add(rests);
-                            count += rests.getRests().size();
-                        }
-                    } finally {
-                        IOHelper.close(is);
+                    log.debug("Found route builder from location: {}", include);
+                    RoutesBuilder builder = ecc.getRoutesBuilderLoader().loadRoutesBuilder(resource);
+                    if (builder != null) {
+                        answer.add(builder);
+                        count++;
                     }
                 }
             } catch (FileNotFoundException e) {
-                log.debug("No XML rests found in {}. Skipping XML rests detection.", part);
+                log.debug("No RoutesBuilder found in {}. Skipping detection.", include);
             } catch (Exception e) {
                 throw RuntimeCamelException.wrapRuntimeException(e);
             }
             if (count > 0) {
-                log.info("Loaded {} ({} millis) additional Camel XML rests from: {}", count, watch.taken(), directory);
+                log.info("Loaded {} ({} millis) additional RoutesBuilder from: {}, pattern: {}", count, watch.taken(), include,
+                        includePattern);
             } else {
-                log.debug("No additional Camel XML rests discovered from: {}", directory);
+                log.debug("No additional RoutesBuilder discovered from: {}", includePattern);
             }
         }
 
         return answer;
     }
-
 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/RoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/RoutesCollector.java
index 6481585..b6ea264 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/RoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesCollector.java
@@ -16,13 +16,10 @@
  */
 package org.apache.camel.main;
 
-import java.util.List;
+import java.util.Collection;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
-import org.apache.camel.model.RouteTemplatesDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 
 /**
  * Collects routes and rests from the various sources (like registry or opinionated classpath locations) and adds these
@@ -39,34 +36,18 @@ public interface RoutesCollector {
      * @param  includePattern include pattern (see javaRoutesIncludePattern option)
      * @return                the discovered routes or an empty list
      */
-    List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, String excludePattern, String includePattern);
+    Collection<RoutesBuilder> collectRoutesFromRegistry(
+            CamelContext camelContext, String excludePattern, String includePattern);
 
     /**
-     * Collects all XML routes from the given directory.
+     * Collects all RoutesBuilder from the given directory.
      *
-     * @param  camelContext the Camel Context
-     * @param  directory    the directory (see xmlRoutes option)
-     * @return              the discovered routes or an empty list
-     */
-    List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception;
-
-    /**
-     * Collects all XML route templates from the given directory.
-     *
-     * @param  camelContext the Camel Context
-     * @param  directory    the directory (see xmlRouteTemplates option)
-     * @return              the discovered route templates or an empty list
-     */
-    List<RouteTemplatesDefinition> collectXmlRouteTemplatesFromDirectory(CamelContext camelContext, String directory)
-            throws Exception;
-
-    /**
-     * Collects all XML rests from the given directory.
-     *
-     * @param  camelContext the Camel Context
-     * @param  directory    the directory (see xmlRests option)
-     * @return              the discovered rests or an empty list
+     * @param  camelContext   the Camel Context
+     * @param  excludePattern exclude pattern (see routesExcludePattern option)
+     * @param  includePattern include pattern (see routesIncludePattern option)
+     * @return                the discovered RoutesBuilder or an empty collection
      */
-    List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception;
+    Collection<RoutesBuilder> collectRoutesFromDirectory(
+            CamelContext camelContext, String excludePattern, String includePattern);
 
 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
index 2d5b3b3..2f9d47fd 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
@@ -21,12 +21,10 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.model.Model;
-import org.apache.camel.model.RouteTemplatesDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.support.OrderedComparator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,12 +33,9 @@ import org.slf4j.LoggerFactory;
  * To configure routes using {@link RoutesCollector} which collects the routes from various sources.
  */
 public class RoutesConfigurer {
-
     private static final Logger LOG = LoggerFactory.getLogger(RoutesConfigurer.class);
 
     private final RoutesCollector routesCollector;
-    private final List<RoutesBuilder> routesBuilders;
-    private boolean addRestsToRoutes = true;
 
     /**
      * Creates a new routes configurer
@@ -48,25 +43,7 @@ public class RoutesConfigurer {
      * @param routesCollector routes collector
      */
     public RoutesConfigurer(RoutesCollector routesCollector) {
-        this(routesCollector, new ArrayList<>());
-    }
-
-    /**
-     * Creates a new routes configurer
-     *
-     * @param routesCollector routes collector
-     * @param routesBuilders  existing route builders
-     */
-    public RoutesConfigurer(RoutesCollector routesCollector, List<RoutesBuilder> routesBuilders) {
         this.routesCollector = routesCollector;
-        this.routesBuilders = routesBuilders;
-    }
-
-    /**
-     * Whether rests should be automatic added as routes
-     */
-    public void setAddRestsToRoutes(boolean addRestsToRoutes) {
-        this.addRestsToRoutes = addRestsToRoutes;
     }
 
     /**
@@ -76,58 +53,78 @@ public class RoutesConfigurer {
      * @param camelContext the Camel context
      * @param config       the configuration
      */
-    public void configureRoutes(CamelContext camelContext, DefaultConfigurationProperties config) {
-        if (config.isRoutesCollectorEnabled()) {
-            try {
-                LOG.debug("RoutesCollectorEnabled: {}", routesCollector);
-                final List<RoutesBuilder> routes = routesCollector.collectRoutesFromRegistry(camelContext,
-                        config.getJavaRoutesExcludePattern(),
-                        config.getJavaRoutesIncludePattern());
-
-                // add newly discovered routes
-                routesBuilders.addAll(routes);
-                // sort routes according to ordered
-                routesBuilders.sort(OrderedComparator.get());
-                // then add the routes
-                for (RoutesBuilder builder : routesBuilders) {
-                    LOG.debug("Adding routes into CamelContext from RoutesBuilder: {}", builder);
-                    camelContext.addRoutes(builder);
-                }
+    public void configureRoutes(CamelContext camelContext, MainConfigurationProperties config) throws Exception {
+        final List<RoutesBuilder> routes = new ArrayList<>(config.getRoutesBuilders());
 
-                boolean scan = !config.getXmlRoutes().equals("false");
-                if (scan) {
-                    List<RoutesDefinition> defs
-                            = routesCollector.collectXmlRoutesFromDirectory(camelContext, config.getXmlRoutes());
-                    for (RoutesDefinition def : defs) {
-                        LOG.debug("Adding routes into CamelContext from XML files: {}", config.getXmlRoutes());
-                        camelContext.getExtension(Model.class).addRouteDefinitions(def.getRoutes());
-                    }
+        if (config.getRoutesBuilderClasses() != null) {
+            String[] routeClasses = config.getRoutesBuilderClasses().split(",");
+            for (String routeClass : routeClasses) {
+                Class<RoutesBuilder> routeClazz = camelContext.getClassResolver().resolveClass(routeClass, RoutesBuilder.class);
+                if (routeClazz == null) {
+                    LOG.warn("Unable to resolve class: {}", routeClass);
+                    continue;
                 }
 
-                boolean scanTemplates = !config.getXmlRouteTemplates().equals("false");
-                if (scanTemplates) {
-                    List<RouteTemplatesDefinition> defs = routesCollector.collectXmlRouteTemplatesFromDirectory(camelContext,
-                            config.getXmlRouteTemplates());
-                    for (RouteTemplatesDefinition def : defs) {
-                        LOG.debug("Adding route templates into CamelContext from XML files: {}", config.getXmlRouteTemplates());
-                        camelContext.getExtension(Model.class).addRouteTemplateDefinitions(def.getRouteTemplates());
-                    }
-                }
+                // lets use Camel's injector so the class has some support for dependency injection
+                RoutesBuilder builder = camelContext.getInjector().newInstance(routeClazz);
 
-                boolean scanRests = !config.getXmlRests().equals("false");
-                if (scanRests) {
-                    List<RestsDefinition> defs
-                            = routesCollector.collectXmlRestsFromDirectory(camelContext, config.getXmlRests());
-                    for (RestsDefinition def : defs) {
-                        LOG.debug("Adding rests into CamelContext from XML files: {}", config.getXmlRests());
-                        camelContext.getExtension(Model.class).addRestDefinitions(def.getRests(), addRestsToRoutes);
-                    }
+                routes.add(builder);
+            }
+        }
+
+        if (config.getPackageScanRouteBuilders() != null) {
+            String[] pkgs = config.getPackageScanRouteBuilders().split(",");
+            Set<Class<?>> set = camelContext.adapt(ExtendedCamelContext.class)
+                    .getPackageScanClassResolver()
+                    .findImplementations(RoutesBuilder.class, pkgs);
+
+            for (Class<?> routeClazz : set) {
+                Object builder = camelContext.getInjector().newInstance(routeClazz);
+                if (builder instanceof RoutesBuilder) {
+                    routes.add((RoutesBuilder) builder);
+                } else {
+                    LOG.warn("Class {} is not a RouteBuilder class", routeClazz);
                 }
+            }
+        }
+
+        if (config.isRoutesCollectorEnabled()) {
+            try {
+                LOG.debug("RoutesCollectorEnabled: {}", routesCollector);
+
+                // add discovered routes from registry
+                routes.addAll(routesCollector.collectRoutesFromRegistry(
+                        camelContext,
+                        config.getJavaRoutesExcludePattern(),
+                        config.getJavaRoutesIncludePattern()));
+                // add discovered routes from directories
+                routes.addAll(routesCollector.collectRoutesFromDirectory(
+                        camelContext,
+                        config.getRoutesExcludePattern(),
+                        config.getRoutesIncludePattern()));
+
             } catch (Exception e) {
                 throw RuntimeCamelException.wrapRuntimeException(e);
             }
         }
 
+        // lets use Camel's bean post processor on any existing route builder classes
+        // so the instance has some support for dependency injection
+        CamelBeanPostProcessor postProcessor = camelContext.adapt(ExtendedCamelContext.class).getBeanPostProcessor();
+        for (RoutesBuilder routeBuilder : routes) {
+            postProcessor.postProcessBeforeInitialization(routeBuilder, routeBuilder.getClass().getName());
+            postProcessor.postProcessAfterInitialization(routeBuilder, routeBuilder.getClass().getName());
+        }
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            LOG.debug("Adding routes into CamelContext from RoutesBuilder: {}", builder);
+            camelContext.addRoutes(builder);
+        }
+
         Set<ConfigureRouteTemplates> set = camelContext.getRegistry().findByType(ConfigureRouteTemplates.class);
         for (ConfigureRouteTemplates crt : set) {
             LOG.debug("Configuring route templates via: {}", crt);
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java b/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
similarity index 52%
copy from core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
copy to core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
index 60298b8..e54fa2e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/Resource.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
@@ -14,24 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
+package org.apache.camel.main.support;
 
-import java.io.IOException;
-import java.io.InputStream;
+import java.util.Map;
 
-/**
- * Describe a resource, such as a file or class path resource.
- */
-public interface Resource {
-    /**
-     * The location of the resource.
-     */
-    String getLocation();
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestConsumerFactory;
 
-    /**
-     * Returns an input stream that reads from the underlying resource.
-     * </p>
-     * Each invocation must return a new {@link InputStream} instance.
-     */
-    InputStream getInputStream() throws IOException;
+public final class MockRestConsumerFactory implements RestConsumerFactory {
+    @Override
+    public Consumer createConsumer(
+            CamelContext camelContext,
+            Processor processor,
+            String verb,
+            String basePath,
+            String uriTemplate,
+            String consumes,
+            String produces,
+            RestConfiguration configuration,
+            Map<String, Object> parameters) {
+        return null;
+    }
 }
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlRestsTest.java b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlRestsTest.java
index 998f139..77c27b8 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlRestsTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlRestsTest.java
@@ -17,18 +17,14 @@
 package org.apache.camel.main.xml;
 
 import java.util.List;
-import java.util.Map;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Consumer;
-import org.apache.camel.Processor;
 import org.apache.camel.main.Main;
+import org.apache.camel.main.support.MockRestConsumerFactory;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.model.rest.GetVerbDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.rest.VerbDefinition;
-import org.apache.camel.spi.RestConfiguration;
-import org.apache.camel.spi.RestConsumerFactory;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -38,49 +34,63 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 public class MainXmlRestsTest {
 
     @Test
-    public void testMainRestsCollector() throws Exception {
+    public void testMainRestsCollector() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-rests.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-rests.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorScan() throws Exception {
+    public void testMainRestsCollectorScan() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-res*.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-res*.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorScanWildcardDirClasspathPath() throws Exception {
+    public void testMainRestsCollectorScanWildcardDirClasspathPath() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/**/camel-res*.xml");
+        doTestMain(
+                "org/apache/camel/main/**/camel-res*.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorScanClasspathPrefix() throws Exception {
+    public void testMainRestsCollectorScanClasspathPrefix() {
         // will load XML from target/classes when testing
-        doTestMain("classpath:org/apache/camel/main/xml/camel-res*.xml");
+        doTestMain(
+                "classpath:org/apache/camel/main/xml/camel-res*.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorScanInDir() throws Exception {
-        doTestMain("file:src/test/resources/org/apache/camel/main/xml/camel-res*.xml");
+    public void testMainRestsCollectorScanInDir() {
+        doTestMain(
+                "file:src/test/resources/org/apache/camel/main/xml/camel-res*.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorScanWildcardDirFilePath() throws Exception {
-        doTestMain("file:src/test/resources/**/camel-res*.xml");
+    public void testMainRestsCollectorScanWildcardDirFilePath() {
+        doTestMain(
+                "file:src/test/resources/**/camel-res*.xml",
+                null);
     }
 
     @Test
-    public void testMainRestsCollectorFile() throws Exception {
+    public void testMainRestsCollectorFile() {
         doTestMain(
-                "file:src/test/resources/org/apache/camel/main/xml/camel-rests.xml,");
+                "file:src/test/resources/org/apache/camel/main/xml/camel-rests.xml,",
+                null);
     }
 
-    protected void doTestMain(String xmlRests) throws Exception {
+    protected void doTestMain(String includes, String excludes) {
         Main main = new Main();
         main.bind("restConsumerFactory", new MockRestConsumerFactory());
-        main.configure().withXmlRests(xmlRests);
+        main.configure().withRoutesIncludePattern(includes);
+        main.configure().withRoutesExcludePattern(excludes);
         main.start();
 
         CamelContext camelContext = main.getCamelContext();
@@ -102,15 +112,4 @@ public class MainXmlRestsTest {
 
         main.stop();
     }
-
-    private static final class MockRestConsumerFactory implements RestConsumerFactory {
-        @Override
-        public Consumer createConsumer(
-                CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
-                String consumes,
-                String produces, RestConfiguration configuration, Map<String, Object> parameters)
-                throws Exception {
-            return null;
-        }
-    }
 }
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTemplateTest.java b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTemplateTest.java
index 134a6ff..847b862 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTemplateTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTemplateTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.main.xml;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.main.Main;
+import org.apache.camel.main.support.MockRestConsumerFactory;
 import org.apache.camel.model.ModelCamelContext;
 import org.junit.jupiter.api.Test;
 
@@ -27,38 +28,50 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 public class MainXmlTemplateTest {
 
     @Test
-    public void testMainRoutesCollector() throws Exception {
+    public void testMainRoutesCollector() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-template.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-template.xml",
+                null);
     }
 
     @Test
-    public void testMainRoutesCollectorScan() throws Exception {
+    public void testMainRoutesCollectorScan() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-template*.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-template*.xml",
+                null);
     }
 
     @Test
-    public void testMainRoutesCollectorScanTwo() throws Exception {
+    public void testMainRoutesCollectorScanTwo() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-*.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-t*.xml",
+                null);
     }
 
     @Test
-    public void testMainRoutesCollectorScanWildcardDirClasspathPath() throws Exception {
+    public void testMainRoutesCollectorScanWildcardDirClasspathPath() {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/**/*.xml");
+        doTestMain(
+                "org/apache/camel/main/**/camel-t*.xml",
+                null);
     }
 
     @Test
-    public void testMainRoutesCollectorScanClasspathPrefix() throws Exception {
+    public void testMainRoutesCollectorScanClasspathPrefix() {
         // will load XML from target/classes when testing
-        doTestMain("classpath:org/apache/camel/main/xml/camel-*.xml");
+        doTestMain(
+                "classpath:org/apache/camel/main/xml/camel-t*.xml",
+                null);
     }
 
-    protected void doTestMain(String xmlRoutes) throws Exception {
+    protected void doTestMain(String includes, String excludes) {
         Main main = new Main();
-        main.configure().withXmlRouteTemplates(xmlRoutes);
+        main.bind("restConsumerFactory", new MockRestConsumerFactory());
+        main.configure().withRoutesIncludePattern(includes);
+        main.configure().withRoutesExcludePattern(excludes);
         main.start();
 
         CamelContext camelContext = main.getCamelContext();
@@ -68,5 +81,4 @@ public class MainXmlTemplateTest {
 
         main.stop();
     }
-
 }
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java
index fa36b88..44ac8f3 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/xml/MainXmlTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.main.xml;
 import org.apache.camel.CamelContext;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.main.Main;
+import org.apache.camel.main.support.MockRestConsumerFactory;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -29,58 +30,76 @@ public class MainXmlTest {
     @Test
     public void testMainRoutesCollector() throws Exception {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-dummy.xml,org/apache/camel/main/xml/camel-scan.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-dummy.xml,org/apache/camel/main/xml/camel-scan.xml",
+                null);
     }
 
     @Test
     public void testMainRoutesCollectorScan() throws Exception {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/xml/camel-*.xml");
+        doTestMain(
+                "org/apache/camel/main/xml/camel-*.xml",
+                "**/camel-rests.xml,**/camel-template.xml");
     }
 
     @Test
     public void testMainRoutesCollectorScanWildcardDirClasspathPath() throws Exception {
         // will load XML from target/classes when testing
-        doTestMain("org/apache/camel/main/**/*.xml");
+        doTestMain(
+                "org/apache/camel/main/**/*.xml",
+                "**/camel-rests.xml,**/camel-template.xml");
     }
 
     @Test
     public void testMainRoutesCollectorScanClasspathPrefix() throws Exception {
         // will load XML from target/classes when testing
-        doTestMain("classpath:org/apache/camel/main/xml/camel-*.xml");
+        doTestMain(
+                "classpath:org/apache/camel/main/xml/camel-*.xml",
+                "**/camel-rests.xml,**/camel-template.xml");
     }
 
     @Test
     public void testMainRoutesCollectorScanInJar() throws Exception {
         // will load XML from camel-core test JAR when testing
-        doTestMain("org/apache/camel/model/scan-*.xml");
+        doTestMain(
+                "org/apache/camel/model/scan-*.xml",
+                null);
     }
 
     @Test
     public void testMainRoutesCollectorScanInDir() throws Exception {
-        doTestMain("file:src/test/resources/org/apache/camel/main/xml/camel-*.xml");
+        doTestMain(
+                "file:src/test/resources/org/apache/camel/main/xml/camel-*.xml",
+                "**/camel-rests.xml,**/camel-template.xml");
     }
 
     @Test
     public void testMainRoutesCollectorScanWildcardDirFilePath() throws Exception {
-        doTestMain("file:src/test/resources/**/*.xml");
+        doTestMain(
+                "file:src/test/resources/**/*.xml",
+                "**/camel-rests.xml,**/camel-template.xml");
     }
 
     @Test
     public void testMainRoutesCollectorFile() throws Exception {
         doTestMain(
-                "file:src/test/resources/org/apache/camel/main/xml/camel-dummy.xml,file:src/test/resources/org/apache/camel/main/xml/camel-scan.xml,");
+                "file:src/test/resources/org/apache/camel/main/xml/camel-dummy.xml,file:src/test/resources/org/apache/camel/main/xml/camel-scan.xml,",
+                null);
     }
 
     @Test
     public void testMainRoutesCollectorScanInJarAndDir() throws Exception {
         doTestMain(
-                "classpath:org/apache/camel/main/xml/*dummy.xml,file:src/test/resources/org/apache/camel/main/xml/*scan.xml");
+                "classpath:org/apache/camel/main/xml/*dummy.xml,file:src/test/resources/org/apache/camel/main/xml/*scan.xml",
+                null);
     }
 
-    protected void doTestMain(String xmlRoutes) throws Exception {
+    protected void doTestMain(String includes, String excludes) throws Exception {
         Main main = new Main();
-        main.configure().withXmlRoutes(xmlRoutes);
+        main.bind("restConsumerFactory", new MockRestConsumerFactory());
+        main.configure().withRoutesIncludePattern(includes);
+        main.configure().withRoutesExcludePattern(excludes);
         main.start();
 
         CamelContext camelContext = main.getCamelContext();
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
index 34a931f..e0c31d4 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
@@ -191,9 +191,11 @@ public interface ManagedCamelContextMBean extends ManagedPerformanceCounterMBean
     @ManagedOperation(description = "Dumps the routes as XML")
     String dumpRoutesAsXml(boolean resolvePlaceholders, boolean resolveDelegateEndpoints) throws Exception;
 
+    @Deprecated
     @ManagedOperation(description = "Adds or updates existing routes from XML")
     void addOrUpdateRoutesFromXml(String xml) throws Exception;
 
+    @Deprecated
     @ManagedOperation(description = "Adds or updates existing routes from XML")
     void addOrUpdateRoutesFromXml(String xml, boolean urlDecode) throws Exception;
 
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
index f5e0896..304998a 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
@@ -107,6 +107,7 @@ public interface ManagedRouteMBean extends ManagedPerformanceCounterMBean {
     @ManagedOperation(description = "Dumps the route as XML")
     String dumpRouteAsXml(boolean resolvePlaceholders, boolean resolveDelegateEndpoints) throws Exception;
 
+    @Deprecated
     @ManagedOperation(description = "Updates the route from XML")
     void updateRouteFromXml(String xml) throws Exception;
 
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/AntPathMatcher.java b/core/camel-util/src/main/java/org/apache/camel/util/AntPathMatcher.java
index 851a2f4..217670e 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/AntPathMatcher.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/AntPathMatcher.java
@@ -69,6 +69,25 @@ public class AntPathMatcher {
         return match(pattern, path, true);
     }
 
+    public boolean anyMatch(String[] patterns, String path) {
+        return anyMatch(patterns, path, true);
+    }
+
+    public boolean anyMatch(String[] patterns, String path, boolean isCaseSensitive) {
+        if (patterns == null) {
+            return false;
+        }
+        if (patterns.length == 0) {
+            return false;
+        }
+        for (String pattern : patterns) {
+            if (match(pattern, path, isCaseSensitive)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public boolean matchStart(String pattern, String path) {
         return matchStart(pattern, path, true);
     }
@@ -83,7 +102,7 @@ public class AntPathMatcher {
 
     /**
      * Actually match the given <code>path</code> against the given <code>pattern</code>.
-     * 
+     *
      * @param  pattern         the pattern to match against
      * @param  path            the path String to test
      * @param  fullMatch       whether a full pattern match is required (else a pattern match as far as the given base
@@ -220,7 +239,7 @@ public class AntPathMatcher {
      * Tests whether or not a string matches against a pattern. The pattern may contain two special characters:<br>
      * '*' means zero or more characters<br>
      * '?' means one and only one character
-     * 
+     *
      * @param  pattern       pattern to match against. Must not be <code>null</code>.
      * @param  str           string which must be matched against the pattern. Must not be <code>null</code>.
      * @param  caseSensitive Whether or not matching should be performed case sensitively.
@@ -417,7 +436,7 @@ public class AntPathMatcher {
      * The given delimiters string is supposed to consist of any number of delimiter characters. Each of those
      * characters can be used to separate tokens. A delimiter is always a single character; for multi-character
      * delimiters, consider using <code>delimitedListToStringArray</code>
-     * 
+     *
      * @param  str        the String to tokenize
      * @param  delimiters the delimiter characters, assembled as String (each of those characters is individually
      *                    considered as delimiter).
diff --git a/core/camel-xml-io/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml b/core/camel-xml-io/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml
new file mode 100644
index 0000000..78de6b4
--- /dev/null
+++ b/core/camel-xml-io/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.xml.in.XmlRoutesBuilderLoader
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/XmlRoutesBuilderLoader.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/XmlRoutesBuilderLoader.java
new file mode 100644
index 0000000..5fc9e16
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/XmlRoutesBuilderLoader.java
@@ -0,0 +1,74 @@
+/*
+ * 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.xml.in;
+
+import java.io.InputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteTemplatesDefinition;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.RoutesBuilderLoader;
+import org.apache.camel.spi.annotations.JdkService;
+
+@JdkService("routes-loaders/xml")
+public class XmlRoutesBuilderLoader implements RoutesBuilderLoader, CamelContextAware {
+    public static final String NAMESPACE = "http://camel.apache.org/schema/spring";
+
+    private CamelContext camelContext;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                try (InputStream is = resource.getInputStream()) {
+                    RouteTemplatesDefinition templates = new ModelParser(is, NAMESPACE).parseRouteTemplatesDefinition();
+                    if (templates != null) {
+                        setRouteTemplateCollection(templates);
+                    }
+                }
+                try (InputStream is = resource.getInputStream()) {
+                    RestsDefinition rests = new ModelParser(is, NAMESPACE).parseRestsDefinition();
+                    if (rests != null) {
+                        setRestCollection(rests);
+                    }
+                }
+                try (InputStream is = resource.getInputStream()) {
+                    RoutesDefinition routes = new ModelParser(is, NAMESPACE).parseRoutesDefinition();
+                    if (routes != null) {
+                        setRouteCollection(routes);
+                    }
+                }
+            }
+        };
+    }
+}
diff --git a/core/camel-xml-jaxb/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml b/core/camel-xml-jaxb/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml
new file mode 100644
index 0000000..daa444e
--- /dev/null
+++ b/core/camel-xml-jaxb/src/generated/resources/META-INF/services/org/apache/camel/routes-loaders/xml
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.xml.jaxb.JaxbXmlRoutesBuilderLoader
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
index de2b2a1..b6268ba 100644
--- a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.xml.jaxb;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -24,6 +26,7 @@ import java.util.Map;
 import javax.xml.bind.Binder;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
@@ -41,6 +44,8 @@ import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.RouteTemplatesDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spi.TypeConverterRegistry;
 
@@ -186,4 +191,102 @@ public final class JaxbHelper {
 
         return type.cast(result);
     }
+
+    public static RoutesDefinition loadRoutesDefinition(CamelContext context, InputStream inputStream) throws Exception {
+        XmlConverter xmlConverter = newXmlConverter(context);
+        Document dom = xmlConverter.toDOMDocument(inputStream, null);
+
+        JAXBContext jaxbContext = getJAXBContext(context);
+
+        Map<String, String> namespaces = new LinkedHashMap<>();
+        extractNamespaces(dom, namespaces);
+
+        Binder<Node> binder = jaxbContext.createBinder();
+        Object result = binder.unmarshal(dom);
+
+        if (result == null) {
+            throw new JAXBException("Cannot unmarshal to RoutesDefinition using JAXB");
+        }
+
+        // can either be routes or a single route
+        RoutesDefinition answer;
+        if (result instanceof RouteDefinition) {
+            RouteDefinition route = (RouteDefinition) result;
+            answer = new RoutesDefinition();
+            applyNamespaces(route, namespaces);
+            answer.getRoutes().add(route);
+        } else if (result instanceof RoutesDefinition) {
+            answer = (RoutesDefinition) result;
+            for (RouteDefinition route : answer.getRoutes()) {
+                applyNamespaces(route, namespaces);
+            }
+        } else {
+            // ignore not supported type
+            return null;
+        }
+
+        return answer;
+    }
+
+    public static RouteTemplatesDefinition loadRouteTemplatesDefinition(CamelContext context, InputStream inputStream)
+            throws Exception {
+        XmlConverter xmlConverter = newXmlConverter(context);
+        Document dom = xmlConverter.toDOMDocument(inputStream, null);
+
+        JAXBContext jaxbContext = getJAXBContext(context);
+
+        Map<String, String> namespaces = new LinkedHashMap<>();
+        extractNamespaces(dom, namespaces);
+
+        Binder<Node> binder = jaxbContext.createBinder();
+        Object result = binder.unmarshal(dom);
+
+        if (result == null) {
+            throw new JAXBException("Cannot unmarshal to RouteTemplatesDefinition using JAXB");
+        }
+
+        // can either be routes or a single route
+        RouteTemplatesDefinition answer;
+        if (result instanceof RouteTemplateDefinition) {
+            RouteTemplateDefinition route = (RouteTemplateDefinition) result;
+            answer = new RouteTemplatesDefinition();
+            applyNamespaces(route.getRoute(), namespaces);
+            answer.getRouteTemplates().add(route);
+        } else if (result instanceof RouteTemplatesDefinition) {
+            answer = (RouteTemplatesDefinition) result;
+            for (RouteTemplateDefinition route : answer.getRouteTemplates()) {
+                applyNamespaces(route.getRoute(), namespaces);
+            }
+        } else {
+            // ignore not supported type
+            return null;
+        }
+
+        return answer;
+    }
+
+    public static RestsDefinition loadRestsDefinition(CamelContext context, InputStream inputStream) throws Exception {
+        // load routes using JAXB
+        Unmarshaller unmarshaller = getJAXBContext(context).createUnmarshaller();
+        Object result = unmarshaller.unmarshal(inputStream);
+
+        if (result == null) {
+            throw new IOException("Cannot unmarshal to rests using JAXB from input stream: " + inputStream);
+        }
+
+        // can either be routes or a single route
+        RestsDefinition answer;
+        if (result instanceof RestDefinition) {
+            RestDefinition rest = (RestDefinition) result;
+            answer = new RestsDefinition();
+            answer.getRests().add(rest);
+        } else if (result instanceof RestsDefinition) {
+            answer = (RestsDefinition) result;
+        } else {
+            // ignore not supported type
+            return null;
+        }
+
+        return answer;
+    }
 }
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXMLRoutesDefinitionLoader.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXMLRoutesDefinitionLoader.java
index a3c8113..2c7b46b 100644
--- a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXMLRoutesDefinitionLoader.java
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXMLRoutesDefinitionLoader.java
@@ -16,35 +16,12 @@
  */
 package org.apache.camel.xml.jaxb;
 
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.xml.bind.Binder;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.converter.jaxp.XmlConverter;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RouteTemplateDefinition;
-import org.apache.camel.model.RouteTemplatesDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.XMLRoutesDefinitionLoader;
 import org.apache.camel.spi.annotations.JdkService;
 
-import static org.apache.camel.xml.jaxb.JaxbHelper.applyNamespaces;
-import static org.apache.camel.xml.jaxb.JaxbHelper.extractNamespaces;
-import static org.apache.camel.xml.jaxb.JaxbHelper.getJAXBContext;
-import static org.apache.camel.xml.jaxb.JaxbHelper.newXmlConverter;
-
 /**
  * JAXB based {@link XMLRoutesDefinitionLoader}. This is the default loader used historically by Camel. The camel-xml-io
  * parser is a light-weight alternative.
@@ -54,102 +31,17 @@ public class JaxbXMLRoutesDefinitionLoader implements XMLRoutesDefinitionLoader
 
     @Override
     public Object loadRoutesDefinition(CamelContext context, InputStream inputStream) throws Exception {
-        XmlConverter xmlConverter = newXmlConverter(context);
-        Document dom = xmlConverter.toDOMDocument(inputStream, null);
-
-        JAXBContext jaxbContext = getJAXBContext(context);
-
-        Map<String, String> namespaces = new LinkedHashMap<>();
-        extractNamespaces(dom, namespaces);
-
-        Binder<Node> binder = jaxbContext.createBinder();
-        Object result = binder.unmarshal(dom);
-
-        if (result == null) {
-            throw new JAXBException("Cannot unmarshal to RoutesDefinition using JAXB");
-        }
-
-        // can either be routes or a single route
-        RoutesDefinition answer;
-        if (result instanceof RouteDefinition) {
-            RouteDefinition route = (RouteDefinition) result;
-            answer = new RoutesDefinition();
-            applyNamespaces(route, namespaces);
-            answer.getRoutes().add(route);
-        } else if (result instanceof RoutesDefinition) {
-            answer = (RoutesDefinition) result;
-            for (RouteDefinition route : answer.getRoutes()) {
-                applyNamespaces(route, namespaces);
-            }
-        } else {
-            // ignore not supported type
-            return null;
-        }
-
-        return answer;
+        return JaxbHelper.loadRoutesDefinition(context, inputStream);
     }
 
     @Override
     public Object loadRouteTemplatesDefinition(CamelContext context, InputStream inputStream) throws Exception {
-        XmlConverter xmlConverter = newXmlConverter(context);
-        Document dom = xmlConverter.toDOMDocument(inputStream, null);
-
-        JAXBContext jaxbContext = getJAXBContext(context);
-
-        Map<String, String> namespaces = new LinkedHashMap<>();
-        extractNamespaces(dom, namespaces);
-
-        Binder<Node> binder = jaxbContext.createBinder();
-        Object result = binder.unmarshal(dom);
-
-        if (result == null) {
-            throw new JAXBException("Cannot unmarshal to RouteTemplatesDefinition using JAXB");
-        }
-
-        // can either be routes or a single route
-        RouteTemplatesDefinition answer;
-        if (result instanceof RouteTemplateDefinition) {
-            RouteTemplateDefinition route = (RouteTemplateDefinition) result;
-            answer = new RouteTemplatesDefinition();
-            applyNamespaces(route.getRoute(), namespaces);
-            answer.getRouteTemplates().add(route);
-        } else if (result instanceof RouteTemplatesDefinition) {
-            answer = (RouteTemplatesDefinition) result;
-            for (RouteTemplateDefinition route : answer.getRouteTemplates()) {
-                applyNamespaces(route.getRoute(), namespaces);
-            }
-        } else {
-            // ignore not supported type
-            return null;
-        }
-
-        return answer;
+        return JaxbHelper.loadRouteTemplatesDefinition(context, inputStream);
     }
 
     @Override
     public Object loadRestsDefinition(CamelContext context, InputStream inputStream) throws Exception {
-        // load routes using JAXB
-        Unmarshaller unmarshaller = getJAXBContext(context).createUnmarshaller();
-        Object result = unmarshaller.unmarshal(inputStream);
-
-        if (result == null) {
-            throw new IOException("Cannot unmarshal to rests using JAXB from input stream: " + inputStream);
-        }
-
-        // can either be routes or a single route
-        RestsDefinition answer;
-        if (result instanceof RestDefinition) {
-            RestDefinition rest = (RestDefinition) result;
-            answer = new RestsDefinition();
-            answer.getRests().add(rest);
-        } else if (result instanceof RestsDefinition) {
-            answer = (RestsDefinition) result;
-        } else {
-            // ignore not supported type
-            return null;
-        }
-
-        return answer;
+        return JaxbHelper.loadRestsDefinition(context, inputStream);
     }
 
     @Override
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXmlRoutesBuilderLoader.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXmlRoutesBuilderLoader.java
new file mode 100644
index 0000000..df23f47
--- /dev/null
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbXmlRoutesBuilderLoader.java
@@ -0,0 +1,72 @@
+/*
+ * 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.xml.jaxb;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteTemplatesDefinition;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.RoutesBuilderLoader;
+import org.apache.camel.spi.annotations.JdkService;
+
+import static org.apache.camel.xml.jaxb.JaxbHelper.loadRestsDefinition;
+import static org.apache.camel.xml.jaxb.JaxbHelper.loadRouteTemplatesDefinition;
+import static org.apache.camel.xml.jaxb.JaxbHelper.loadRoutesDefinition;
+
+@JdkService("routes-loaders/xml")
+public class JaxbXmlRoutesBuilderLoader implements RoutesBuilderLoader, CamelContextAware {
+    public static final String NAMESPACE = "http://camel.apache.org/schema/spring";
+
+    private CamelContext camelContext;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                RouteTemplatesDefinition templates = loadRouteTemplatesDefinition(getCamelContext(), resource.getInputStream());
+                if (templates != null) {
+                    setRouteTemplateCollection(templates);
+                }
+
+                RestsDefinition rests = loadRestsDefinition(getCamelContext(), resource.getInputStream());
+                if (rests != null) {
+                    setRestCollection(rests);
+                }
+
+                RoutesDefinition routes = loadRoutesDefinition(getCamelContext(), resource.getInputStream());
+                if (routes != null) {
+                    setRouteCollection(routes);
+                }
+            }
+        };
+    }
+}
diff --git a/core/camel-xml-jaxb/src/main/resources/META-INF/LICENSE.txt b/core/camel-xml-jaxb/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/core/camel-xml-jaxb/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/core/camel-xml-jaxb/src/main/resources/META-INF/NOTICE.txt b/core/camel-xml-jaxb/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..8547fe7
--- /dev/null
+++ b/core/camel-xml-jaxb/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,15 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   This product includes software developed by the Indiana
+   University Extreme! Lab.  For further information please visit
+   http://www.extreme.indiana.edu/.
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.