You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/10/17 19:09:21 UTC

[camel] branch route-collector created (now 12b90dc)

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

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


      at 12b90dc  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

This branch includes the following new commits:

     new f727b5c  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new 8fd86c3  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new dba0c7f  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new 5b1147b  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new 80dc28a  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new b14e58a  CAMEL-14050: Polish Superivisiting route controller a bit, and fixed a test that was unpredicable.
     new 19db834  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new cbdcf4d  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
     new 12b90dc  CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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



[camel] 02/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit 8fd86c3c5208c69ad4372efa03e22d36b2e104c9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 15:06:27 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../camel/spring/boot/CamelAutoConfiguration.java  | 13 +++-
 ...Collector.java => RoutesCollectorListener.java} | 64 +++++-----------
 .../spring/boot/SpringBootRoutesCollector.java     | 85 ++++++++++++++++++++++
 .../boot/parent/SpringBootRefreshContextTest.java  |  4 +-
 ...utesCollector.java => BaseRoutesCollector.java} | 22 ++++--
 .../org/apache/camel/main/RoutesCollector.java     | 34 +++++++++
 6 files changed, 163 insertions(+), 59 deletions(-)

diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
index 6a5bd55..c155230 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
@@ -29,6 +29,7 @@ import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.component.properties.PropertiesParser;
 import org.apache.camel.main.DefaultConfigurationConfigurer;
+import org.apache.camel.main.RoutesCollector;
 import org.apache.camel.model.Model;
 import org.apache.camel.spi.BeanRepository;
 import org.apache.camel.spring.CamelBeanPostProcessor;
@@ -133,7 +134,6 @@ public class CamelAutoConfiguration {
         // lookup and configure SPI beans
         DefaultConfigurationConfigurer.afterPropertiesSet(camelContext);
 
-
         return camelContext;
     }
 
@@ -144,9 +144,16 @@ public class CamelAutoConfiguration {
 
     @Bean
     @ConditionalOnMissingBean(RoutesCollector.class)
-    RoutesCollector routesCollector(ApplicationContext applicationContext, CamelConfigurationProperties config) {
+    RoutesCollector routesCollector(ApplicationContext applicationContext) {
+        return new SpringBootRoutesCollector(applicationContext);
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(RoutesCollectorListener.class)
+    RoutesCollectorListener routesCollectorListener(ApplicationContext applicationContext, CamelConfigurationProperties config,
+                                                    RoutesCollector routesCollector) {
         Collection<CamelContextConfiguration> configurations = applicationContext.getBeansOfType(CamelContextConfiguration.class).values();
-        return new RoutesCollector(applicationContext, new ArrayList(configurations), config);
+        return new RoutesCollectorListener(applicationContext, new ArrayList(configurations), config, routesCollector);
     }
 
     /**
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java
similarity index 84%
rename from components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
rename to components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java
index 1858219..0c7c4fc 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.spring.boot;
 
-import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -29,9 +28,8 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.StartupListener;
 import org.apache.camel.main.MainDurationEventNotifier;
-import org.apache.camel.main.MainRoutesCollector;
+import org.apache.camel.main.RoutesCollector;
 import org.apache.camel.model.Model;
-import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.CamelEvent;
@@ -47,17 +45,16 @@ import org.springframework.context.ApplicationListener;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.Ordered;
-import org.springframework.core.io.Resource;
 
 /**
  * Collects routes and rests from the various sources (like Spring application context beans registry or opinionated
  * classpath locations) and injects these into the Camel context.
  */
-public class RoutesCollector implements ApplicationListener<ContextRefreshedEvent>, Ordered {
+public class RoutesCollectorListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {
 
     // Static collaborators
 
-    private static final Logger LOG = LoggerFactory.getLogger(RoutesCollector.class);
+    private static final Logger LOG = LoggerFactory.getLogger(RoutesCollectorListener.class);
 
     // Collaborators
 
@@ -67,13 +64,17 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
 
     private final CamelConfigurationProperties configurationProperties;
 
+    private final RoutesCollector springBootRoutesCollector;
+
     // Constructors
 
-    public RoutesCollector(ApplicationContext applicationContext, List<CamelContextConfiguration> camelContextConfigurations,
-                           CamelConfigurationProperties configurationProperties) {
+    public RoutesCollectorListener(ApplicationContext applicationContext, List<CamelContextConfiguration> camelContextConfigurations,
+                                   CamelConfigurationProperties configurationProperties,
+                                   RoutesCollector springBootRoutesCollector) {
         this.applicationContext = applicationContext;
         this.camelContextConfigurations = new ArrayList<>(camelContextConfigurations);
         this.configurationProperties = configurationProperties;
+        this.springBootRoutesCollector = springBootRoutesCollector;
     }
 
     // Overridden
@@ -87,8 +88,7 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
                 && camelContext.getStatus().isStopped()) {
             LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName());
 
-            MainRoutesCollector collector = new MainRoutesCollector();
-            final List<RoutesBuilder> routes = collector.collectRoutes(camelContext, configurationProperties);
+            final List<RoutesBuilder> routes = springBootRoutesCollector.collectRoutesFromRegistry(camelContext, configurationProperties);
 
             // sort routes according to ordered
             routes.sort(OrderedComparator.get());
@@ -105,12 +105,18 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
             try {
                 boolean scan = !configurationProperties.getXmlRoutes().equals("false");
                 if (scan) {
-                    loadXmlRoutes(applicationContext, camelContext, configurationProperties.getXmlRoutes());
+                    List<RoutesDefinition> defs = springBootRoutesCollector.collectXmlRoutesFromDirectory(camelContext, configurationProperties.getXmlRoutes());
+                    for (RoutesDefinition def : defs) {
+                        camelContext.getExtension(Model.class).addRouteDefinitions(def.getRoutes());
+                    }
                 }
 
                 boolean scanRests = !configurationProperties.getXmlRests().equals("false");
                 if (scanRests) {
-                    loadXmlRests(applicationContext, camelContext, configurationProperties.getXmlRests());
+                    List<RestsDefinition> defs = springBootRoutesCollector.collectXmlRestsFromDirectory(camelContext, configurationProperties.getXmlRests());
+                    for (RestsDefinition def : defs) {
+                        camelContext.getExtension(Model.class).addRestDefinitions(def.getRests(), true);
+                    }
                 }
 
                 for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
@@ -238,40 +244,6 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
 
     // Helpers
 
-
-    private void loadXmlRoutes(ApplicationContext applicationContext, CamelContext camelContext, String directory) throws Exception {
-        String[] parts = directory.split(",");
-        for (String part : parts) {
-            LOG.info("Loading additional Camel XML routes from: {}", part);
-            try {
-                Resource[] xmlRoutes = applicationContext.getResources(part);
-                for (Resource xmlRoute : xmlRoutes) {
-                    LOG.debug("Found XML route: {}", xmlRoute);
-                    RoutesDefinition routes = ModelHelper.loadRoutesDefinition(camelContext, xmlRoute.getInputStream());
-                    camelContext.getExtension(Model.class).addRouteDefinitions(routes.getRoutes());
-                }
-            } catch (FileNotFoundException e) {
-                LOG.debug("No XML routes found in {}. Skipping XML routes detection.", part);
-            }
-        }
-    }
-
-    private void loadXmlRests(ApplicationContext applicationContext, CamelContext camelContext, String directory) throws Exception {
-        String[] parts = directory.split(",");
-        for (String part : parts) {
-            LOG.info("Loading additional Camel XML rests from: {}", part);
-            try {
-                final Resource[] xmlRests = applicationContext.getResources(part);
-                for (final Resource xmlRest : xmlRests) {
-                    RestsDefinition rests = ModelHelper.loadRestsDefinition(camelContext, xmlRest.getInputStream());
-                    camelContext.getExtension(Model.class).addRestDefinitions(rests.getRests(), true);
-                }
-            } catch (FileNotFoundException e) {
-                LOG.debug("No XML rests found in {}. Skipping XML rests detection.", part);
-            }
-        }
-    }
-
     private void terminateMainControllerAfter(final CamelContext camelContext, int seconds, final AtomicBoolean completed, final CountDownLatch latch) {
         ScheduledExecutorService executorService = camelContext.getExecutorServiceManager().newSingleThreadScheduledExecutor(this, "CamelSpringBootTerminateTask");
         Runnable task = () -> {
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
new file mode 100644
index 0000000..3f5d7d3
--- /dev/null
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
@@ -0,0 +1,85 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.spring.boot;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.main.BaseRoutesCollector;
+import org.apache.camel.model.ModelHelper;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.Resource;
+
+/**
+ * Spring Boot {@link org.apache.camel.main.RoutesCollector}.
+ */
+public class SpringBootRoutesCollector extends BaseRoutesCollector {
+
+    private final ApplicationContext applicationContext;
+
+    public SpringBootRoutesCollector(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    @Override
+    public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception {
+        List<RoutesDefinition> answer = new ArrayList<>();
+
+        String[] parts = directory.split(",");
+        for (String part : parts) {
+            log.info("Loading additional Camel XML routes from: {}", part);
+            try {
+                Resource[] xmlRoutes = applicationContext.getResources(part);
+                for (Resource xmlRoute : xmlRoutes) {
+                    log.debug("Found XML route: {}", xmlRoute);
+                    RoutesDefinition routes = ModelHelper.loadRoutesDefinition(camelContext, xmlRoute.getInputStream());
+                    answer.add(routes);
+                }
+            } catch (FileNotFoundException e) {
+                log.debug("No XML routes found in {}. Skipping XML routes detection.", part);
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception {
+        List<RestsDefinition> answer = new ArrayList<>();
+
+        String[] parts = directory.split(",");
+        for (String part : parts) {
+            log.info("Loading additional Camel XML rests from: {}", part);
+            try {
+                final Resource[] xmlRests = applicationContext.getResources(part);
+                for (final Resource xmlRest : xmlRests) {
+                    RestsDefinition rests = ModelHelper.loadRestsDefinition(camelContext, xmlRest.getInputStream());
+                    answer.add(rests);
+                }
+            } catch (FileNotFoundException e) {
+                log.debug("No XML rests found in {}. Skipping XML rests detection.", part);
+            }
+        }
+
+        return answer;
+    }
+
+}
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
index 141685d..29d81a0 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
@@ -18,7 +18,7 @@ package org.apache.camel.spring.boot.parent;
 
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spring.boot.RoutesCollector;
+import org.apache.camel.spring.boot.RoutesCollectorListener;
 import org.junit.Test;
 import org.springframework.boot.WebApplicationType;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -36,7 +36,7 @@ public class SpringBootRefreshContextTest {
         parent.refresh();
         ConfigurableApplicationContext context = new SpringApplicationBuilder(Configuration.class).web(WebApplicationType.NONE).parent(parent).run();
         ContextRefreshedEvent refreshEvent = new ContextRefreshedEvent(context);
-        RoutesCollector collector = context.getBean(RoutesCollector.class);
+        RoutesCollectorListener collector = context.getBean(RoutesCollectorListener.class);
         collector.onApplicationEvent(refreshEvent); //no changes should happen here
     }
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
similarity index 82%
rename from core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java
rename to core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
index fe5c2da..38cbfb9 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
@@ -23,6 +23,8 @@ import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -32,14 +34,15 @@ import org.slf4j.LoggerFactory;
  * Collects routes and rests from the various sources (like registry or opinionated
  * classpath locations) and injects these into the Camel context.
  */
-public class MainRoutesCollector {
+public abstract class BaseRoutesCollector implements RoutesCollector {
 
     // TODO: Add load routes from xml and rest
     // TODO: Base class and extended for spring-boot etc
+    // TODO: Add to camel main that it uses route collector
 
-    private static final Logger LOG = LoggerFactory.getLogger(MainRoutesCollector.class);
+    protected final Logger log = LoggerFactory.getLogger(getClass());
 
-    public List<RoutesBuilder> collectRoutes(CamelContext camelContext, DefaultConfigurationProperties configurationProperties) {
+    public List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, DefaultConfigurationProperties configurationProperties) {
         final List<RoutesBuilder> routes = new ArrayList<>();
 
         final AntPathMatcher matcher = new AntPathMatcher();
@@ -63,7 +66,7 @@ public class MainRoutesCollector {
                     for (String part : parts) {
                         // must negate when excluding, and hence !
                         match = !matcher.match(part, name);
-                        LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        log.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
                         if (!match) {
                             break;
                         }
@@ -81,7 +84,7 @@ public class MainRoutesCollector {
                     for (String part : parts) {
                         // must negate when excluding, and hence !
                         match = !matcher.match(part, name);
-                        LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        log.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
                         if (!match) {
                             break;
                         }
@@ -92,22 +95,25 @@ public class MainRoutesCollector {
                     String[] parts = include.split(",");
                     for (String part : parts) {
                         match = matcher.match(part, name);
-                        LOG.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
+                        log.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
                         if (match) {
                             break;
                         }
                     }
                 }
-                LOG.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match);
+                log.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match);
                 if (match) {
                     routes.add(routesBuilder);
                 }
             }
 
-
         }
 
         return routes;
     }
 
+    public abstract List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception;
+
+    public abstract List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception;
+
 }
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
new file mode 100644
index 0000000..33fabb1
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesCollector.java
@@ -0,0 +1,34 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.main;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+
+public interface RoutesCollector {
+
+    List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, DefaultConfigurationProperties configurationProperties);
+
+    List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception;
+
+    List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception;
+
+}


[camel] 03/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit dba0c7ff4c670986ea31f73e42abec6f85170e76
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 15:12:41 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../spring/boot/CamelConfigurationProperties.java  |  63 +++++-------
 .../camel/main/DefaultConfigurationProperties.java | 107 +++++++++++++++------
 .../camel-main-configuration-metadata.json         |  14 +++
 3 files changed, 114 insertions(+), 70 deletions(-)

diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
index 3018a8d..8e06364 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
@@ -47,30 +47,6 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
      */
     private boolean warnOnEarlyShutdown = true;
 
-    /**
-     * 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
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    private String xmlRoutes = "classpath:camel/*.xml";
-
-    /**
-     * 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
-     *
-     * Multiple directories can be specified and separated by comma, such as:
-     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
-     */
-    private String xmlRests = "classpath:camel-rest/*.xml";
-
     // Default Properties via camel-main
     // ---------------------------------
 
@@ -457,6 +433,30 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
      */
     private String javaRoutesExcludePattern;
 
+    /**
+     * 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
+     *
+     * Multiple directories can be specified and separated by comma, such as:
+     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+     */
+    private String xmlRoutes = "classpath:camel/*.xml";
+
+    /**
+     * 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
+     *
+     * Multiple directories can be specified and separated by comma, such as:
+     * file:/myapp/mycamel/&#42;.xml,file:/myapp/myothercamel/&#42;.xml
+     */
+    private String xmlRests = "classpath:camel-rest/*.xml";
+
     // Getters & setters
     // -----------------
 
@@ -484,19 +484,4 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
         this.warnOnEarlyShutdown = warnOnEarlyShutdown;
     }
 
-    public String getXmlRoutes() {
-        return xmlRoutes;
-    }
-
-    public void setXmlRoutes(String xmlRoutes) {
-        this.xmlRoutes = xmlRoutes;
-    }
-
-    public String getXmlRests() {
-        return xmlRests;
-    }
-
-    public void setXmlRests(String xmlRests) {
-        this.xmlRests = xmlRests;
-    }
 }
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 fdd1c66..e8794c5 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
@@ -71,31 +71,10 @@ public abstract class DefaultConfigurationProperties<T> {
     private String routeFilterExcludePattern;
     private boolean beanIntrospectionExtendedStatistics;
     private LoggingLevel beanIntrospectionLoggingLevel;
-    /**
-     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
-     * The exclusive filtering takes precedence over inclusive filtering.
-     * The pattern is using Ant-path style pattern.
-     *
-     * Multiple patterns can be specified separated by comma.
-     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
-     * To include all routes form a specific package use: com/mycompany/foo/&#42;
-     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
-     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
-     */
     private String javaRoutesIncludePattern;
-
-    /**
-     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
-     * The exclusive filtering takes precedence over inclusive filtering.
-     * The pattern is using Ant-path style pattern.
-     * Multiple patterns can be specified separated by comma.
-     *
-     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
-     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
-     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
-     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
-     */
     private String javaRoutesExcludePattern;
+    private String xmlRoutes = "classpath:camel/*.xml";
+    private String xmlRests = "classpath:camel-rest/*.xml";
 
     // getter and setters
     // --------------------------------------------------------------
@@ -767,6 +746,42 @@ 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
+     *
+     * 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 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
+     *
+     * 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;
+    }
+
     // fluent builders
     // --------------------------------------------------------------
 
@@ -1237,9 +1252,9 @@ public abstract class DefaultConfigurationProperties<T> {
      * The pattern matches by node and route id's
      * Multiple patterns can be separated by comma.
      */
-    public DefaultConfigurationProperties withTracingPattern(String tracingPattern) {
+    public T withTracingPattern(String tracingPattern) {
         this.tracingPattern = tracingPattern;
-        return this;
+        return (T) this;
     }
 
     /**
@@ -1256,9 +1271,9 @@ public abstract class DefaultConfigurationProperties<T> {
      * 3. regular expression match, returns true
      * 4. otherwise returns false
      */
-    public DefaultConfigurationProperties withMdcLoggingKeysPattern(String mdcLoggingKeysPattern) {
+    public T withMdcLoggingKeysPattern(String mdcLoggingKeysPattern) {
         this.mdcLoggingKeysPattern = mdcLoggingKeysPattern;
-        return this;
+        return (T) this;
     }
 
     /**
@@ -1272,9 +1287,9 @@ public abstract class DefaultConfigurationProperties<T> {
      * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
      * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
      */
-    public DefaultConfigurationProperties withJavaRoutesIncludePattern(String javaRoutesIncludePattern) {
+    public T withJavaRoutesIncludePattern(String javaRoutesIncludePattern) {
         this.javaRoutesIncludePattern = javaRoutesIncludePattern;
-        return this;
+        return (T) this;
     }
 
     /**
@@ -1288,8 +1303,38 @@ public abstract class DefaultConfigurationProperties<T> {
      * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
      * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
      */
-    public DefaultConfigurationProperties withJavaRoutesExcludePattern(String javaRoutesExcludePattern) {
+    public T withJavaRoutesExcludePattern(String javaRoutesExcludePattern) {
         this.javaRoutesExcludePattern = javaRoutesExcludePattern;
-        return this;
+        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:
+     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+     *
+     * 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 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
+     *
+     * 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;
     }
 }
diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
index d0f9a75..e0c3bfe 100644
--- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
@@ -380,6 +380,20 @@
 			"description":"To turn on MDC logging"
 		},
 		{
+			"name":"camel.main.xml-rests",
+			"type":"java.lang.String",
+			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
+			"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 Multiple directories can be specified and separated by comma, such as: file:\/myapp\/mycamel\/&#42;.xml,file:\/myapp\/myothercamel\/&#42;.xml",
+			"defaultValue":"classpath:camel-rest\/*.xml"
+		},
+		{
+			"name":"camel.main.xml-routes",
+			"type":"java.lang.String",
+			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
+			"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 Multiple directories can be specified and separated by comma, such as: file:\/myapp\/mycamel\/&#42;.xml,file:\/myapp\/myothercamel\/&#42;.xml",
+			"defaultValue":"classpath:camel\/*.xml"
+		},
+		{
 			"name":"camel.hystrix.allow-maximum-size-to-diverge-from-core-size",
 			"type":"java.lang.Boolean",
 			"sourceType":"org.apache.camel.main.HystrixConfigurationProperties",


[camel] 01/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit f727b5ce91c110eadd05968982dbfeca01a5b1ac
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 13:43:24 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../spring/boot/CamelConfigurationProperties.java  |  67 +++++------
 .../apache/camel/spring/boot/RoutesCollector.java  |  69 +-----------
 .../camel/main/DefaultConfigurationProperties.java | 124 +++++++++++++++++++++
 .../org/apache/camel/main/MainRoutesCollector.java | 113 +++++++++++++++++++
 .../camel-main-configuration-metadata.json         |  12 ++
 5 files changed, 278 insertions(+), 107 deletions(-)

diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
index 9f33bac..3018a8d 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
@@ -48,32 +48,6 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
     private boolean warnOnEarlyShutdown = true;
 
     /**
-     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
-     * The exclusive filtering takes precedence over inclusive filtering.
-     * The pattern is using Ant-path style pattern.
-     *
-     * Multiple patterns can be specified separated by comma.
-     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
-     * To include all routes form a specific package use: com/mycompany/foo/&#42;
-     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
-     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
-     */
-    private String javaRoutesIncludePattern;
-
-    /**
-     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
-     * The exclusive filtering takes precedence over inclusive filtering.
-     * The pattern is using Ant-path style pattern.
-     * Multiple patterns can be specified separated by comma.
-     *
-     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
-     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
-     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
-     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
-     */
-    private String javaRoutesExcludePattern;
-
-    /**
      * Directory to scan for adding additional XML routes.
      * You can turn this off by setting the value to false.
      *
@@ -457,6 +431,31 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
      */
     private LoggingLevel beanIntrospectionLoggingLevel;
 
+    /**
+     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma.
+     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
+     * To include all routes form a specific package use: com/mycompany/foo/&#42;
+     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
+     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
+     */
+    private String javaRoutesIncludePattern;
+
+    /**
+     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     *
+     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
+     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
+     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
+     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
+     */
+    private String javaRoutesExcludePattern;
 
     // Getters & setters
     // -----------------
@@ -485,22 +484,6 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
         this.warnOnEarlyShutdown = warnOnEarlyShutdown;
     }
 
-    public String getJavaRoutesIncludePattern() {
-        return javaRoutesIncludePattern;
-    }
-
-    public void setJavaRoutesIncludePattern(String javaRoutesIncludePattern) {
-        this.javaRoutesIncludePattern = javaRoutesIncludePattern;
-    }
-
-    public String getJavaRoutesExcludePattern() {
-        return javaRoutesExcludePattern;
-    }
-
-    public void setJavaRoutesExcludePattern(String javaRoutesExcludePattern) {
-        this.javaRoutesExcludePattern = javaRoutesExcludePattern;
-    }
-
     public String getXmlRoutes() {
         return xmlRoutes;
     }
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
index cb02311..1858219 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
@@ -17,7 +17,6 @@
 package org.apache.camel.spring.boot;
 
 import java.io.FileNotFoundException;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -30,6 +29,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.StartupListener;
 import org.apache.camel.main.MainDurationEventNotifier;
+import org.apache.camel.main.MainRoutesCollector;
 import org.apache.camel.model.Model;
 import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
@@ -40,7 +40,6 @@ import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.support.EventNotifierSupport;
 import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.service.ServiceHelper;
-import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
@@ -49,7 +48,6 @@ import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.Ordered;
 import org.springframework.core.io.Resource;
-import org.springframework.util.AntPathMatcher;
 
 /**
  * Collects routes and rests from the various sources (like Spring application context beans registry or opinionated
@@ -89,68 +87,8 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
                 && camelContext.getStatus().isStopped()) {
             LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName());
 
-            final AntPathMatcher matcher = new AntPathMatcher();
-            final List<RoutesBuilder> routes = new ArrayList<>();
-            for (RoutesBuilder routesBuilder : applicationContext.getBeansOfType(RoutesBuilder.class, configurationProperties.isIncludeNonSingletons(), true).values()) {
-                // filter out abstract classes
-                boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers());
-                if (!abs) {
-                    String name = routesBuilder.getClass().getName();
-                    // make name as path so we can use ant path matcher
-                    name = name.replace('.', '/');
-
-                    String exclude = configurationProperties.getJavaRoutesExcludePattern();
-                    String include = configurationProperties.getJavaRoutesIncludePattern();
-
-                    boolean match = !"false".equals(include);
-                    // exclude take precedence over include
-                    if (match && ObjectHelper.isNotEmpty(exclude)) {
-                        // there may be multiple separated by comma
-                        String[] parts = exclude.split(",");
-                        for (String part : parts) {
-                            // must negate when excluding, and hence !
-                            match = !matcher.match(part, name);
-                            LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
-                            if (!match) {
-                                break;
-                            }
-                        }
-                    }
-                    // special support for testing with @ExcludeRoutes annotation with camel-test-spring
-                    exclude = System.getProperty("CamelTestSpringExcludeRoutes");
-                    // exclude take precedence over include
-                    if (match && ObjectHelper.isNotEmpty(exclude)) {
-                        // this property is a comma separated list of FQN class names, so we need to make
-                        // name as path so we can use ant patch matcher
-                        exclude = exclude.replace('.', '/');
-                        // there may be multiple separated by comma
-                        String[] parts = exclude.split(",");
-                        for (String part : parts) {
-                            // must negate when excluding, and hence !
-                            match = !matcher.match(part, name);
-                            LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
-                            if (!match) {
-                                break;
-                            }
-                        }
-                    }
-                    if (match && ObjectHelper.isNotEmpty(include)) {
-                        // there may be multiple separated by comma
-                        String[] parts = include.split(",");
-                        for (String part : parts) {
-                            match = matcher.match(part, name);
-                            LOG.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
-                            if (match) {
-                                break;
-                            }
-                        }
-                    }
-                    LOG.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match);
-                    if (match) {
-                        routes.add(routesBuilder);
-                    }
-                }
-            }
+            MainRoutesCollector collector = new MainRoutesCollector();
+            final List<RoutesBuilder> routes = collector.collectRoutes(camelContext, configurationProperties);
 
             // sort routes according to ordered
             routes.sort(OrderedComparator.get());
@@ -300,6 +238,7 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
 
     // Helpers
 
+
     private void loadXmlRoutes(ApplicationContext applicationContext, CamelContext camelContext, String directory) throws Exception {
         String[] parts = directory.split(",");
         for (String part : parts) {
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 3e92f77..fdd1c66 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
@@ -71,6 +71,31 @@ public abstract class DefaultConfigurationProperties<T> {
     private String routeFilterExcludePattern;
     private boolean beanIntrospectionExtendedStatistics;
     private LoggingLevel beanIntrospectionLoggingLevel;
+    /**
+     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma.
+     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
+     * To include all routes form a specific package use: com/mycompany/foo/&#42;
+     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
+     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
+     */
+    private String javaRoutesIncludePattern;
+
+    /**
+     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     *
+     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
+     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
+     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
+     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
+     */
+    private String javaRoutesExcludePattern;
 
     // getter and setters
     // --------------------------------------------------------------
@@ -704,6 +729,44 @@ public abstract class DefaultConfigurationProperties<T> {
         this.beanIntrospectionLoggingLevel = beanIntrospectionLoggingLevel;
     }
 
+    public String getJavaRoutesIncludePattern() {
+        return javaRoutesIncludePattern;
+    }
+
+    /**
+     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma.
+     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
+     * To include all routes form a specific package use: com/mycompany/foo/&#42;
+     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
+     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
+     */
+    public void setJavaRoutesIncludePattern(String javaRoutesIncludePattern) {
+        this.javaRoutesIncludePattern = javaRoutesIncludePattern;
+    }
+
+    public String getJavaRoutesExcludePattern() {
+        return javaRoutesExcludePattern;
+    }
+
+    /**
+     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     *
+     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
+     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
+     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
+     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
+     */
+    public void setJavaRoutesExcludePattern(String javaRoutesExcludePattern) {
+        this.javaRoutesExcludePattern = javaRoutesExcludePattern;
+    }
+
     // fluent builders
     // --------------------------------------------------------------
 
@@ -1168,4 +1231,65 @@ public abstract class DefaultConfigurationProperties<T> {
         return (T) this;
     }
 
+    /**
+     * Tracing pattern to match which node EIPs to trace.
+     * For example to match all To EIP nodes, use to*.
+     * The pattern matches by node and route id's
+     * Multiple patterns can be separated by comma.
+     */
+    public DefaultConfigurationProperties withTracingPattern(String tracingPattern) {
+        this.tracingPattern = tracingPattern;
+        return this;
+    }
+
+    /**
+     * Sets the pattern used for determine which custom MDC keys to propagate during message routing when
+     * the routing engine continues routing asynchronously for the given message. Setting this pattern to * will
+     * propagate all custom keys. Or setting the pattern to foo*,bar* will propagate any keys starting with
+     * either foo or bar.
+     * Notice that a set of standard Camel MDC keys are always propagated which starts with camel. as key name.
+     *
+     * The match rules are applied in this order (case insensitive):
+     *
+     * 1. exact match, returns true
+     * 2. wildcard match (pattern ends with a * and the name starts with the pattern), returns true
+     * 3. regular expression match, returns true
+     * 4. otherwise returns false
+     */
+    public DefaultConfigurationProperties withMdcLoggingKeysPattern(String mdcLoggingKeysPattern) {
+        this.mdcLoggingKeysPattern = mdcLoggingKeysPattern;
+        return this;
+    }
+
+    /**
+     * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     *
+     * Multiple patterns can be specified separated by comma.
+     * For example to include all classes starting with Foo use: &#42;&#42;/Foo*
+     * To include all routes form a specific package use: com/mycompany/foo/&#42;
+     * To include all routes form a specific package and its sub-packages use double wildcards: com/mycompany/foo/&#42;&#42;
+     * And to include all routes from two specific packages use: com/mycompany/foo/&#42;,com/mycompany/stuff/&#42;
+     */
+    public DefaultConfigurationProperties withJavaRoutesIncludePattern(String javaRoutesIncludePattern) {
+        this.javaRoutesIncludePattern = javaRoutesIncludePattern;
+        return this;
+    }
+
+    /**
+     * Used for exclusive filtering component scanning of RouteBuilder classes with @Component annotation.
+     * The exclusive filtering takes precedence over inclusive filtering.
+     * The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     *
+     * For example to exclude all classes starting with Bar use: &#42;&#42;/Bar&#42;
+     * To exclude all routes form a specific package use: com/mycompany/bar/&#42;
+     * To exclude all routes form a specific package and its sub-packages use double wildcards: com/mycompany/bar/&#42;&#42;
+     * And to exclude all routes from two specific packages use: com/mycompany/bar/&#42;,com/mycompany/stuff/&#42;
+     */
+    public DefaultConfigurationProperties withJavaRoutesExcludePattern(String javaRoutesExcludePattern) {
+        this.javaRoutesExcludePattern = javaRoutesExcludePattern;
+        return this;
+    }
 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java
new file mode 100644
index 0000000..fe5c2da
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainRoutesCollector.java
@@ -0,0 +1,113 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.main;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.util.AntPathMatcher;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Collects routes and rests from the various sources (like registry or opinionated
+ * classpath locations) and injects these into the Camel context.
+ */
+public class MainRoutesCollector {
+
+    // TODO: Add load routes from xml and rest
+    // TODO: Base class and extended for spring-boot etc
+
+    private static final Logger LOG = LoggerFactory.getLogger(MainRoutesCollector.class);
+
+    public List<RoutesBuilder> collectRoutes(CamelContext camelContext, DefaultConfigurationProperties configurationProperties) {
+        final List<RoutesBuilder> routes = new ArrayList<>();
+
+        final AntPathMatcher matcher = new AntPathMatcher();
+        Set<RoutesBuilder> builders = camelContext.getRegistry().findByType(RoutesBuilder.class);
+        for (RoutesBuilder routesBuilder : builders) {
+            // filter out abstract classes
+            boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers());
+            if (!abs) {
+                String name = routesBuilder.getClass().getName();
+                // make name as path so we can use ant path matcher
+                name = name.replace('.', '/');
+
+                String exclude = configurationProperties.getJavaRoutesExcludePattern();
+                String include = configurationProperties.getJavaRoutesIncludePattern();
+
+                boolean match = !"false".equals(include);
+                // exclude take precedence over include
+                if (match && ObjectHelper.isNotEmpty(exclude)) {
+                    // there may be multiple separated by comma
+                    String[] parts = exclude.split(",");
+                    for (String part : parts) {
+                        // must negate when excluding, and hence !
+                        match = !matcher.match(part, name);
+                        LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        if (!match) {
+                            break;
+                        }
+                    }
+                }
+                // special support for testing with @ExcludeRoutes annotation with camel-test-spring
+                exclude = System.getProperty("CamelTestSpringExcludeRoutes");
+                // exclude take precedence over include
+                if (match && ObjectHelper.isNotEmpty(exclude)) {
+                    // this property is a comma separated list of FQN class names, so we need to make
+                    // name as path so we can use ant patch matcher
+                    exclude = exclude.replace('.', '/');
+                    // there may be multiple separated by comma
+                    String[] parts = exclude.split(",");
+                    for (String part : parts) {
+                        // must negate when excluding, and hence !
+                        match = !matcher.match(part, name);
+                        LOG.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        if (!match) {
+                            break;
+                        }
+                    }
+                }
+                if (match && ObjectHelper.isNotEmpty(include)) {
+                    // there may be multiple separated by comma
+                    String[] parts = include.split(",");
+                    for (String part : parts) {
+                        match = matcher.match(part, name);
+                        LOG.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
+                        if (match) {
+                            break;
+                        }
+                    }
+                }
+                LOG.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match);
+                if (match) {
+                    routes.add(routesBuilder);
+                }
+            }
+
+
+        }
+
+        return routes;
+    }
+
+}
diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
index 8548426..d0f9a75 100644
--- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
@@ -147,6 +147,18 @@
 			"defaultValue":"true"
 		},
 		{
+			"name":"camel.main.java-routes-exclude-pattern",
+			"type":"java.lang.String",
+			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
+			"description":"Used for exclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to exclude all classes starting with Bar use: &#42;&#42;\/Bar&#42; To exclude all routes form a specific package use: com\/mycompany\/bar\/&#42; To exclude all routes form a specific package and i [...]
+		},
+		{
+			"name":"camel.main.java-routes-include-pattern",
+			"type":"java.lang.String",
+			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
+			"description":"Used for inclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to include all classes starting with Foo use: &#42;&#42;\/Foo To include all routes form a specific package use: com\/mycompany\/foo\/&#42; To include all routes form a specific package and its su [...]
+		},
+		{
 			"name":"camel.main.jmx-create-connector",
 			"type":"boolean",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",


[camel] 05/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit 80dc28aea98279569536b534de58559643849e7f
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 18:54:59 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../spring/boot/SpringBootRoutesCollector.java     |  6 +--
 .../org/apache/camel/main/BaseMainSupport.java     | 21 +++++---
 ...sCollector.java => DefaultRoutesCollector.java} | 57 ++++++++++++++++++++--
 .../org/apache/camel/main/RoutesConfigurer.java    | 34 ++++++++++---
 4 files changed, 98 insertions(+), 20 deletions(-)

diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
index e2a30a1..d6b446f 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
@@ -21,10 +21,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.main.BaseRoutesCollector;
-import org.apache.camel.main.DefaultConfigurationProperties;
+import org.apache.camel.main.DefaultRoutesCollector;
 import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
@@ -34,7 +32,7 @@ import org.springframework.core.io.Resource;
 /**
  * Spring Boot {@link org.apache.camel.main.RoutesCollector}.
  */
-public class SpringBootRoutesCollector extends BaseRoutesCollector {
+public class SpringBootRoutesCollector extends DefaultRoutesCollector {
 
     private final ApplicationContext applicationContext;
 
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 ad8caf5..c3816a5 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
@@ -51,7 +51,6 @@ import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.PropertyConfigurer;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.support.LifecycleStrategySupport;
-import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.service.ServiceSupport;
@@ -81,6 +80,7 @@ public abstract class BaseMainSupport extends ServiceSupport {
 
     protected final List<MainListener> listeners = new ArrayList<>();
     protected final MainConfigurationProperties mainConfigurationProperties = new MainConfigurationProperties();
+    protected RoutesCollector routesCollector = new DefaultRoutesCollector();
     protected List<RoutesBuilder> routeBuilders = new ArrayList<>();
     protected String routeBuilderClasses;
     protected List<Object> configurations = new ArrayList<>();
@@ -210,6 +210,17 @@ public abstract class BaseMainSupport extends ServiceSupport {
         configurations.add(configuration);
     }
 
+    public RoutesCollector getRoutesCollector() {
+        return routesCollector;
+    }
+
+    /**
+     * To use a custom {@link RoutesCollector}.
+     */
+    public void setRoutesCollector(RoutesCollector routesCollector) {
+        this.routesCollector = routesCollector;
+    }
+
     public String getRouteBuilderClasses() {
         return routeBuilderClasses;
     }
@@ -519,11 +530,9 @@ public abstract class BaseMainSupport extends ServiceSupport {
 
         // try to load the route builders
         loadRouteBuilders(camelContext);
-        // sort routes according to ordered
-        routeBuilders.sort(OrderedComparator.get());
-        for (RoutesBuilder routeBuilder : routeBuilders) {
-            camelContext.addRoutes(routeBuilder);
-        }
+        // then configure and add the routes
+        RoutesConfigurer configurer = new RoutesConfigurer(routesCollector, routeBuilders);
+        configurer.configureRoutes(camelContext, mainConfigurationProperties);
         // register lifecycle so we are notified in Camel is stopped from JMX or somewhere else
         camelContext.addLifecycleStrategy(new MainLifecycleStrategy(completed, latch));
         // allow to do configuration before its started
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
similarity index 67%
rename from core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
rename to core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
index 17fe2a3..2b64ff9 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultRoutesCollector.java
@@ -16,6 +16,8 @@
  */
 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.List;
@@ -23,17 +25,20 @@ import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.model.ModelHelper;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Base {@link RoutesCollector}.
+ * A default {@link RoutesCollector}.
  */
-public abstract class BaseRoutesCollector implements RoutesCollector {
-
-    // TODO: Add to camel main that it uses route collector
+public class DefaultRoutesCollector implements RoutesCollector {
 
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
@@ -105,4 +110,48 @@ public abstract class BaseRoutesCollector implements RoutesCollector {
         return routes;
     }
 
+    @Override
+    public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) {
+        List<RoutesDefinition> answer = new ArrayList<>();
+
+        String[] parts = directory.split(",");
+        for (String part : parts) {
+            log.info("Loading additional Camel XML routes from: {}", part);
+            try {
+                InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, part);
+                log.debug("Found XML route: {}", is);
+                RoutesDefinition routes = ModelHelper.loadRoutesDefinition(camelContext, is);
+                answer.add(routes);
+            } catch (FileNotFoundException e) {
+                log.debug("No XML routes found in {}. Skipping XML routes detection.", part);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) {
+        List<RestsDefinition> answer = new ArrayList<>();
+
+        String[] parts = directory.split(",");
+        for (String part : parts) {
+            log.info("Loading additional Camel XML rests from: {}", part);
+            try {
+                InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, part);
+                log.debug("Found XML rest: {}", is);
+                RestsDefinition rests = ModelHelper.loadRestsDefinition(camelContext, is);
+                answer.add(rests);
+            } catch (FileNotFoundException e) {
+                log.debug("No XML rests found in {}. Skipping XML rests detection.", part);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
+        return answer;
+    }
+
 }
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 fd18ad4..589988e 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
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.main;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.camel.CamelContext;
@@ -36,16 +37,33 @@ public class RoutesConfigurer {
     private static final Logger LOG = LoggerFactory.getLogger(RoutesConfigurer.class);
 
     private final RoutesCollector routesCollector;
+    private final List<RoutesBuilder> routesBuilders;
 
+    /**
+     * Creates a new routes configurer
+     *
+     * @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;
     }
 
     /**
      * Collects routes and rests from the various sources (like registry or opinionated
-     * classpath locations) and injects these into the Camel context.
+     * classpath locations) and injects (adds) these into the Camel context.
      *
-     * @param camelContext  the Camel Context
+     * @param camelContext  the Camel context
      * @param config        the configuration
      */
     public void configureRoutes(CamelContext camelContext, DefaultConfigurationProperties config) {
@@ -56,18 +74,21 @@ public class RoutesConfigurer {
                         config.getJavaRoutesExcludePattern(),
                         config.getJavaRoutesIncludePattern());
 
+                // add newly discovered routes
+                routesBuilders.addAll(routes);
                 // sort routes according to ordered
-                routes.sort(OrderedComparator.get());
+                routesBuilders.sort(OrderedComparator.get());
                 // then add the routes
-                for (RoutesBuilder routesBuilder : routes) {
-                    LOG.debug("Injecting following route into the CamelContext: {}", routesBuilder);
-                    camelContext.addRoutes(routesBuilder);
+                for (RoutesBuilder builder : routesBuilders) {
+                    LOG.debug("Adding routes into CamelContext from RoutesBuilder: {}", builder);
+                    camelContext.addRoutes(builder);
                 }
 
                 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());
                     }
                 }
@@ -76,6 +97,7 @@ public class RoutesConfigurer {
                 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(), true);
                     }
                 }


[camel] 06/09: CAMEL-14050: Polish Superivisiting route controller a bit, and fixed a test that was unpredicable.

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

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

commit b14e58a36a793a18dbe0ee46a6079cd9e6791d3e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 20:26:42 2019 +0200

    CAMEL-14050: Polish Superivisiting route controller a bit, and fixed a test that was unpredicable.
---
 .../boot/CamelSpringBootApplicationListener.java   |  7 +--
 .../spring/boot/SpringBootRoutesCollector.java     | 70 ++++++++++++++++++++++
 .../boot/SupervisingRouteControllerTest.java       | 20 +++++--
 .../java/org/apache/camel/spi/RouteContext.java    | 10 +---
 .../apache/camel/main/DefaultRoutesCollector.java  | 18 ------
 .../org/apache/camel/main/RoutesCollector.java     |  2 +-
 6 files changed, 90 insertions(+), 37 deletions(-)

diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
index ed0eca1..107d749 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
@@ -85,11 +85,8 @@ public class CamelSpringBootApplicationListener implements ApplicationListener<C
                 && camelContext.getStatus().isStopped()) {
             LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName());
 
-            if (configurationProperties.isRoutesCollectorEnabled()) {
-                LOG.debug("RoutesCollectorEnabled: {}", springBootRoutesCollector);
-                RoutesConfigurer configurer = new RoutesConfigurer(springBootRoutesCollector);
-                configurer.configureRoutes(camelContext, configurationProperties);
-            }
+            RoutesConfigurer configurer = new RoutesConfigurer(springBootRoutesCollector);
+            configurer.configureRoutes(camelContext, configurationProperties);
 
             for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
                 LOG.debug("CamelContextConfiguration found. Invoking beforeApplicationStart: {}", camelContextConfiguration);
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
index d6b446f..335a46c 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
@@ -17,15 +17,19 @@
 package org.apache.camel.spring.boot;
 
 import java.io.FileNotFoundException;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.main.DefaultRoutesCollector;
 import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.util.AntPathMatcher;
+import org.apache.camel.util.ObjectHelper;
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.io.Resource;
 
@@ -41,6 +45,72 @@ public class SpringBootRoutesCollector extends DefaultRoutesCollector {
     }
 
     @Override
+    public List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, String excludePattern, String includePattern) {
+        final List<RoutesBuilder> routes = new ArrayList<>();
+
+        final AntPathMatcher matcher = new AntPathMatcher();
+        for (RoutesBuilder routesBuilder : applicationContext.getBeansOfType(RoutesBuilder.class, true, true).values()) {
+            // filter out abstract classes
+            boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers());
+            if (!abs) {
+                String name = routesBuilder.getClass().getName();
+                // make name as path so we can use ant path matcher
+                name = name.replace('.', '/');
+
+                boolean match = !"false".equals(includePattern);
+                // exclude take precedence over include
+                if (match && ObjectHelper.isNotEmpty(excludePattern)) {
+                    // there may be multiple separated by comma
+                    String[] parts = excludePattern.split(",");
+                    for (String part : parts) {
+                        // must negate when excluding, and hence !
+                        match = !matcher.match(part, name);
+                        log.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        if (!match) {
+                            break;
+                        }
+                    }
+                }
+                // special support for testing with @ExcludeRoutes annotation with camel-test-spring
+                excludePattern = System.getProperty("CamelTestSpringExcludeRoutes");
+                // exclude take precedence over include
+                if (match && ObjectHelper.isNotEmpty(excludePattern)) {
+                    // this property is a comma separated list of FQN class names, so we need to make
+                    // name as path so we can use ant patch matcher
+                    excludePattern = excludePattern.replace('.', '/');
+                    // there may be multiple separated by comma
+                    String[] parts = excludePattern.split(",");
+                    for (String part : parts) {
+                        // must negate when excluding, and hence !
+                        match = !matcher.match(part, name);
+                        log.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
+                        if (!match) {
+                            break;
+                        }
+                    }
+                }
+                if (match && ObjectHelper.isNotEmpty(includePattern)) {
+                    // there may be multiple separated by comma
+                    String[] parts = includePattern.split(",");
+                    for (String part : parts) {
+                        match = matcher.match(part, name);
+                        log.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
+                        if (match) {
+                            break;
+                        }
+                    }
+                }
+                log.debug("Java RoutesBuilder: {} accepted by include/exclude filter: {}", name, match);
+                if (match) {
+                    routes.add(routesBuilder);
+                }
+            }
+        }
+
+        return routes;
+    }
+
+    @Override
     public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) {
         List<RoutesDefinition> answer = new ArrayList<>();
 
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SupervisingRouteControllerTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SupervisingRouteControllerTest.java
index 3b2b640..7d9c495 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SupervisingRouteControllerTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SupervisingRouteControllerTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.spring.boot;
 
+import java.util.concurrent.TimeUnit;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.ServiceStatus;
 import org.apache.camel.builder.RouteBuilder;
@@ -32,6 +34,8 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit4.SpringRunner;
 
+import static org.awaitility.Awaitility.await;
+
 @DirtiesContext
 @RunWith(SpringRunner.class)
 @SpringBootTest(
@@ -42,6 +46,7 @@ import org.springframework.test.context.junit4.SpringRunner;
     },
     properties = {
         "camel.springboot.xml-routes = false",
+        "camel.springboot.xml-rests = false",
         "camel.springboot.main-run-controller = true",
         "camel.supervising.controller.enabled = true",
         "camel.supervising.controller.initial-delay = 2s",
@@ -78,13 +83,18 @@ public class SupervisingRouteControllerTest {
         Assert.assertEquals(Long.MAX_VALUE, bar.getMaxDelay().toMillis());
         Assert.assertEquals(3L, bar.getMaxAttempts().longValue());
 
-        Assert.assertEquals(controller, context.getRoute("foo").getRouteContext().getRouteController());
-        Assert.assertEquals(controller, context.getRoute("bar").getRouteContext().getRouteController());
-        Assert.assertNull(context.getRoute("timer-unmanaged").getRouteContext().getRouteController());
-        Assert.assertNull(context.getRoute("timer-no-autostartup").getRouteContext().getRouteController());
-
         Assert.assertEquals(ServiceStatus.Stopped, context.getRouteController().getRouteStatus("foo"));
         Assert.assertEquals(ServiceStatus.Stopped, context.getRouteController().getRouteStatus("bar"));
+        Assert.assertEquals(ServiceStatus.Stopped, context.getRouteController().getRouteStatus("timer-no-autostartup"));
+        Assert.assertEquals(ServiceStatus.Stopped, context.getRouteController().getRouteStatus("jetty"));
+
+        // Wait for the controller to start the routes also unmanaged
+        await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+            Assert.assertEquals(ServiceStatus.Started, context.getRouteController().getRouteStatus("jetty"));
+            Assert.assertEquals(ServiceStatus.Started, context.getRouteController().getRouteStatus("timer-unmanaged"));
+        });
+        Assert.assertEquals(ServiceStatus.Started, context.getRouteController().getRouteStatus("jetty"));
+        Assert.assertEquals(ServiceStatus.Started, context.getRouteController().getRouteStatus("timer-unmanaged"));
     }
 
     // *************************************
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
index feb117f..7c5b337 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
@@ -28,7 +28,6 @@ import org.apache.camel.NamedNode;
 import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.RuntimeConfiguration;
-import org.apache.camel.meta.Experimental;
 
 /**
  * The context used to activate new routing rules
@@ -234,19 +233,14 @@ public interface RouteContext extends RuntimeConfiguration, EndpointAware {
      *
      * @return the route controller,
      */
-    @Experimental
-    default RouteController getRouteController() {
-        return null;
-    }
+    RouteController getRouteController();
 
     /**
      * Sets the {@link RouteController} for this route.
      *
      * @param controller the RouteController
      */
-    @Experimental
-    default void setRouteController(RouteController controller) {
-    }
+    void setRouteController(RouteController controller);
 
     Processor getOnCompletion(String onCompletionId);
 
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 2b64ff9..3bd10a3 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
@@ -71,24 +71,6 @@ public class DefaultRoutesCollector implements RoutesCollector {
                         }
                     }
                 }
-                // special support for testing with @ExcludeRoutes annotation with camel-test-spring
-                excludePattern = System.getProperty("CamelTestSpringExcludeRoutes");
-                // exclude take precedence over include
-                if (match && ObjectHelper.isNotEmpty(excludePattern)) {
-                    // this property is a comma separated list of FQN class names, so we need to make
-                    // name as path so we can use ant patch matcher
-                    excludePattern = excludePattern.replace('.', '/');
-                    // there may be multiple separated by comma
-                    String[] parts = excludePattern.split(",");
-                    for (String part : parts) {
-                        // must negate when excluding, and hence !
-                        match = !matcher.match(part, name);
-                        log.trace("Java RoutesBuilder: {} exclude filter: {} -> {}", name, part, match);
-                        if (!match) {
-                            break;
-                        }
-                    }
-                }
                 if (match && ObjectHelper.isNotEmpty(includePattern)) {
                     // there may be multiple separated by comma
                     String[] parts = includePattern.split(",");
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 b8e9648..8d8b2fc 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
@@ -25,7 +25,7 @@ import org.apache.camel.model.rest.RestsDefinition;
 
 /**
  * Collects routes and rests from the various sources (like registry or opinionated
- * classpath locations) and injects these into the Camel context.
+ * classpath locations) and adds these into the Camel context.
  */
 public interface RoutesCollector {
 


[camel] 09/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit 12b90dca63edf48de9f7a94569b889eb814e5ee5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 21:08:49 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../org/apache/camel/main/BaseMainSupport.java     | 14 +++++++++++++
 .../camel/main/MainConfigurationProperties.java    | 24 ++++++++++++++++++++++
 .../camel-main-configuration-metadata.json         |  6 ++++++
 .../main/MainRoutesCollectorPackageScanTest.java   | 10 +--------
 4 files changed, 45 insertions(+), 9 deletions(-)

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 c3816a5..ee06fdd 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
@@ -28,6 +28,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -423,6 +424,19 @@ public abstract class BaseMainSupport extends ServiceSupport {
                 }
             }
         }
+
+        if (mainConfigurationProperties.getPackageScanRouteBuilders() != null) {
+            String[] pkgs = mainConfigurationProperties.getPackageScanRouteBuilders().split(",");
+            Set<Class<?>> set = camelContext.getExtension(ExtendedCamelContext.class).getPackageScanClassResolver().findImplementations(RoutesBuilder.class, pkgs);
+            for (Class<?> routeClazz : set) {
+                Object builder = camelContext.getInjector().newInstance(routeClazz);
+                if (builder instanceof RouteBuilder) {
+                    getRoutesBuilders().add((RouteBuilder) builder);
+                } else {
+                    LOG.warn("Class {} is not a RouteBuilder class", routeClazz);
+                }
+            }
+        }
     }
 
     protected void loadConfigurations(CamelContext camelContext) throws Exception {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index ffdca5d..28ab76d 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -30,6 +30,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
     private boolean autowireComponentPropertiesAllowPrivateSetter = true;
     private int durationHitExitCode;
     private boolean hangupInterceptorEnabled = true;
+    private String packageScanRouteBuilders;
 
     // extended configuration
     private final HystrixConfigurationProperties hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
@@ -178,6 +179,19 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
         this.hangupInterceptorEnabled = hangupInterceptorEnabled;
     }
 
+    public String getPackageScanRouteBuilders() {
+        return packageScanRouteBuilders;
+    }
+
+    /**
+     * Sets package names for scanning for {@link org.apache.camel.builder.RouteBuilder} classes as candidates to be included.
+     * If you are using Spring Boot then its instead recommended to use Spring Boots component scanning and annotate your route builder
+     * classes with `@Component`. In other words only use this for Camel Main in standalone mode.
+     */
+    public void setPackageScanRouteBuilders(String packageScanRouteBuilders) {
+        this.packageScanRouteBuilders = packageScanRouteBuilders;
+    }
+
     public int getDurationHitExitCode() {
         return durationHitExitCode;
     }
@@ -301,4 +315,14 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
         return this;
     }
 
+    /**
+     * Sets package names for scanning for {@link org.apache.camel.builder.RouteBuilder} classes as candidates to be included.
+     * If you are using Spring Boot then its instead recommended to use Spring Boots component scanning and annotate your route builder
+     * classes with `@Component`. In other words only use this for Camel Main in standalone mode.
+     */
+    public MainConfigurationProperties withPackageScanRouteBuilders(String packageScanRouteBuilders) {
+        this.packageScanRouteBuilders = packageScanRouteBuilders;
+        return this;
+    }
+
 }
diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
index 67616b3..bd3d045 100644
--- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
@@ -230,6 +230,12 @@
 			"description":"Sets the name of the CamelContext."
 		},
 		{
+			"name":"camel.main.package-scan-route-builders",
+			"type":"java.lang.String",
+			"sourceType":"org.apache.camel.main.MainConfigurationProperties",
+			"description":"Sets package names for scanning for org.apache.camel.builder.RouteBuilder classes as candidates to be included. If you are using Spring Boot then its instead recommended to use Spring Boots component scanning and annotate your route builder classes with Component. In other words only use this for Camel Main in standalone mode."
+		},
+		{
 			"name":"camel.main.producer-template-cache-size",
 			"type":"int",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
index 208a5e5..06a4b1d 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
@@ -16,13 +16,8 @@
  */
 package org.apache.camel.main;
 
-import java.util.Set;
-
 import org.apache.camel.CamelContext;
-import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
-import org.apache.camel.spi.PackageScanClassResolver;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -31,10 +26,7 @@ public class MainRoutesCollectorPackageScanTest extends Assert {
     @Test
     public void testMainRoutesCollector() throws Exception {
         Main main = new Main();
-
-        PackageScanClassResolver resolver = new DefaultPackageScanClassResolver();
-        Set<Class<?>> set = resolver.findImplementations(RouteBuilder.class, "org.apache.camel.main.scan");
-        set.forEach(main::addRouteBuilder);
+        main.configure().withPackageScanRouteBuilders("org.apache.camel.main.scan");
         main.start();
 
         CamelContext camelContext = main.getCamelContext();


[camel] 04/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit 5b1147bd47c18a7b57984788b36658db90a301d8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 17:20:49 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../src/main/docs/spring-boot.adoc                 |  3 +-
 .../camel/spring/boot/CamelAutoConfiguration.java  |  8 +-
 .../spring/boot/CamelConfigurationProperties.java  | 10 +++
 ...ava => CamelSpringBootApplicationListener.java} | 75 ++++++-------------
 .../spring/boot/SpringBootRoutesCollector.java     | 11 ++-
 .../boot/parent/SpringBootRefreshContextTest.java  |  4 +-
 .../org/apache/camel/main/BaseRoutesCollector.java | 45 +++++------
 .../camel/main/DefaultConfigurationProperties.java | 30 ++++++++
 .../org/apache/camel/main/RoutesCollector.java     | 37 +++++++--
 .../org/apache/camel/main/RoutesConfigurer.java    | 87 ++++++++++++++++++++++
 .../camel-main-configuration-metadata.json         |  7 ++
 11 files changed, 224 insertions(+), 93 deletions(-)

diff --git a/components/camel-spring-boot/src/main/docs/spring-boot.adoc b/components/camel-spring-boot/src/main/docs/spring-boot.adoc
index 73a8678..89a5c30 100644
--- a/components/camel-spring-boot/src/main/docs/spring-boot.adoc
+++ b/components/camel-spring-boot/src/main/docs/spring-boot.adoc
@@ -89,7 +89,7 @@ When using Spring Boot make sure to use the following Maven dependency to have s
 ----
 
 
-The component supports 139 options, which are listed below.
+The component supports 140 options, which are listed below.
 
 
 
@@ -182,6 +182,7 @@ The component supports 139 options, which are listed below.
 | *camel.springboot.producer-template-cache-size* | Producer template endpoints cache size. | 1000 | Integer
 | *camel.springboot.route-filter-exclude-pattern* | Used for filtering routes routes matching the given pattern, which follows the following rules: - Match by route id - Match by route input endpoint uri The matching is using exact match, by wildcard and regular expression. For example to only include routes which starts with foo in their route id's, use: include=foo&#42; And to exclude routes which starts from JMS endpoints, use: exclude=jms:&#42; Multiple patterns can be separated by c [...]
 | *camel.springboot.route-filter-include-pattern* | Used for filtering routes routes matching the given pattern, which follows the following rules: - Match by route id - Match by route input endpoint uri The matching is using exact match, by wildcard and regular expression. For example to only include routes which starts with foo in their route id's, use: include=foo&#42; And to exclude routes which starts from JMS endpoints, use: exclude=jms:&#42; Multiple patterns can be separated by c [...]
+| *camel.springboot.routes-collector-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.springboot.shutdown-log-inflight-exchanges-on-timeout* | Sets whether to log information about the inflight Exchanges which are still running during a shutdown which didn't complete without the given timeout. | true | Boolean
 | *camel.springboot.shutdown-now-on-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.springboot.shutdown-routes-in-reverse-order* | Sets whether routes should be shutdown in reverse or the same order as they where started. | true | Boolean
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
index c155230..b1c73ea 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
@@ -149,11 +149,11 @@ public class CamelAutoConfiguration {
     }
 
     @Bean
-    @ConditionalOnMissingBean(RoutesCollectorListener.class)
-    RoutesCollectorListener routesCollectorListener(ApplicationContext applicationContext, CamelConfigurationProperties config,
-                                                    RoutesCollector routesCollector) {
+    @ConditionalOnMissingBean(CamelSpringBootApplicationListener.class)
+    CamelSpringBootApplicationListener routesCollectorListener(ApplicationContext applicationContext, CamelConfigurationProperties config,
+                                                               RoutesCollector routesCollector) {
         Collection<CamelContextConfiguration> configurations = applicationContext.getBeansOfType(CamelContextConfiguration.class).values();
-        return new RoutesCollectorListener(applicationContext, new ArrayList(configurations), config, routesCollector);
+        return new CamelSpringBootApplicationListener(applicationContext, new ArrayList(configurations), config, routesCollector);
     }
 
     /**
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
index 8e06364..f1c36fa 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
@@ -408,6 +408,16 @@ public class CamelConfigurationProperties extends DefaultConfigurationProperties
     private LoggingLevel beanIntrospectionLoggingLevel;
 
     /**
+     * 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.
+     */
+    private boolean routesCollectorEnabled = true;
+
+    /**
      * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
      * The exclusive filtering takes precedence over inclusive filtering.
      * The pattern is using Ant-path style pattern.
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
similarity index 80%
rename from components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java
rename to components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
index 0c7c4fc..ed0eca1 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollectorListener.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationListener.java
@@ -25,18 +25,14 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.RoutesBuilder;
 import org.apache.camel.StartupListener;
 import org.apache.camel.main.MainDurationEventNotifier;
 import org.apache.camel.main.RoutesCollector;
-import org.apache.camel.model.Model;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.main.RoutesConfigurer;
 import org.apache.camel.spi.CamelEvent;
 import org.apache.camel.spi.CamelEvent.Type;
 import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.support.EventNotifierSupport;
-import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.service.ServiceHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,30 +43,31 @@ import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.Ordered;
 
 /**
- * Collects routes and rests from the various sources (like Spring application context beans registry or opinionated
+ * A spring application listener that when spring boot is starting (refresh event) will setup Camel by:
+ * <p>
+ * 1. collecting routes and rests from the various sources (like Spring application context beans registry or opinionated
  * classpath locations) and injects these into the Camel context.
+ * 2. setting up Camel main controller if enabled.
+ * 3. setting up run duration if in use.
  */
-public class RoutesCollectorListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {
+public class CamelSpringBootApplicationListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {
 
     // Static collaborators
 
-    private static final Logger LOG = LoggerFactory.getLogger(RoutesCollectorListener.class);
+    private static final Logger LOG = LoggerFactory.getLogger(CamelSpringBootApplicationListener.class);
 
     // Collaborators
 
     private final ApplicationContext applicationContext;
-
     private final List<CamelContextConfiguration> camelContextConfigurations;
-
     private final CamelConfigurationProperties configurationProperties;
-
     private final RoutesCollector springBootRoutesCollector;
 
     // Constructors
 
-    public RoutesCollectorListener(ApplicationContext applicationContext, List<CamelContextConfiguration> camelContextConfigurations,
-                                   CamelConfigurationProperties configurationProperties,
-                                   RoutesCollector springBootRoutesCollector) {
+    public CamelSpringBootApplicationListener(ApplicationContext applicationContext, List<CamelContextConfiguration> camelContextConfigurations,
+                                              CamelConfigurationProperties configurationProperties,
+                                              RoutesCollector springBootRoutesCollector) {
         this.applicationContext = applicationContext;
         this.camelContextConfigurations = new ArrayList<>(camelContextConfigurations);
         this.configurationProperties = configurationProperties;
@@ -88,42 +85,18 @@ public class RoutesCollectorListener implements ApplicationListener<ContextRefre
                 && camelContext.getStatus().isStopped()) {
             LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName());
 
-            final List<RoutesBuilder> routes = springBootRoutesCollector.collectRoutesFromRegistry(camelContext, configurationProperties);
+            if (configurationProperties.isRoutesCollectorEnabled()) {
+                LOG.debug("RoutesCollectorEnabled: {}", springBootRoutesCollector);
+                RoutesConfigurer configurer = new RoutesConfigurer(springBootRoutesCollector);
+                configurer.configureRoutes(camelContext, configurationProperties);
+            }
 
-            // sort routes according to ordered
-            routes.sort(OrderedComparator.get());
-            // then add the routes
-            for (RoutesBuilder routesBuilder : routes) {
-                try {
-                    LOG.debug("Injecting following route into the CamelContext: {}", routesBuilder);
-                    camelContext.addRoutes(routesBuilder);
-                } catch (Exception e) {
-                    throw new CamelSpringBootInitializationException(e);
-                }
+            for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
+                LOG.debug("CamelContextConfiguration found. Invoking beforeApplicationStart: {}", camelContextConfiguration);
+                camelContextConfiguration.beforeApplicationStart(camelContext);
             }
 
             try {
-                boolean scan = !configurationProperties.getXmlRoutes().equals("false");
-                if (scan) {
-                    List<RoutesDefinition> defs = springBootRoutesCollector.collectXmlRoutesFromDirectory(camelContext, configurationProperties.getXmlRoutes());
-                    for (RoutesDefinition def : defs) {
-                        camelContext.getExtension(Model.class).addRouteDefinitions(def.getRoutes());
-                    }
-                }
-
-                boolean scanRests = !configurationProperties.getXmlRests().equals("false");
-                if (scanRests) {
-                    List<RestsDefinition> defs = springBootRoutesCollector.collectXmlRestsFromDirectory(camelContext, configurationProperties.getXmlRests());
-                    for (RestsDefinition def : defs) {
-                        camelContext.getExtension(Model.class).addRestDefinitions(def.getRests(), true);
-                    }
-                }
-
-                for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
-                    LOG.debug("CamelContextConfiguration found. Invoking beforeApplicationStart: {}", camelContextConfiguration);
-                    camelContextConfiguration.beforeApplicationStart(camelContext);
-                }
-
                 if (configurationProperties.isMainRunController()) {
                     CamelMainRunController controller = new CamelMainRunController(applicationContext, camelContext);
 
@@ -136,8 +109,8 @@ public class RoutesCollectorListener implements ApplicationListener<ContextRefre
                         }
                         // register lifecycle so we can trigger to shutdown the JVM when maximum number of messages has been processed
                         EventNotifier notifier = new MainDurationEventNotifier(camelContext,
-                            configurationProperties.getDurationMaxMessages(), configurationProperties.getDurationMaxIdleSeconds(),
-                            controller.getCompleted(), controller.getLatch(), true);
+                                configurationProperties.getDurationMaxMessages(), configurationProperties.getDurationMaxIdleSeconds(),
+                                controller.getCompleted(), controller.getLatch(), true);
                         // register our event notifier
                         ServiceHelper.startService(notifier);
                         camelContext.getManagementStrategy().addEventNotifier(notifier);
@@ -146,7 +119,7 @@ public class RoutesCollectorListener implements ApplicationListener<ContextRefre
                     if (configurationProperties.getDurationMaxSeconds() > 0) {
                         LOG.info("CamelSpringBoot will terminate after {} seconds", configurationProperties.getDurationMaxSeconds());
                         terminateMainControllerAfter(camelContext, configurationProperties.getDurationMaxSeconds(),
-                            controller.getCompleted(), controller.getLatch());
+                                controller.getCompleted(), controller.getLatch());
                     }
 
                     camelContext.addStartupListener(new StartupListener() {
@@ -185,8 +158,8 @@ public class RoutesCollectorListener implements ApplicationListener<ContextRefre
 
                             // register lifecycle so we can trigger to shutdown the JVM when maximum number of messages has been processed
                             EventNotifier notifier = new MainDurationEventNotifier(camelContext,
-                                configurationProperties.getDurationMaxMessages(), configurationProperties.getDurationMaxIdleSeconds(),
-                                completed, latch, false);
+                                    configurationProperties.getDurationMaxMessages(), configurationProperties.getDurationMaxIdleSeconds(),
+                                    completed, latch, false);
                             // register our event notifier
                             ServiceHelper.startService(notifier);
                             camelContext.getManagementStrategy().addEventNotifier(notifier);
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
index 3f5d7d3..e2a30a1 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootRoutesCollector.java
@@ -21,7 +21,10 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.main.BaseRoutesCollector;
+import org.apache.camel.main.DefaultConfigurationProperties;
 import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.rest.RestsDefinition;
@@ -40,7 +43,7 @@ public class SpringBootRoutesCollector extends BaseRoutesCollector {
     }
 
     @Override
-    public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception {
+    public List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) {
         List<RoutesDefinition> answer = new ArrayList<>();
 
         String[] parts = directory.split(",");
@@ -55,6 +58,8 @@ public class SpringBootRoutesCollector extends BaseRoutesCollector {
                 }
             } catch (FileNotFoundException e) {
                 log.debug("No XML routes found in {}. Skipping XML routes detection.", part);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
             }
         }
 
@@ -62,7 +67,7 @@ public class SpringBootRoutesCollector extends BaseRoutesCollector {
     }
 
     @Override
-    public List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception {
+    public List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) {
         List<RestsDefinition> answer = new ArrayList<>();
 
         String[] parts = directory.split(",");
@@ -76,6 +81,8 @@ public class SpringBootRoutesCollector extends BaseRoutesCollector {
                 }
             } catch (FileNotFoundException e) {
                 log.debug("No XML rests found in {}. Skipping XML rests detection.", part);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
             }
         }
 
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
index 29d81a0..e8ed75d 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/parent/SpringBootRefreshContextTest.java
@@ -18,7 +18,7 @@ package org.apache.camel.spring.boot.parent;
 
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spring.boot.RoutesCollectorListener;
+import org.apache.camel.spring.boot.CamelSpringBootApplicationListener;
 import org.junit.Test;
 import org.springframework.boot.WebApplicationType;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -36,7 +36,7 @@ public class SpringBootRefreshContextTest {
         parent.refresh();
         ConfigurableApplicationContext context = new SpringApplicationBuilder(Configuration.class).web(WebApplicationType.NONE).parent(parent).run();
         ContextRefreshedEvent refreshEvent = new ContextRefreshedEvent(context);
-        RoutesCollectorListener collector = context.getBean(RoutesCollectorListener.class);
+        CamelSpringBootApplicationListener collector = context.getBean(CamelSpringBootApplicationListener.class);
         collector.onApplicationEvent(refreshEvent); //no changes should happen here
     }
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
index 38cbfb9..17fe2a3 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseRoutesCollector.java
@@ -1,13 +1,13 @@
-/**
+/*
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *      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.
@@ -23,26 +23,23 @@ import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.RoutesBuilder;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Collects routes and rests from the various sources (like registry or opinionated
- * classpath locations) and injects these into the Camel context.
+ * Base {@link RoutesCollector}.
  */
 public abstract class BaseRoutesCollector implements RoutesCollector {
 
-    // TODO: Add load routes from xml and rest
-    // TODO: Base class and extended for spring-boot etc
     // TODO: Add to camel main that it uses route collector
 
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
-    public List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, DefaultConfigurationProperties configurationProperties) {
+    @Override
+    public List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext,
+                                                         String excludePattern, String includePattern) {
         final List<RoutesBuilder> routes = new ArrayList<>();
 
         final AntPathMatcher matcher = new AntPathMatcher();
@@ -55,14 +52,11 @@ public abstract class BaseRoutesCollector implements RoutesCollector {
                 // make name as path so we can use ant path matcher
                 name = name.replace('.', '/');
 
-                String exclude = configurationProperties.getJavaRoutesExcludePattern();
-                String include = configurationProperties.getJavaRoutesIncludePattern();
-
-                boolean match = !"false".equals(include);
+                boolean match = !"false".equals(includePattern);
                 // exclude take precedence over include
-                if (match && ObjectHelper.isNotEmpty(exclude)) {
+                if (match && ObjectHelper.isNotEmpty(excludePattern)) {
                     // there may be multiple separated by comma
-                    String[] parts = exclude.split(",");
+                    String[] parts = excludePattern.split(",");
                     for (String part : parts) {
                         // must negate when excluding, and hence !
                         match = !matcher.match(part, name);
@@ -73,14 +67,14 @@ public abstract class BaseRoutesCollector implements RoutesCollector {
                     }
                 }
                 // special support for testing with @ExcludeRoutes annotation with camel-test-spring
-                exclude = System.getProperty("CamelTestSpringExcludeRoutes");
+                excludePattern = System.getProperty("CamelTestSpringExcludeRoutes");
                 // exclude take precedence over include
-                if (match && ObjectHelper.isNotEmpty(exclude)) {
+                if (match && ObjectHelper.isNotEmpty(excludePattern)) {
                     // this property is a comma separated list of FQN class names, so we need to make
                     // name as path so we can use ant patch matcher
-                    exclude = exclude.replace('.', '/');
+                    excludePattern = excludePattern.replace('.', '/');
                     // there may be multiple separated by comma
-                    String[] parts = exclude.split(",");
+                    String[] parts = excludePattern.split(",");
                     for (String part : parts) {
                         // must negate when excluding, and hence !
                         match = !matcher.match(part, name);
@@ -90,9 +84,9 @@ public abstract class BaseRoutesCollector implements RoutesCollector {
                         }
                     }
                 }
-                if (match && ObjectHelper.isNotEmpty(include)) {
+                if (match && ObjectHelper.isNotEmpty(includePattern)) {
                     // there may be multiple separated by comma
-                    String[] parts = include.split(",");
+                    String[] parts = includePattern.split(",");
                     for (String part : parts) {
                         match = matcher.match(part, name);
                         log.trace("Java RoutesBuilder: {} include filter: {} -> {}", name, part, match);
@@ -106,14 +100,9 @@ public abstract class BaseRoutesCollector implements RoutesCollector {
                     routes.add(routesBuilder);
                 }
             }
-
         }
 
         return routes;
     }
 
-    public abstract List<RoutesDefinition> collectXmlRoutesFromDirectory(CamelContext camelContext, String directory) throws Exception;
-
-    public abstract List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception;
-
 }
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 e8794c5..b0c0271 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
@@ -71,6 +71,7 @@ public abstract class DefaultConfigurationProperties<T> {
     private String routeFilterExcludePattern;
     private boolean beanIntrospectionExtendedStatistics;
     private LoggingLevel beanIntrospectionLoggingLevel;
+    private boolean routesCollectorEnabled = true;
     private String javaRoutesIncludePattern;
     private String javaRoutesExcludePattern;
     private String xmlRoutes = "classpath:camel/*.xml";
@@ -708,6 +709,22 @@ public abstract class DefaultConfigurationProperties<T> {
         this.beanIntrospectionLoggingLevel = beanIntrospectionLoggingLevel;
     }
 
+    public boolean isRoutesCollectorEnabled() {
+        return routesCollectorEnabled;
+    }
+
+    /**
+     * 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.
+     */
+    public void setRoutesCollectorEnabled(boolean routesCollectorEnabled) {
+        this.routesCollectorEnabled = routesCollectorEnabled;
+    }
+
     public String getJavaRoutesIncludePattern() {
         return javaRoutesIncludePattern;
     }
@@ -1277,6 +1294,19 @@ 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.
+     *
+     * The routes collector is default enabled.
+     */
+    public T withRoutesCollectorEnabled(boolean routesCollectorEnabled) {
+        this.routesCollectorEnabled = routesCollectorEnabled;
+        return (T) this;
+    }
+
+    /**
      * Used for inclusive filtering component scanning of RouteBuilder classes with @Component annotation.
      * The exclusive filtering takes precedence over inclusive filtering.
      * The pattern is using Ant-path style pattern.
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 33fabb1..b8e9648 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
@@ -1,13 +1,13 @@
-/**
+/*
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *      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.
@@ -23,12 +23,39 @@ import org.apache.camel.RoutesBuilder;
 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 injects these into the Camel context.
+ */
 public interface RoutesCollector {
 
-    List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, DefaultConfigurationProperties configurationProperties);
+    /**
+     * Collects the {@link RoutesBuilder} instances which was discovered from the {@link org.apache.camel.spi.Registry} such as
+     * Spring or CDI bean containers.
+     *
+     * @param camelContext        the Camel Context
+     * @param excludePattern      exclude pattern (see javaRoutesExcludePattern option)
+     * @param includePattern      include pattern  (see javaRoutesIncludePattern option)
+     * @return the discovered routes or an empty list
+     */
+    List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, String excludePattern, String includePattern);
 
+    /**
+     * Collects all XML routes 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 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
+     */
     List<RestsDefinition> collectXmlRestsFromDirectory(CamelContext camelContext, String directory) throws Exception;
 
 }
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
new file mode 100644
index 0000000..fd18ad4
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
@@ -0,0 +1,87 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.main;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.support.OrderedComparator;
+import org.slf4j.Logger;
+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;
+
+    public RoutesConfigurer(RoutesCollector routesCollector) {
+        this.routesCollector = routesCollector;
+    }
+
+    /**
+     * Collects routes and rests from the various sources (like registry or opinionated
+     * classpath locations) and injects these into the Camel context.
+     *
+     * @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());
+
+                // sort routes according to ordered
+                routes.sort(OrderedComparator.get());
+                // then add the routes
+                for (RoutesBuilder routesBuilder : routes) {
+                    LOG.debug("Injecting following route into the CamelContext: {}", routesBuilder);
+                    camelContext.addRoutes(routesBuilder);
+                }
+
+                boolean scan = !config.getXmlRoutes().equals("false");
+                if (scan) {
+                    List<RoutesDefinition> defs = routesCollector.collectXmlRoutesFromDirectory(camelContext, config.getXmlRoutes());
+                    for (RoutesDefinition def : defs) {
+                        camelContext.getExtension(Model.class).addRouteDefinitions(def.getRoutes());
+                    }
+                }
+
+                boolean scanRests = !config.getXmlRests().equals("false");
+                if (scanRests) {
+                    List<RestsDefinition> defs = routesCollector.collectXmlRestsFromDirectory(camelContext, config.getXmlRests());
+                    for (RestsDefinition def : defs) {
+                        camelContext.getExtension(Model.class).addRestDefinitions(def.getRests(), true);
+                    }
+                }
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
index e0c3bfe..67616b3 100644
--- a/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/main/resources/META-INF/camel-main-configuration-metadata.json
@@ -249,6 +249,13 @@
 			"description":"Used for filtering routes routes matching the given pattern, which follows the following rules: - Match by route id - Match by route input endpoint uri The matching is using exact match, by wildcard and regular expression as documented by PatternHelper#matchPattern(String,String) . For example to only include routes which starts with foo in their route id's, use: include=foo&#42; And to exclude routes which starts from JMS endpoints, use: exclude=jms:&#42; Multiple patt [...]
 		},
 		{
+			"name":"camel.main.routes-collector-enabled",
+			"type":"boolean",
+			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",
+			"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.",
+			"defaultValue":"true"
+		},
+		{
 			"name":"camel.main.shutdown-log-inflight-exchanges-on-timeout",
 			"type":"boolean",
 			"sourceType":"org.apache.camel.main.DefaultConfigurationProperties",


[camel] 07/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit 19db834f84fe901e2f60b1be68cb29038b488771
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 20:32:56 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../apache/camel/main/MainRoutesCollectorTest.java | 54 ++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorTest.java
new file mode 100644
index 0000000..56ab2ec
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.main;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MainRoutesCollectorTest extends Assert {
+
+    @Test
+    public void testMainRoutesCollector() throws Exception {
+        Main main = new Main();
+        main.bind("myBarRoute", new MyRouteBuilder());
+        main.start();
+
+        CamelContext camelContext = main.getCamelContext();
+        assertNotNull(camelContext);
+        assertEquals(1, camelContext.getRoutes().size());
+
+        MockEndpoint endpoint = camelContext.getEndpoint("mock:results", MockEndpoint.class);
+        endpoint.expectedBodiesReceived("Hello World");
+
+        main.getCamelTemplate().sendBody("direct:start", "Hello World");
+
+        endpoint.assertIsSatisfied();
+
+        main.stop();
+    }
+
+    public static class MyRouteBuilder extends RouteBuilder {
+
+        @Override
+        public void configure() throws Exception {
+            from("direct:start").to("mock:results");
+        }
+    }
+}


[camel] 08/09: CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has

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

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

commit cbdcf4d9b8b47419782613b0c7e8d1b562dd4659
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 17 20:38:03 2019 +0200

    CAMEL-14050: camel-main - Add logic for automatic RouteBuilder class detection ala camel-spring-boot has
---
 .../main/MainRoutesCollectorPackageScanTest.java   | 58 ++++++++++++++++++++++
 .../camel/main/scan/MyDummyRouteBuilder.java       | 27 ++++++++++
 .../apache/camel/main/scan/MyScanRouteBuilder.java | 27 ++++++++++
 3 files changed, 112 insertions(+)

diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
new file mode 100644
index 0000000..208a5e5
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.main;
+
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.spi.PackageScanClassResolver;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MainRoutesCollectorPackageScanTest extends Assert {
+
+    @Test
+    public void testMainRoutesCollector() throws Exception {
+        Main main = new Main();
+
+        PackageScanClassResolver resolver = new DefaultPackageScanClassResolver();
+        Set<Class<?>> set = resolver.findImplementations(RouteBuilder.class, "org.apache.camel.main.scan");
+        set.forEach(main::addRouteBuilder);
+        main.start();
+
+        CamelContext camelContext = main.getCamelContext();
+        assertNotNull(camelContext);
+        assertEquals(2, camelContext.getRoutes().size());
+
+        MockEndpoint endpoint = camelContext.getEndpoint("mock:scan", MockEndpoint.class);
+        endpoint.expectedBodiesReceived("Hello World");
+        MockEndpoint endpoint2 = camelContext.getEndpoint("mock:dummy", MockEndpoint.class);
+        endpoint2.expectedBodiesReceived("Bye World");
+
+        main.getCamelTemplate().sendBody("direct:scan", "Hello World");
+        main.getCamelTemplate().sendBody("direct:dummy", "Bye World");
+
+        endpoint.assertIsSatisfied();
+        endpoint2.assertIsSatisfied();
+
+        main.stop();
+    }
+
+}
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/scan/MyDummyRouteBuilder.java b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyDummyRouteBuilder.java
new file mode 100644
index 0000000..d2a5d78
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyDummyRouteBuilder.java
@@ -0,0 +1,27 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.main.scan;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyDummyRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("direct:dummy").to("mock:dummy");
+    }
+}
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanRouteBuilder.java b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanRouteBuilder.java
new file mode 100644
index 0000000..ff258c7
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanRouteBuilder.java
@@ -0,0 +1,27 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.main.scan;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyScanRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("direct:scan").to("mock:scan");
+    }
+}