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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3da7391  CAMEL-15036: Make it easier to switch to use supervising 
route controller in XML DSL
3da7391 is described below

commit 3da7391444e79f806e14097c1a134a8460346e0b
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon May 11 14:00:02 2020 +0200

    CAMEL-15036: Make it easier to switch to use supervising route controller 
in XML DSL
---
 .../camel/cdi/xml/CamelContextFactoryBean.java     |  13 ++
 .../org/apache/camel/spring/camelContext.json      |   1 +
 .../camel/spring/CamelContextFactoryBean.java      |  12 ++
 .../spring/handler/CamelNamespaceHandler.java      |   3 +
 .../impl/SpringSupervisingRouteControllerTest.java |  85 ++-------
 .../impl/SpringSupervisingRouteControllerTest.xml  |  50 ++++++
 .../engine/DefaultSupervisingRouteController.java  |  15 +-
 .../resources/org/apache/camel/core/xml/jaxb.index |   1 +
 .../org/apache/camel/core/xml/routeController.json |  26 +++
 .../core/xml/AbstractCamelContextFactoryBean.java  |  70 +++++++-
 .../core/xml/CamelRouteControllerDefinition.java   | 197 +++++++++++++++++++++
 .../DefaultSupervisingRouteControllerTest.java     |   1 -
 12 files changed, 387 insertions(+), 87 deletions(-)

diff --git 
a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
 
b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
index 18d5c88..4827132 100644
--- 
a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
+++ 
b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
@@ -41,6 +41,7 @@ import org.apache.camel.core.xml.AbstractCamelFactoryBean;
 import org.apache.camel.core.xml.CamelJMXAgentDefinition;
 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
 import org.apache.camel.core.xml.CamelProxyFactoryDefinition;
+import org.apache.camel.core.xml.CamelRouteControllerDefinition;
 import org.apache.camel.core.xml.CamelServiceExporterDefinition;
 import org.apache.camel.core.xml.CamelStreamCachingStrategyDefinition;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -177,6 +178,9 @@ public class CamelContextFactoryBean extends 
AbstractCamelContextFactoryBean<Def
     @XmlElement(name = "streamCaching", type = 
CamelStreamCachingStrategyDefinition.class)
     private CamelStreamCachingStrategyDefinition camelStreamCachingStrategy;
 
+    @XmlElement(name = "routeController", type = 
CamelRouteControllerDefinition.class)
+    private CamelRouteControllerDefinition camelRouteController;
+
     @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class)
     private CamelJMXAgentDefinition camelJMXAgent;
 
@@ -603,6 +607,15 @@ public class CamelContextFactoryBean extends 
AbstractCamelContextFactoryBean<Def
     }
 
     @Override
+    public CamelRouteControllerDefinition getCamelRouteController() {
+        return camelRouteController;
+    }
+
+    public void setCamelRouteController(CamelRouteControllerDefinition 
camelRouteController) {
+        this.camelRouteController = camelRouteController;
+    }
+
+    @Override
     public String getTrace() {
         return trace;
     }
diff --git 
a/components/camel-spring/src/generated/resources/org/apache/camel/spring/camelContext.json
 
b/components/camel-spring/src/generated/resources/org/apache/camel/spring/camelContext.json
index 9e5d43c..4a380f7 100644
--- 
a/components/camel-spring/src/generated/resources/org/apache/camel/spring/camelContext.json
+++ 
b/components/camel-spring/src/generated/resources/org/apache/camel/spring/camelContext.json
@@ -47,6 +47,7 @@
     "contextScan": { "kind": "element", "displayName": "Context Scan", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.model.ContextScanDefinition", "deprecated": false, "secret": 
false, "description": "Sets the context scanning (eg Spring's 
ApplicationContext) information. Context scanning allows for the automatic 
discovery of Camel routes runtime for inclusion e.g. 
org.apache.camel.builder.RouteBuilder implementations" },
     "streamCaching": { "kind": "element", "displayName": "Stream Caching", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.core.xml.CamelStreamCachingStrategyDefinition", "deprecated": 
false, "secret": false, "description": "Configuration of stream caching." },
     "jmxAgent": { "kind": "element", "displayName": "JMX Agent", "required": 
false, "type": "object", "javaType": 
"org.apache.camel.core.xml.CamelJMXAgentDefinition", "deprecated": false, 
"secret": false, "description": "Configuration of JMX Agent." },
+    "routeController": { "kind": "element", "displayName": "Route Controller", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.core.xml.CamelRouteControllerDefinition", "deprecated": 
false, "secret": false },
     "beansFactory": { "kind": "element", "displayName": "Beans Factory", 
"required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.core.xml.AbstractCamelFactoryBean<java.lang.Object>>",
 "oneOf": [ "consumerTemplate", "fluentTemplate", "template" ], "deprecated": 
false, "secret": false, "description": "Miscellaneous configurations" },
     "beans": { "kind": "element", "displayName": "Beans", "required": true, 
"type": "array", "javaType": "java.util.List<java.lang.Object>", "oneOf": [ 
"errorHandler", "export", "proxy" ], "deprecated": false, "secret": false, 
"description": "Miscellaneous configurations" },
     "defaultServiceCallConfiguration": { "kind": "element", "displayName": 
"Default Service Call Configuration", "required": false, "type": "object", 
"javaType": "org.apache.camel.model.cloud.ServiceCallConfigurationDefinition", 
"deprecated": false, "secret": false, "description": "ServiceCall EIP default 
configuration" },
diff --git 
a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
 
b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
index 99bdc6e..f556e73 100644
--- 
a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
+++ 
b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
@@ -42,6 +42,7 @@ import org.apache.camel.core.xml.AbstractCamelFactoryBean;
 import org.apache.camel.core.xml.CamelJMXAgentDefinition;
 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
 import org.apache.camel.core.xml.CamelProxyFactoryDefinition;
+import org.apache.camel.core.xml.CamelRouteControllerDefinition;
 import org.apache.camel.core.xml.CamelServiceExporterDefinition;
 import org.apache.camel.core.xml.CamelStreamCachingStrategyDefinition;
 import org.apache.camel.model.ContextScanDefinition;
@@ -173,6 +174,8 @@ public class CamelContextFactoryBean extends 
AbstractCamelContextFactoryBean<Spr
     private CamelStreamCachingStrategyDefinition camelStreamCachingStrategy;
     @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class) 
@Metadata(displayName = "JMX Agent")
     private CamelJMXAgentDefinition camelJMXAgent;
+    @XmlElement(name = "routeController", type = 
CamelRouteControllerDefinition.class)
+    private CamelRouteControllerDefinition camelRouteController;
     @XmlElements({
             @XmlElement(name = "template", type = 
CamelProducerTemplateFactoryBean.class),
             @XmlElement(name = "fluentTemplate", type = 
CamelFluentProducerTemplateFactoryBean.class),
@@ -679,6 +682,15 @@ public class CamelContextFactoryBean extends 
AbstractCamelContextFactoryBean<Spr
         this.camelStreamCachingStrategy = camelStreamCachingStrategy;
     }
 
+    @Override
+    public CamelRouteControllerDefinition getCamelRouteController() {
+        return camelRouteController;
+    }
+
+    public void setCamelRouteController(CamelRouteControllerDefinition 
camelRouteController) {
+        this.camelRouteController = camelRouteController;
+    }
+
     /**
      * Configuration of JMX Agent.
      */
diff --git 
a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
 
b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
index 89fe934..a2e0964 100644
--- 
a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
+++ 
b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
@@ -26,6 +26,7 @@ import javax.xml.bind.Binder;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 
+import org.apache.camel.core.xml.CamelRouteControllerDefinition;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
@@ -149,6 +150,7 @@ public class CamelNamespaceHandler extends 
NamespaceHandlerSupport {
         addBeanDefinitionParser("jmxAgent", CamelJMXAgentDefinition.class, 
false, false);
         addBeanDefinitionParser("streamCaching", 
CamelStreamCachingStrategyDefinition.class, false, false);
         addBeanDefinitionParser("propertyPlaceholder", 
CamelPropertyPlaceholderDefinition.class, false, false);
+        addBeanDefinitionParser("routeController", 
CamelRouteControllerDefinition.class, false, false);
 
         // error handler could be the sub element of camelContext or defined 
outside camelContext
         BeanDefinitionParser errorHandlerParser = new 
ErrorHandlerDefinitionParser();
@@ -378,6 +380,7 @@ public class CamelNamespaceHandler extends 
NamespaceHandlerSupport {
                 builder.addPropertyValue("camelPropertyPlaceholder", 
factoryBean.getCamelPropertyPlaceholder());
                 builder.addPropertyValue("camelJMXAgent", 
factoryBean.getCamelJMXAgent());
                 builder.addPropertyValue("camelStreamCachingStrategy", 
factoryBean.getCamelStreamCachingStrategy());
+                builder.addPropertyValue("camelRouteController", 
factoryBean.getCamelRouteController());
                 builder.addPropertyValue("threadPoolProfiles", 
factoryBean.getThreadPoolProfiles());
                 builder.addPropertyValue("beansFactory", 
factoryBean.getBeansFactory());
                 builder.addPropertyValue("beans", factoryBean.getBeans());
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
 
b/components/camel-spring/src/test/java/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.java
similarity index 57%
copy from 
core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
copy to 
components/camel-spring/src/test/java/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.java
index abb7ece..fd5fa54 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
+++ 
b/components/camel-spring/src/test/java/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.java
@@ -14,44 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.engine;
+package org.apache.camel.spring.impl;
 
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.Consumer;
-import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Processor;
-import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.component.seda.SedaComponent;
 import org.apache.camel.component.seda.SedaConsumer;
 import org.apache.camel.component.seda.SedaEndpoint;
 import org.apache.camel.spi.SupervisingRouteController;
+import org.apache.camel.spring.SpringTestSupport;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.junit.Test;
 
-public class DefaultSupervisingRouteControllerTest extends ContextTestSupport {
+public class SpringSupervisingRouteControllerTest extends SpringTestSupport {
 
     @Override
-    public boolean isUseRouteBuilder() {
-        return false;
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.xml");
     }
 
     @Test
     public void testSupervising() throws Exception {
-        // lets make a simple route
-        context.addRoutes(new MyRoute());
-
-        // configure supervising route controller
-        SupervisingRouteController src = 
context.getRouteController().supervising();
-        src.setBackOffDelay(25);
-        src.setBackOffMaxAttempts(3);
-        src.setInitialDelay(100);
-        src.setThreadPoolSize(2);
-
-        context.start();
-
         MockEndpoint mock = context.getEndpoint("mock:foo", 
MockEndpoint.class);
         mock.expectedMinimumMessageCount(3);
 
@@ -72,6 +61,8 @@ public class DefaultSupervisingRouteControllerTest extends 
ContextTestSupport {
         // cake was not able to start
         assertEquals("Stopped", 
context.getRouteController().getRouteStatus("cake").toString());
 
+        SupervisingRouteController src = 
context.getRouteController().adapt(SupervisingRouteController.class);
+
         Throwable e = src.getRestartException("cake");
         assertNotNull(e);
         assertEquals("Cannot start", e.getMessage());
@@ -81,59 +72,7 @@ public class DefaultSupervisingRouteControllerTest extends 
ContextTestSupport {
         assertEquals("Stopped", 
context.getRouteController().getRouteStatus("bar").toString());
     }
 
-    @Test
-    public void testSupervisingOk() throws Exception {
-        // lets make a simple route
-        context.addRoutes(new MyRoute());
-
-        // configure supervising
-        SupervisingRouteController src = 
context.getRouteController().supervising();
-        src.setBackOffDelay(25);
-        src.setBackOffMaxAttempts(10);
-        src.setInitialDelay(100);
-        src.setThreadPoolSize(2);
-        context.setRouteController(src);
-
-        context.start();
-
-        MockEndpoint mock = context.getEndpoint("mock:foo", 
MockEndpoint.class);
-        mock.expectedMinimumMessageCount(3);
-
-        MockEndpoint mock2 = context.getEndpoint("mock:cheese", 
MockEndpoint.class);
-        mock2.expectedMessageCount(0);
-
-        MockEndpoint mock3 = context.getEndpoint("mock:cake", 
MockEndpoint.class);
-        mock3.expectedMessageCount(0);
-
-        MockEndpoint mock4 = context.getEndpoint("mock:bar", 
MockEndpoint.class);
-        mock4.expectedMessageCount(0);
-
-        MockEndpoint.assertIsSatisfied(5, TimeUnit.SECONDS, mock, mock2, 
mock3, mock4);
-
-        // these should all start
-        assertEquals("Started", 
context.getRouteController().getRouteStatus("foo").toString());
-        assertEquals("Started", 
context.getRouteController().getRouteStatus("cheese").toString());
-        assertEquals("Started", 
context.getRouteController().getRouteStatus("cake").toString());
-        // bar is no auto startup
-        assertEquals("Stopped", 
context.getRouteController().getRouteStatus("bar").toString());
-    }
-
-    private class MyRoute extends RouteBuilder {
-        @Override
-        public void configure() throws Exception {
-            getContext().addComponent("jms", new MyJmsComponent());
-
-            from("timer:foo").to("mock:foo").routeId("foo");
-
-            from("jms:cheese").to("mock:cheese").routeId("cheese");
-
-            from("jms:cake").to("mock:cake").routeId("cake");
-
-            from("seda:bar").routeId("bar").noAutoStartup().to("mock:bar");
-        }
-    }
-
-    private class MyJmsComponent extends SedaComponent {
+    public static class MyJmsComponent extends SedaComponent {
 
         @Override
         protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
@@ -141,7 +80,7 @@ public class DefaultSupervisingRouteControllerTest extends 
ContextTestSupport {
         }
     }
 
-    private class MyJmsEndpoint extends SedaEndpoint {
+    public static  class MyJmsEndpoint extends SedaEndpoint {
 
         private String name;
 
@@ -161,7 +100,7 @@ public class DefaultSupervisingRouteControllerTest extends 
ContextTestSupport {
         }
     }
 
-    private class MyJmsConsumer extends SedaConsumer {
+    public static  class MyJmsConsumer extends SedaConsumer {
 
         private int counter;
 
diff --git 
a/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.xml
 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.xml
new file mode 100644
index 0000000..54a1bda
--- /dev/null
+++ 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/SpringSupervisingRouteControllerTest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <bean id="jms" 
class="org.apache.camel.spring.impl.SpringSupervisingRouteControllerTest.MyJmsComponent"/>
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring";>
+    <routeController id="myController"
+                     supervising="true" initialDelay="100" threadPoolSize="2" 
backOffDelay="25" backOffMaxAttempts="3"/>
+    <route id="foo">
+      <from uri="timer:foo"/>
+      <to uri="mock:foo"/>
+    </route>
+    <route id="cheese">
+      <from uri="jms:cheese"/>
+      <to uri="mock:cheese"/>
+    </route>
+    <route id="cake">
+      <from uri="jms:cake"/>
+      <to uri="mock:cake"/>
+    </route>
+    <route id="bar" autoStartup="false">
+      <from uri="seda:bar"/>
+      <to uri="mock:bar"/>
+    </route>
+  </camelContext>
+
+</beans>
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
index b62219f..8944856 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
@@ -181,16 +181,10 @@ public class DefaultSupervisingRouteController extends 
DefaultRouteController im
 
     @Override
     protected void doInit() throws Exception {
-        this.backOff = new BackOff(
-                Duration.ofMillis(backOffDelay),
-                backOffMaxDelay > 0 ? Duration.ofMillis(backOffMaxDelay) : 
Duration.ofMillis(Long.MAX_VALUE),
-                backOffMaxElapsedTime > 0 ? 
Duration.ofMillis(backOffMaxElapsedTime) : Duration.ofMillis(Long.MAX_VALUE),
-                backOffMaxAttempts > 0 ? backOffMaxAttempts : Long.MAX_VALUE,
-                backOffMultiplier);
         this.listener = new CamelContextStartupListener();
 
-        CamelContext context = getCamelContext();
         // prevent routes from automatic being started by default
+        CamelContext context = getCamelContext();
         context.setAutoStartup(false);
         context.addRoutePolicyFactory(new ManagedRoutePolicyFactory());
         context.addStartupListener(this.listener);
@@ -198,6 +192,13 @@ public class DefaultSupervisingRouteController extends 
DefaultRouteController im
 
     @Override
     protected void doStart() throws Exception {
+        this.backOff = new BackOff(
+                Duration.ofMillis(backOffDelay),
+                backOffMaxDelay > 0 ? Duration.ofMillis(backOffMaxDelay) : 
Duration.ofMillis(Long.MAX_VALUE),
+                backOffMaxElapsedTime > 0 ? 
Duration.ofMillis(backOffMaxElapsedTime) : Duration.ofMillis(Long.MAX_VALUE),
+                backOffMaxAttempts > 0 ? backOffMaxAttempts : Long.MAX_VALUE,
+                backOffMultiplier);
+
         CamelContext context = getCamelContext();
         if (threadPoolSize == 1) {
             executorService = 
context.getExecutorServiceManager().newSingleThreadScheduledExecutor(this, 
"SupervisingRouteController");
diff --git 
a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jaxb.index
 
b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jaxb.index
index d0e2b70..97912b3 100644
--- 
a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jaxb.index
+++ 
b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/jaxb.index
@@ -4,5 +4,6 @@ CamelPropertyPlaceholderDefinition
 CamelPropertyPlaceholderFunctionDefinition
 CamelPropertyPlaceholderLocationDefinition
 CamelProxyFactoryDefinition
+CamelRouteControllerDefinition
 CamelServiceExporterDefinition
 CamelStreamCachingStrategyDefinition
diff --git 
a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/routeController.json
 
b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/routeController.json
new file mode 100644
index 0000000..1d6a9df
--- /dev/null
+++ 
b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/routeController.json
@@ -0,0 +1,26 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "routeController",
+    "title": "Route Controller",
+    "description": "Route controller configuration.",
+    "deprecated": false,
+    "label": "spring,configuration",
+    "javaType": "org.apache.camel.core.xml.CamelRouteControllerDefinition",
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "supervising": { "kind": "attribute", "displayName": "Supervising", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "defaultValue": "false", "description": 
"To enable using supervising route controller which allows Camel to startup and 
then the controller takes care of starting the routes in a safe manner. This 
can be used when you want to startup Camel despite a route may otherwise fail 
fast during startup and cause Camel to [...]
+    "includeRoutes": { "kind": "attribute", "displayName": "Include Routes", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Pattern for filtering 
routes to be included as supervised. The pattern is matching on route id, and 
endpoint uri for the route. Multiple patterns can be separated by comma. For 
example to include all kafka routes, you can say kafka:. And to include routes 
with specific route ids myRoute,myOt [...]
+    "excludeRoutes": { "kind": "attribute", "displayName": "Exclude Routes", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Pattern for filtering 
routes to be excluded as supervised. The pattern is matching on route id, and 
endpoint uri for the route. Multiple patterns can be separated by comma. For 
example to exclude all JMS routes, you can say jms:. And to exclude routes with 
specific route ids mySpecialRoute,m [...]
+    "threadPoolSize": { "kind": "attribute", "displayName": "Thread Pool 
Size", "required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "defaultValue": "1", "description": "The 
number of threads used by the scheduled thread pool that are used for 
restarting routes. The pool uses 1 thread by default, but you can increase this 
to allow the controller to concurrently attempt to restart multiple routes in 
case more than one route has problem [...]
+    "initialDelay": { "kind": "attribute", "displayName": "Initial Delay", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Initial delay in milli 
seconds before the route controller starts, after CamelContext has been 
started." },
+    "backOffDelay": { "kind": "attribute", "displayName": "Back Off Delay", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "defaultValue": "2000", "description": 
"Backoff delay in millis when restarting a route that failed to startup." },
+    "backOffMaxDelay": { "kind": "attribute", "displayName": "Back Off Max 
Delay", "required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Backoff maximum delay in 
millis when restarting a route that failed to startup." },
+    "backOffMaxElapsedTime": { "kind": "attribute", "displayName": "Back Off 
Max Elapsed Time", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "secret": false, "description": 
"Backoff maximum elapsed time in millis, after which the backoff should be 
considered exhausted and no more attempts should be made." },
+    "backOffMaxAttempts": { "kind": "attribute", "displayName": "Back Off Max 
Attempts", "required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Backoff maximum number of 
attempts to restart a route that failed to startup. When this threshold has 
been exceeded then the controller will give up attempting to restart the route, 
and the route will remain as stopped." },
+    "backOffMultiplier": { "kind": "attribute", "displayName": "Back Off 
Multiplier", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "secret": false, "defaultValue": 
"1.0", "description": "Backoff multiplier to use for exponential backoff. This 
is used to extend the delay between restart attempts." },
+    "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"secret": false, "description": "The id of this node" }
+  }
+}
diff --git 
a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
 
b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
index cec0b69..ba4457c 100644
--- 
a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
+++ 
b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
@@ -117,6 +117,7 @@ import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StreamCachingStrategy;
+import org.apache.camel.spi.SupervisingRouteController;
 import org.apache.camel.spi.ThreadPoolFactory;
 import org.apache.camel.spi.ThreadPoolProfile;
 import org.apache.camel.spi.Transformer;
@@ -382,12 +383,6 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
             LOG.info("Using HealthCheckService: {}", healthCheckService);
             getContext().addService(healthCheckService);
         }
-        // Route controller
-        RouteController routeController = 
getBeanForType(RouteController.class);
-        if (routeController != null) {
-            LOG.info("Using RouteController: {}", routeController);
-            getContext().setRouteController(routeController);
-        }
         // UuidGenerator
         UuidGenerator uuidGenerator = getBeanForType(UuidGenerator.class);
         if (uuidGenerator != null) {
@@ -417,6 +412,9 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
 
         // init stream caching strategy
         initStreamCachingStrategy();
+
+        // init route controller
+        initRouteController();
     }
     //CHECKSTYLE:ON
 
@@ -647,6 +645,64 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
         }
     }
 
+    protected void initRouteController() throws Exception {
+        // Route controller
+        RouteController routeController = 
getBeanForType(RouteController.class);
+        if (routeController != null) {
+            LOG.info("Using RouteController: {}", routeController);
+            getContext().setRouteController(routeController);
+            // we are using custom so dont attempt to use the default below
+            return;
+        }
+
+        CamelRouteControllerDefinition rc = getCamelRouteController();
+        if (rc == null) {
+            return;
+        }
+
+        SupervisingRouteController src = null;
+        Boolean enabled = CamelContextHelper.parseBoolean(getContext(), 
rc.getSupervising());
+        if (enabled != null) {
+            src = getContext().getRouteController().supervising();
+        }
+        String includeRoutes = CamelContextHelper.parseText(getContext(), 
rc.getIncludeRoutes());
+        if (includeRoutes != null && src != null) {
+            src.setIncludeRoutes(includeRoutes);
+        }
+        String excludeRoutes = CamelContextHelper.parseText(getContext(), 
rc.getExcludeRoutes());
+        if (excludeRoutes != null && src != null) {
+            src.setExcludeRoutes(excludeRoutes);
+        }
+        Integer threadPoolSize = CamelContextHelper.parseInteger(getContext(), 
rc.getThreadPoolSize());
+        if (threadPoolSize != null && src != null) {
+            src.setThreadPoolSize(threadPoolSize);
+        }
+        Long initialDelay = CamelContextHelper.parseLong(getContext(), 
rc.getInitialDelay());
+        if (initialDelay != null && src != null) {
+            src.setInitialDelay(initialDelay);
+        }
+        Long backoffDelay = CamelContextHelper.parseLong(getContext(), 
rc.getBackOffDelay());
+        if (backoffDelay != null && src != null) {
+            src.setBackOffDelay(backoffDelay);
+        }
+        Long backOffMaxDelay = CamelContextHelper.parseLong(getContext(), 
rc.getBackOffMaxDelay());
+        if (backOffMaxDelay != null && src != null) {
+            src.setBackOffMaxDelay(backOffMaxDelay);
+        }
+        Long backOffMaxElapsedTime = 
CamelContextHelper.parseLong(getContext(), rc.getBackOffMaxElapsedTime());
+        if (backOffMaxElapsedTime != null && src != null) {
+            src.setBackOffMaxElapsedTime(backOffMaxElapsedTime);
+        }
+        Long backOffMaxAttempts = CamelContextHelper.parseLong(getContext(), 
rc.getBackOffMaxAttempts());
+        if (backOffMaxAttempts != null && src != null) {
+            src.setBackOffMaxAttempts(backOffMaxAttempts);
+        }
+        Double backOffMultiplier = 
CamelContextHelper.parseDouble(getContext(), rc.getBackOffMultiplier());
+        if (backOffMultiplier != null && src != null) {
+            src.setBackOffMultiplier(backOffMultiplier);
+        }
+    }
+
     protected void initPropertyPlaceholder() throws Exception {
         if (getCamelPropertyPlaceholder() != null) {
             CamelPropertyPlaceholderDefinition def = 
getCamelPropertyPlaceholder();
@@ -825,6 +881,8 @@ public abstract class AbstractCamelContextFactoryBean<T 
extends ModelCamelContex
 
     public abstract CamelStreamCachingStrategyDefinition 
getCamelStreamCachingStrategy();
 
+    public abstract CamelRouteControllerDefinition getCamelRouteController();
+
     public abstract List<RouteBuilderDefinition> getBuilderRefs();
 
     public abstract List<RouteContextRefDefinition> getRouteRefs();
diff --git 
a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelRouteControllerDefinition.java
 
b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelRouteControllerDefinition.java
new file mode 100644
index 0000000..c79142a
--- /dev/null
+++ 
b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelRouteControllerDefinition.java
@@ -0,0 +1,197 @@
+/*
+ * 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.core.xml;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Route controller configuration.
+ */
+@Metadata(label = "spring,configuration")
+@XmlRootElement(name = "routeController")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class CamelRouteControllerDefinition extends IdentifiedType {
+
+    @XmlAttribute @Metadata(defaultValue = "false")
+    private String supervising;
+    @XmlAttribute
+    private String includeRoutes;
+    @XmlAttribute
+    private String excludeRoutes;
+    @XmlAttribute @Metadata(defaultValue = "1")
+    private String threadPoolSize;
+    @XmlAttribute
+    private String initialDelay;
+    @XmlAttribute @Metadata(defaultValue = "2000")
+    private String backOffDelay;
+    @XmlAttribute
+    private String backOffMaxDelay;
+    @XmlAttribute
+    private String backOffMaxElapsedTime;
+    @XmlAttribute
+    private String backOffMaxAttempts;
+    @XmlAttribute @Metadata(defaultValue = "1.0")
+    private String backOffMultiplier;
+
+    public String getSupervising() {
+        return supervising;
+    }
+
+    /**
+     * To enable using supervising route controller which allows Camel to 
startup
+     * and then the controller takes care of starting the routes in a safe 
manner.
+     *
+     * This can be used when you want to startup Camel despite a route may 
otherwise
+     * fail fast during startup and cause Camel to fail to startup as well. By 
delegating
+     * the route startup to the supervising route controller then its manages 
the startup
+     * using a background thread. The controller allows to be configured with 
various
+     * settings to attempt to restart failing routes.
+     */
+    public void setSupervising(String supervising) {
+        this.supervising = supervising;
+    }
+
+    public String getIncludeRoutes() {
+        return includeRoutes;
+    }
+
+    /**
+     * Pattern for filtering routes to be included as supervised.
+     *
+     * The pattern is matching on route id, and endpoint uri for the route.
+     * Multiple patterns can be separated by comma.
+     *
+     * For example to include all kafka routes, you can say <tt>kafka:*</tt>.
+     * And to include routes with specific route ids 
<tt>myRoute,myOtherRoute</tt>.
+     * The pattern supports wildcards and uses the matcher from
+     * org.apache.camel.support.PatternHelper#matchPattern.
+     */
+    public void setIncludeRoutes(String includeRoutes) {
+        this.includeRoutes = includeRoutes;
+    }
+
+    public String getExcludeRoutes() {
+        return excludeRoutes;
+    }
+
+    /**
+     * Pattern for filtering routes to be excluded as supervised.
+     *
+     * The pattern is matching on route id, and endpoint uri for the route.
+     * Multiple patterns can be separated by comma.
+     *
+     * For example to exclude all JMS routes, you can say <tt>jms:*</tt>.
+     * And to exclude routes with specific route ids 
<tt>mySpecialRoute,myOtherSpecialRoute</tt>.
+     * The pattern supports wildcards and uses the matcher from
+     * org.apache.camel.support.PatternHelper#matchPattern.
+     */
+    public void setExcludeRoutes(String excludeRoutes) {
+        this.excludeRoutes = excludeRoutes;
+    }
+
+    public String getThreadPoolSize() {
+        return threadPoolSize;
+    }
+
+    /**
+     * The number of threads used by the scheduled thread pool that are used 
for restarting
+     * routes. The pool uses 1 thread by default, but you can increase this to 
allow the controller
+     * to concurrently attempt to restart multiple routes in case more than 
one route has problems
+     * starting.
+     */
+    public void setThreadPoolSize(String threadPoolSize) {
+        this.threadPoolSize = threadPoolSize;
+    }
+
+    public String getInitialDelay() {
+        return initialDelay;
+    }
+
+    /**
+     * Initial delay in milli seconds before the route controller starts, after
+     * CamelContext has been started.
+     */
+    public void setInitialDelay(String initialDelay) {
+        this.initialDelay = initialDelay;
+    }
+
+    public String getBackOffDelay() {
+        return backOffDelay;
+    }
+
+    /**
+     * Backoff delay in millis when restarting a route that failed to startup.
+     */
+    public void setBackOffDelay(String backOffDelay) {
+        this.backOffDelay = backOffDelay;
+    }
+
+    public String getBackOffMaxDelay() {
+        return backOffMaxDelay;
+    }
+
+    /**
+     * Backoff maximum delay in millis when restarting a route that failed to 
startup.
+     */
+    public void setBackOffMaxDelay(String backOffMaxDelay) {
+        this.backOffMaxDelay = backOffMaxDelay;
+    }
+
+    public String getBackOffMaxElapsedTime() {
+        return backOffMaxElapsedTime;
+    }
+
+    /**
+     * Backoff maximum elapsed time in millis, after which the backoff should 
be considered
+     * exhausted and no more attempts should be made.
+     */
+    public void setBackOffMaxElapsedTime(String backOffMaxElapsedTime) {
+        this.backOffMaxElapsedTime = backOffMaxElapsedTime;
+    }
+
+    public String getBackOffMaxAttempts() {
+        return backOffMaxAttempts;
+    }
+
+    /**
+     * Backoff maximum number of attempts to restart a route that failed to 
startup.
+     * When this threshold has been exceeded then the controller will give up
+     * attempting to restart the route, and the route will remain as stopped.
+     */
+    public void setBackOffMaxAttempts(String backOffMaxAttempts) {
+        this.backOffMaxAttempts = backOffMaxAttempts;
+    }
+
+    public String getBackOffMultiplier() {
+        return backOffMultiplier;
+    }
+
+    /**
+     * Backoff multiplier to use for exponential backoff. This is used to 
extend the delay
+     * between restart attempts.
+     */
+    public void setBackOffMultiplier(String backOffMultiplier) {
+        this.backOffMultiplier = backOffMultiplier;
+    }
+
+}
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
index abb7ece..e3ddb86 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultSupervisingRouteControllerTest.java
@@ -92,7 +92,6 @@ public class DefaultSupervisingRouteControllerTest extends 
ContextTestSupport {
         src.setBackOffMaxAttempts(10);
         src.setInitialDelay(100);
         src.setThreadPoolSize(2);
-        context.setRouteController(src);
 
         context.start();
 

Reply via email to