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 2021/08/03 12:33:30 UTC

[camel] branch CAMEL-16757b created (now 8ee3b06)

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

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


      at 8ee3b06  CAMEL-16757: Added route configuration docs

This branch includes the following new commits:

     new 58d633e  Merge branch 'CAMEL-16757' into CAMEL-16757b
     new 90824ad  CAMEL-16757: routes configuration for intercept, on completion
     new 3b521f8  Polihed
     new cbb3913  CAMEL-16757: routes configuration for intercept, on completion
     new 2e44237  CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.
     new 15eb07b  CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.
     new 1748351  CAMEL-16757: YAML DSL to support route configuration
     new 83f19b4  CAMEL-16757: polished
     new 69771aa  CAMEL-16833: LambdaEndpointRouteBuilder
     new 4bd662a  CAMEL-16757: camel-endpointdsl to have route configuration builder also.
     new 10aafb1  CAMEL-16757: camel-endpointdsl to have route configuration builder also.
     new b221561  CAMEL-16757: YAML DSL to support route configuration
     new 0a6b029  CAMEL-16757: YAML DSL to support route configuration
     new 61b7a16  CAMEL-16757: JMX attribute for route configuration ids on route mbean
     new 778fcf5  CAMEL-16757: Rename and polish
     new 00fe78a  Deprecat classic startup logging level
     new f5f7265  Polished
     new 68d3778  CAMEL-16757: Added DEBUG logging when a route is using route configuration ids. Added summary logging if verbose level.
     new 33beec2  CAMEL-16757: route configuration added to classic spring xml (also for cdi xml)
     new 2f24240  CAMEL-16757: spring/blueprint XML to support routeConfiguration
     new afbbb2c  CAMEL-16757: yaml dsl test with route-configuration-id
     new 8ee3b06  CAMEL-16757: Added route configuration docs

The 22 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] 04/22: CAMEL-16757: routes configuration for intercept, on completion

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

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

commit cbb3913ff04db16d2cacc2763f8f3634cc4971b9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 09:01:22 2021 +0200

    CAMEL-16757: routes configuration for intercept, on completion
---
 .../src/main/java/org/apache/camel/model/RoutesDefinition.java           | 1 -
 1 file changed, 1 deletion(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 8f07fba..2df9432 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -43,7 +43,6 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
         implements RouteContainer, CamelContextAware {
     @XmlElementRef
     private List<RouteDefinition> routes = new ArrayList<>();
-    // TODO: Use RoutesConfigurationDefinition instead
     @XmlTransient
     private List<InterceptDefinition> intercepts = new ArrayList<>();
     @XmlTransient

[camel] 15/22: CAMEL-16757: Rename and polish

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

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

commit 778fcf5e2eaed13e9562efe64f615d4a1a44ffa0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 09:00:48 2021 +0200

    CAMEL-16757: Rename and polish
---
 .../java/org/apache/camel/model/RouteDefinition.java   | 18 +++++++++---------
 .../java/org/apache/camel/model/RoutesDefinition.java  |  2 +-
 .../java/org/apache/camel/reifier/RouteReifier.java    |  4 +++-
 .../RoutesConfigurationBuilderIdOrPatternTest.java     |  8 ++++----
 .../java/org/apache/camel/xml/in/ModelParser.java      |  2 +-
 .../deserializers/RouteDefinitionDeserializer.java     |  6 +++---
 .../src/generated/resources/camel-yaml-dsl.json        |  2 +-
 7 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index d3ef4dd..40ef2e1 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -57,7 +57,7 @@ import org.apache.camel.spi.RoutePolicy;
 public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute {
     private final AtomicBoolean prepared = new AtomicBoolean();
     private FromDefinition input;
-    private String routeConfiguration;
+    private String routeConfigurationId;
     private String group;
     private String streamCache;
     private String trace;
@@ -207,11 +207,11 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
      * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
      * separated by comma.
      *
-     * @param  routeConfiguration id or pattern
-     * @return                    the builder
+     * @param  routeConfigurationId id or pattern
+     * @return                      the builder
      */
-    public RouteDefinition routeConfiguration(String routeConfiguration) {
-        setRouteConfiguration(routeConfiguration);
+    public RouteDefinition routeConfigurationId(String routeConfigurationId) {
+        setRouteConfigurationId(routeConfigurationId);
         return this;
     }
 
@@ -734,8 +734,8 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
      * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
      * separated by comma.
      */
-    public String getRouteConfiguration() {
-        return routeConfiguration;
+    public String getRouteConfigurationId() {
+        return routeConfigurationId;
     }
 
     /**
@@ -743,8 +743,8 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
      * separated by comma.
      */
     @XmlAttribute
-    public void setRouteConfiguration(String routeConfiguration) {
-        this.routeConfiguration = routeConfiguration;
+    public void setRouteConfigurationId(String routeConfigurationId) {
+        this.routeConfigurationId = routeConfigurationId;
     }
 
     /**
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index f4df5fa..4151ff0 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -227,7 +227,7 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
                         // global configurations have no id assigned or is a wildcard
                         // if the route has a route configuration assigned then use pattern matching
                         .filter(g -> (g.getId() == null || g.getId().equals("*"))
-                                || (PatternHelper.matchPattern(g.getId(), route.getRouteConfiguration())))
+                                || (PatternHelper.matchPattern(g.getId(), route.getRouteConfigurationId())))
                         .forEach(g -> {
                             oe.addAll(g.getOnExceptions());
                             icp.addAll(g.getIntercepts());
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
index bb7da1b..f921817 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
@@ -373,7 +373,9 @@ public class RouteReifier extends ProcessorReifier<RouteDefinition> {
         routeProperties.put(Route.REST_PROPERTY, rest);
         String template = Boolean.toString(definition.isTemplate() != null && definition.isTemplate());
         routeProperties.put(Route.TEMPLATE_PROPERTY, template);
-        routeProperties.put(Route.CONFIGURATION_ID_PROPERTY, definition.getRouteConfiguration());
+        if (definition.getRouteConfigurationId() != null) {
+            routeProperties.put(Route.CONFIGURATION_ID_PROPERTY, definition.getRouteConfigurationId());
+        }
 
         List<PropertyDefinition> properties = definition.getRouteProperties();
         if (properties != null) {
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
index c21ce74..ebefa1b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -52,7 +52,7 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
             @Override
             public void configure() throws Exception {
                 from("direct:start2")
-                        .routeConfiguration("handleError")
+                        .routeConfigurationId("handleError")
                         .throwException(new IllegalArgumentException("Foo2"));
             }
         });
@@ -101,7 +101,7 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
             @Override
             public void configure() throws Exception {
                 from("direct:start")
-                        .routeConfiguration("general*")
+                        .routeConfigurationId("general*")
                         .throwException(new IllegalArgumentException("Foo"));
             }
         });
@@ -109,7 +109,7 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
             @Override
             public void configure() throws Exception {
                 from("direct:start2")
-                        .routeConfiguration("io*")
+                        .routeConfigurationId("io*")
                         .throwException(new IOException("Foo2"));
             }
         });
@@ -206,7 +206,7 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
             @Override
             public void configure() throws Exception {
                 from("direct:start2").routeId("foo2")
-                        .routeConfiguration("ioError")
+                        .routeConfigurationId("ioError")
                         .throwException(new IOException("Foo2"));
             }
         });
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 53df0c2..b8fa6e4 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1001,7 +1001,7 @@ public class ModelParser extends BaseParser {
                 case "group": def.setGroup(val); break;
                 case "logMask": def.setLogMask(val); break;
                 case "messageHistory": def.setMessageHistory(val); break;
-                case "routeConfiguration": def.setRouteConfiguration(val); break;
+                case "routeConfigurationId": def.setRouteConfigurationId(val); break;
                 case "routePolicyRef": def.setRoutePolicyRef(val); break;
                 case "shutdownRoute": def.setShutdownRoute(val); break;
                 case "shutdownRunningTask": def.setShutdownRunningTask(val); break;
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
index 074a387..da7ca89 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
@@ -37,7 +37,7 @@ import org.snakeyaml.engine.v2.nodes.NodeTuple;
           properties = {
                   @YamlProperty(name = "id", type = "string"),
                   @YamlProperty(name = "group", type = "string"),
-                  @YamlProperty(name = "route-configuration", type = "string"),
+                  @YamlProperty(name = "route-configuration-id", type = "string"),
                   @YamlProperty(name = "from", type = "object:org.apache.camel.model.FromDefinition", required = true),
                   @YamlProperty(name = "steps", type = "array:org.apache.camel.model.ProcessorDefinition", required = true)
           })
@@ -71,8 +71,8 @@ public class RouteDefinitionDeserializer extends YamlDeserializerBase<RouteDefin
                 case "group":
                     target.setGroup(asText(val));
                     break;
-                case "route-configuration":
-                    target.setRouteConfiguration(asText(val));
+                case "route-configuration-id":
+                    target.setRouteConfigurationId(asText(val));
                     break;
                 case "from":
                     target.setInput(asType(val, FromDefinition.class));
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 90d56ae..10e7ac6 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2098,7 +2098,7 @@
           "id" : {
             "type" : "string"
           },
-          "route-configuration" : {
+          "route-configuration-id" : {
             "type" : "string"
           },
           "steps" : {

[camel] 17/22: Polished

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

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

commit f5f72657d5e93d87dbaaf8e5d98bf7c3b4f385e0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 09:05:49 2021 +0200

    Polished
---
 .../main/java/org/apache/camel/impl/engine/AbstractCamelContext.java | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 1e75104..268a5c4 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -2872,7 +2872,7 @@ public abstract class AbstractCamelContext extends BaseService
             }
         }
 
-        // ant duplicate components in use?
+        // duplicate components in use?
         logDuplicateComponents();
 
         // log startup summary
@@ -3021,8 +3021,7 @@ public abstract class AbstractCamelContext extends BaseService
 
     protected void doStartCamel() throws Exception {
         if (!adapt(ExtendedCamelContext.class).getBeanPostProcessor().isEnabled()) {
-            LOG.info(
-                    "BeanPostProcessor is disabled. This means features such as dependency injection of Camel annotations in beans is not supported.");
+            LOG.info("BeanPostProcessor is disabled. Dependency injection of Camel annotations in beans is not supported.");
         }
         if (LOG.isDebugEnabled()) {
             LOG.debug(

[camel] 14/22: CAMEL-16757: JMX attribute for route configuration ids on route mbean

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

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

commit 61b7a166b8de05da3e8856f84fb9ca7fc20888b6
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 07:20:55 2021 +0200

    CAMEL-16757: JMX attribute for route configuration ids on route mbean
---
 core/camel-api/src/main/java/org/apache/camel/Route.java  | 11 +++++++++++
 .../java/org/apache/camel/impl/engine/DefaultRoute.java   |  6 ++++++
 .../main/java/org/apache/camel/reifier/RouteReifier.java  |  3 ++-
 .../camel/api/management/mbean/ManagedRouteMBean.java     |  3 +++
 .../org/apache/camel/management/mbean/ManagedRoute.java   | 15 +++++++++++----
 5 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/Route.java b/core/camel-api/src/main/java/org/apache/camel/Route.java
index 808dc35..27e5e84 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Route.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Route.java
@@ -44,6 +44,7 @@ public interface Route extends RuntimeConfiguration {
     String REST_PROPERTY = "rest";
     String TEMPLATE_PROPERTY = "template";
     String DESCRIPTION_PROPERTY = "description";
+    String CONFIGURATION_ID_PROPERTY = "configurationId";
 
     /**
      * Gets the route id
@@ -116,6 +117,16 @@ public interface Route extends RuntimeConfiguration {
     String getDescription();
 
     /**
+     * Gets the route configuration id(s) (if any has been configured).
+     * <p/>
+     * The configuration ids is configured using the {@link #CONFIGURATION_ID_PROPERTY} as key in the
+     * {@link #getProperties()}.
+     *
+     * @return the configuration, or <tt>null</tt> if no configuration has been configured.
+     */
+    String getConfigurationId();
+
+    /**
      * Gets the camel context
      *
      * @return the camel context
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoute.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoute.java
index fd877b0..3d39dbf 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoute.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoute.java
@@ -157,6 +157,12 @@ public class DefaultRoute extends ServiceSupport implements Route {
     }
 
     @Override
+    public String getConfigurationId() {
+        Object value = properties.get(Route.CONFIGURATION_ID_PROPERTY);
+        return value != null ? (String) value : null;
+    }
+
+    @Override
     public void initializeServices() throws Exception {
         // gather all the services for this route
         gatherServices(services);
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
index 10ede58..bb7da1b 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RouteReifier.java
@@ -58,7 +58,7 @@ public class RouteReifier extends ProcessorReifier<RouteDefinition> {
     private static final String[] RESERVED_PROPERTIES = new String[] {
             Route.ID_PROPERTY, Route.CUSTOM_ID_PROPERTY, Route.PARENT_PROPERTY,
             Route.DESCRIPTION_PROPERTY, Route.GROUP_PROPERTY,
-            Route.REST_PROPERTY };
+            Route.REST_PROPERTY, Route.CONFIGURATION_ID_PROPERTY };
 
     public RouteReifier(CamelContext camelContext, ProcessorDefinition<?> definition) {
         super(camelContext, (RouteDefinition) definition);
@@ -373,6 +373,7 @@ public class RouteReifier extends ProcessorReifier<RouteDefinition> {
         routeProperties.put(Route.REST_PROPERTY, rest);
         String template = Boolean.toString(definition.isTemplate() != null && definition.isTemplate());
         routeProperties.put(Route.TEMPLATE_PROPERTY, template);
+        routeProperties.put(Route.CONFIGURATION_ID_PROPERTY, definition.getRouteConfiguration());
 
         List<PropertyDefinition> properties = definition.getRouteProperties();
         if (properties != null) {
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
index 304998a..e019e88 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
@@ -35,6 +35,9 @@ public interface ManagedRouteMBean extends ManagedPerformanceCounterMBean {
     @ManagedAttribute(description = "Route Description")
     String getDescription();
 
+    @ManagedAttribute(description = "Route Configuration ID")
+    String getRouteConfigurationId();
+
     @ManagedAttribute(description = "Route Endpoint URI", mask = true)
     String getEndpointUri();
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
index 87ab081..988dc20 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
@@ -71,6 +71,7 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
 
     protected final Route route;
     protected final String description;
+    protected final String configurationId;
     protected final CamelContext context;
     private final LoadTriplet load = new LoadTriplet();
     private final String jmxDomain;
@@ -79,6 +80,7 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         this.route = route;
         this.context = context;
         this.description = route.getDescription();
+        this.configurationId = route.getConfigurationId();
         this.jmxDomain = context.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName();
     }
 
@@ -143,6 +145,11 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
     }
 
     @Override
+    public String getRouteConfigurationId() {
+        return configurationId;
+    }
+
+    @Override
     public String getEndpointUri() {
         if (route.getEndpoint() != null) {
             return route.getEndpoint().getEndpointUri();
@@ -171,10 +178,6 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         return route.getUptimeMillis();
     }
 
-    public Integer getInflightExchanges() {
-        return (int) super.getExchangesInflight();
-    }
-
     @Override
     public String getCamelId() {
         return context.getName();
@@ -646,6 +649,10 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         }
     }
 
+    private Integer getInflightExchanges() {
+        return (int) super.getExchangesInflight();
+    }
+
     /**
      * Used for sorting the processor mbeans accordingly to their index.
      */

[camel] 19/22: CAMEL-16757: route configuration added to classic spring xml (also for cdi xml)

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

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

commit 33beec2734a530d044f6ce4f15592824ab10e90a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 11:03:12 2021 +0200

    CAMEL-16757: route configuration added to classic spring xml (also for cdi xml)
---
 .../camel/cdi/xml/CamelContextFactoryBean.java     | 14 ++++
 .../camel/cdi/test/XmlRouteConfigurationTest.java  | 77 ++++++++++++++++++++++
 .../resources/camel-context-routeConfiguration.xml | 49 ++++++++++++++
 .../org/apache/camel/spring/xml/camelContext.json  |  1 +
 .../camel/spring/xml/CamelContextFactoryBean.java  | 18 +++++
 .../spring/xml/handler/CamelNamespaceHandler.java  |  1 +
 ...gRoutesConfigurationBuilderIdOrPatternTest.java | 48 ++++++++++++++
 ...ngRoutesConfigurationBuilderIdOrPatternTest.xml | 52 +++++++++++++++
 .../java/org/apache/camel/impl/DefaultModel.java   |  9 +++
 ...ainer.java => RouteConfigurationContainer.java} | 16 ++---
 .../camel/model/RouteConfigurationsDefinition.java |  2 +-
 .../org/apache/camel/model/RouteContainer.java     |  2 +-
 .../apache/camel/model/RouteTemplateContainer.java |  2 +-
 .../core/xml/AbstractCamelContextFactoryBean.java  | 45 +++++++++++--
 .../RoutesConfigurationBuilderIdOrPatternTest.java | 21 ++++++
 15 files changed, 342 insertions(+), 15 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 001012d..96b7170 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
@@ -59,6 +59,7 @@ import org.apache.camel.model.PackageScanDefinition;
 import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RestContextRefDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateContextRefDefinition;
@@ -296,6 +297,9 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
     @XmlElement(name = "rest")
     private List<RestDefinition> rests = new ArrayList<>();
 
+    @XmlElement(name = "routeConfiguration")
+    private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
+
     @XmlElement(name = "routeTemplate")
     private List<RouteTemplateDefinition> routeTemplates = new ArrayList<>();
 
@@ -492,6 +496,16 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
     }
 
     @Override
+    public List<RouteConfigurationDefinition> getRouteConfigurations() {
+        return routeConfigurations;
+    }
+
+    @Override
+    public void setRouteConfigurations(List<RouteConfigurationDefinition> routeConfigurations) {
+        this.routeConfigurations = routeConfigurations;
+    }
+
+    @Override
     public List<RouteTemplateDefinition> getRouteTemplates() {
         return routeTemplates;
     }
diff --git a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java
new file mode 100644
index 0000000..7bbcb0d
--- /dev/null
+++ b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.cdi.test;
+
+import java.nio.file.Paths;
+
+import javax.inject.Inject;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.cdi.CdiCamelExtension;
+import org.apache.camel.cdi.ImportResource;
+import org.apache.camel.cdi.Uri;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.fail;
+
+@RunWith(Arquillian.class)
+@ImportResource("imported-context.xml")
+public class XmlRouteConfigurationTest {
+
+    @Inject
+    private ProducerTemplate template;
+
+    @Inject
+    @Uri("mock:error")
+    private MockEndpoint mock;
+
+    @Deployment
+    public static Archive<?> deployment() {
+        return ShrinkWrap.create(JavaArchive.class)
+                // Camel CDI
+                .addPackage(CdiCamelExtension.class.getPackage())
+                // Test Camel XML
+                .addAsResource(
+                        Paths.get("src/test/resources/camel-context-routeConfiguration.xml").toFile(),
+                        "imported-context.xml")
+                // Bean archive deployment descriptor
+                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+    }
+
+    @Test
+    public void testRoutesConfigurationOnException() throws Exception {
+        mock.expectedBodiesReceived("Bye World");
+
+        try {
+            template.sendBody("direct:start", "Hello World");
+            fail("Should throw exception");
+        } catch (Exception e) {
+            // expected
+        }
+        template.sendBody("direct:start2", "Bye World");
+
+        mock.assertIsSatisfied();
+    }
+}
diff --git a/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml b/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml
new file mode 100644
index 0000000..a77cae3
--- /dev/null
+++ b/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml
@@ -0,0 +1,49 @@
+<?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">
+
+    <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+        <routeConfiguration id="handleError">
+            <onException>
+                <exception>java.lang.Exception</exception>
+                <handled>
+                    <constant>true</constant>
+                </handled>
+                <to uri="mock:error"/>
+            </onException>
+        </routeConfiguration>
+
+        <route>
+            <from uri="direct:start"/>
+            <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo"/>
+        </route>
+
+        <route routeConfigurationId="handleError">
+            <from uri="direct:start2"/>
+            <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo2"/>
+        </route>
+
+    </camelContext>
+
+</beans>
diff --git a/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json b/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
index fb39212..9a6507f 100644
--- a/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
+++ b/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
@@ -80,6 +80,7 @@
     "interceptSendToEndpoint": { "kind": "element", "displayName": "Intercept Send To Endpoint", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptSendToEndpointDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Configuration of interceptors that triggers sending messages to endpoints." },
     "restConfiguration": { "kind": "element", "displayName": "Rest Configuration", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestConfigurationDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Configuration for rest-dsl" },
     "rest": { "kind": "element", "displayName": "Rest", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.RestDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the rest services defined using the rest-dsl" },
+    "routeConfiguration": { "kind": "element", "displayName": "Route Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel route configurations" },
     "routeTemplate": { "kind": "element", "displayName": "Route Template", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteTemplateDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel route templates" },
     "route": { "kind": "element", "displayName": "Route", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel routes" },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }
diff --git a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
index 87a990e..4aa862d 100644
--- a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
+++ b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
@@ -57,6 +57,7 @@ import org.apache.camel.model.PackageScanDefinition;
 import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RestContextRefDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationDefinition;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateContextRefDefinition;
@@ -263,6 +264,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
     private RestConfigurationDefinition restConfiguration;
     @XmlElement(name = "rest")
     private List<RestDefinition> rests = new ArrayList<>();
+    @XmlElement(name = "routeConfiguration")
+    private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
     @XmlElement(name = "routeTemplate")
     private List<RouteTemplateDefinition> routeTemplates = new ArrayList<>();
     @XmlElement(name = "route")
@@ -557,6 +560,20 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
         this.routes = routes;
     }
 
+    @Override
+    public List<RouteConfigurationDefinition> getRouteConfigurations() {
+        return routeConfigurations;
+    }
+
+    /**
+     * Contains the Camel route configurations
+     */
+    @Override
+    public void setRouteConfigurations(List<RouteConfigurationDefinition> routeConfigurations) {
+        this.routeConfigurations = routeConfigurations;
+    }
+
+    @Override
     public List<RouteTemplateDefinition> getRouteTemplates() {
         return routeTemplates;
     }
@@ -564,6 +581,7 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
     /**
      * Contains the Camel route templates
      */
+    @Override
     public void setRouteTemplates(List<RouteTemplateDefinition> routeTemplates) {
         this.routeTemplates = routeTemplates;
     }
diff --git a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
index d7272be..fed1bba 100644
--- a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
+++ b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
@@ -390,6 +390,7 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
                 builder.addPropertyValue("implicitId", implicitId);
                 builder.addPropertyValue("restConfiguration", factoryBean.getRestConfiguration());
                 builder.addPropertyValue("rests", factoryBean.getRests());
+                builder.addPropertyValue("routeConfigurations", factoryBean.getRouteConfigurations());
                 builder.addPropertyValue("routeTemplates", factoryBean.getRouteTemplates());
                 builder.addPropertyValue("routes", factoryBean.getRoutes());
                 builder.addPropertyValue("intercepts", factoryBean.getIntercepts());
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java
new file mode 100644
index 0000000..5e9a316
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spring;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class SpringRoutesConfigurationBuilderIdOrPatternTest extends SpringTestSupport {
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext(
+                "org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml");
+    }
+
+    @Test
+    public void testRoutesConfigurationOnException() throws Exception {
+        getMockEndpoint("mock:error").expectedBodiesReceived("Bye World");
+
+        try {
+            template.sendBody("direct:start", "Hello World");
+            fail("Should throw exception");
+        } catch (Exception e) {
+            // expected
+        }
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml
new file mode 100644
index 0000000..f8b4d43
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml
@@ -0,0 +1,52 @@
+<?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
+    ">
+
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+    <routeConfiguration id="handleError">
+      <onException>
+        <exception>java.lang.Exception</exception>
+        <handled>
+          <constant>true</constant>
+        </handled>
+        <to uri="mock:error"/>
+      </onException>
+    </routeConfiguration>
+
+    <route>
+      <from uri="direct:start"/>
+      <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo"/>
+    </route>
+
+    <route routeConfigurationId="handleError">
+      <from uri="direct:start2"/>
+      <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo2"/>
+    </route>
+
+  </camelContext>
+
+</beans>
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 475a975..b658b6b 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -123,6 +123,15 @@ public class DefaultModel implements Model {
         // only add if not already exists (route-loader may let Java DSL add route configuration twice
         // because it extends RouteBuilder as base class)
         if (!this.routesConfigurations.contains(routesConfiguration)) {
+            // check that there is no id clash
+            if (routesConfiguration.getId() != null) {
+                boolean clash = this.routesConfigurations.stream()
+                        .anyMatch(r -> ObjectHelper.equal(r.getId(), routesConfiguration.getId()));
+                if (clash) {
+                    throw new IllegalArgumentException(
+                            "Route configuration already exists with id: " + routesConfiguration.getId());
+                }
+            }
             this.routesConfigurations.add(routesConfiguration);
         }
     }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
similarity index 69%
copy from core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
copy to core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
index 5e4ba8e..c46aabe 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
@@ -21,22 +21,22 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElementRef;
 
 /**
- * Container to hold {@link org.apache.camel.model.RouteDefinition Route}.
+ * Container to hold {@link RouteConfigurationDefinition route configurations}.
  */
-public interface RouteContainer {
+public interface RouteConfigurationContainer {
 
     /**
-     * Returns the routes
+     * Returns the route configurations
      *
-     * @return the routes
+     * @return the route configurations
      */
     @XmlElementRef
-    List<RouteDefinition> getRoutes();
+    List<RouteConfigurationDefinition> getRouteConfigurations();
 
     /**
-     * Sets the routes to use
+     * Sets the route configurations to use
      *
-     * @param routes the routes
+     * @param routes the route configurations
      */
-    void setRoutes(List<RouteDefinition> routes);
+    void setRouteConfigurations(List<RouteConfigurationDefinition> routes);
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
index c56874b..92ec02c 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
@@ -34,7 +34,7 @@ import org.apache.camel.spi.Metadata;
 @Metadata(label = "configuration")
 @XmlRootElement(name = "routeConfigurations")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class RouteConfigurationsDefinition {
+public class RouteConfigurationsDefinition implements RouteConfigurationContainer {
 
     @XmlElementRef
     private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
index 5e4ba8e..ba548f2 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
@@ -21,7 +21,7 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElementRef;
 
 /**
- * Container to hold {@link org.apache.camel.model.RouteDefinition Route}.
+ * Container to hold {@link org.apache.camel.model.RouteDefinition routes}.
  */
 public interface RouteContainer {
 
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
index ae4e8c8..b2715c8 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
@@ -21,7 +21,7 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElementRef;
 
 /**
- * Container to hold {@link RouteTemplateDefinition Route}.
+ * Container to hold {@link RouteTemplateDefinition route templates}.
  */
 public interface RouteTemplateContainer {
 
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 2e88712..9b62c51 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
@@ -72,6 +72,8 @@ import org.apache.camel.model.PackageScanDefinition;
 import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RestContextRefDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationContainer;
+import org.apache.camel.model.RouteConfigurationDefinition;
 import org.apache.camel.model.RouteContainer;
 import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
@@ -132,6 +134,7 @@ import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.spi.Validator;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.ObjectHelper;
+import org.apache.camel.support.PatternHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
 import org.slf4j.Logger;
@@ -143,7 +146,7 @@ import org.slf4j.LoggerFactory;
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContext> extends IdentifiedType
-        implements RouteTemplateContainer, RouteContainer, RestContainer {
+        implements RouteTemplateContainer, RouteConfigurationContainer, RouteContainer, RestContainer {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractCamelContextFactoryBean.class);
 
@@ -444,6 +447,9 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
             // mark that we are setting up routes
             getContext().adapt(ExtendedCamelContext.class).setupRoutes(false);
 
+            // add route configurations
+            getContext().addRouteConfigurations(getRouteConfigurations());
+
             // init route templates
             initRouteTemplateRefs();
 
@@ -546,9 +552,37 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
             // sanity check first as the route is created using XML
             RouteDefinitionHelper.sanityCheckRoute(route);
 
-            // leverage logic from route definition helper to prepare the route
-            RouteDefinitionHelper.prepareRoute(getContext(), route, getOnExceptions(), getIntercepts(), getInterceptFroms(),
-                    getInterceptSendToEndpoints(), getOnCompletions());
+            // merge global and route scoped together
+            List<OnExceptionDefinition> oe = new ArrayList<>(getOnExceptions());
+            List<InterceptDefinition> icp = new ArrayList<>(getIntercepts());
+            List<InterceptFromDefinition> ifrom = new ArrayList<>(getInterceptFroms());
+            List<InterceptSendToEndpointDefinition> ito = new ArrayList<>(getInterceptSendToEndpoints());
+            List<OnCompletionDefinition> oc = new ArrayList<>(getOnCompletions());
+            if (getContext() != null) {
+                List<RouteConfigurationDefinition> globalConfigurations
+                        = getContext().adapt(ModelCamelContext.class).getRouteConfigurationDefinitions();
+                if (globalConfigurations != null) {
+                    globalConfigurations.stream()
+                            // global configurations have no id assigned or is a wildcard
+                            // if the route has a route configuration assigned then use pattern matching
+                            .filter(g -> (g.getId() == null || g.getId().equals("*"))
+                                    || (PatternHelper.matchPattern(g.getId(), route.getRouteConfigurationId())))
+                            .forEach(g -> {
+                                oe.addAll(g.getOnExceptions());
+                                icp.addAll(g.getIntercepts());
+                                ifrom.addAll(g.getInterceptFroms());
+                                ito.addAll(g.getInterceptSendTos());
+                                oc.addAll(g.getOnCompletions());
+                            });
+                }
+            }
+
+            // must prepare the route before we can add it to the routes list
+            RouteDefinitionHelper.prepareRoute(getContext(), route, oe, icp, ifrom, ito, oc);
+
+            if (LOG.isDebugEnabled() && route.getRouteConfigurationId() != null) {
+                LOG.debug("Route: {} is using routeConfigurationsId: {}", route.getId(), route.getRouteConfigurationId());
+            }
 
             // mark the route as prepared now
             route.markPrepared();
@@ -857,6 +891,9 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
     public abstract List<RouteTemplateDefinition> getRouteTemplates();
 
     @Override
+    public abstract List<RouteConfigurationDefinition> getRouteConfigurations();
+
+    @Override
     public abstract List<RouteDefinition> getRoutes();
 
     @Override
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
index ebefa1b..d79b4d0 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.model;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -28,6 +29,7 @@ import org.apache.camel.builder.RouteConfigurationBuilder;
 import org.apache.camel.support.OrderedComparator;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
 public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSupport {
@@ -219,4 +221,23 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testRoutesConfigurationIdClash() throws Exception {
+        RouteConfigurationBuilder rcb = new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                routeConfiguration().onException(Exception.class).handled(true).to("mock:foo");
+                routeConfiguration("foo").onException(IOException.class).handled(true).to("mock:foo");
+                routeConfiguration("bar").onException(FileNotFoundException.class).handled(true).to("mock:bar");
+                routeConfiguration("foo").onException(IllegalArgumentException.class).handled(true).to("mock:foo");
+            }
+        };
+        try {
+            context.addRoutesConfigurations(rcb);
+            fail("Should throw exception");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Route configuration already exists with id: foo", e.getMessage());
+        }
+    }
+
 }

[camel] 20/22: CAMEL-16757: spring/blueprint XML to support routeConfiguration

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

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

commit 2f242403ca9500a44f33fcc10832f99cacc22cc4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 11:46:14 2021 +0200

    CAMEL-16757: spring/blueprint XML to support routeConfiguration
---
 .../org/apache/camel/model/routeConfiguration.json |  5 +++
 .../camel/model/RouteConfigurationDefinition.java  | 12 ++---
 .../java/org/apache/camel/xml/in/ModelParser.java  |  2 +-
 .../camel/dsl/yaml/RouteConfigurationTest.groovy   | 51 ++++++++++++++++++++++
 4 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
index 515c123..131da2a 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
@@ -11,6 +11,11 @@
     "output": false
   },
   "properties": {
+    "onException": { "kind": "element", "displayName": "On Exception", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnExceptionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Exception clause for catching certain exceptions and handling them." },
+    "onCompletion": { "kind": "element", "displayName": "On Completion", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnCompletionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "On completion callback for doing custom routing when the org.apache.camel.Exchange is complete." },
+    "intercept": { "kind": "element", "displayName": "Intercept", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds a route for an interceptor that intercepts every processing step." },
+    "interceptFrom": { "kind": "element", "displayName": "Intercept From", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptFromDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Adds a route for an interceptor that intercepts incoming messages on the given endpoint." },
+    "interceptSendToEndpoint": { "kind": "element", "displayName": "Intercept Send To Endpoint", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptSendToEndpointDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Applies a route for an interceptor if an exchange is send to the given endpoint" },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "kind": "element", "displayName": "Description", "required": false, "type": "object", "javaType": "org.apache.camel.model.DescriptionDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" }
   }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
index ae3e8e8..8e4e308 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
@@ -22,7 +22,7 @@ import java.util.List;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.apache.camel.spi.Metadata;
@@ -37,15 +37,15 @@ public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<R
 
     // TODO: Model for ErrorHandler (requires to move error handler model from spring-xml, blueprint to core)
 
-    @XmlElementRef
+    @XmlElement(name = "onException")
     private List<OnExceptionDefinition> onExceptions = new ArrayList<>();
-    @XmlElementRef
+    @XmlElement(name = "onCompletion")
     private List<OnCompletionDefinition> onCompletions = new ArrayList<>();
-    @XmlElementRef
+    @XmlElement(name = "intercept")
     private List<InterceptDefinition> intercepts = new ArrayList<>();
-    @XmlElementRef
+    @XmlElement(name = "interceptFrom")
     private List<InterceptFromDefinition> interceptFroms = new ArrayList<>();
-    @XmlElementRef
+    @XmlElement(name = "interceptSendToEndpoint")
     private List<InterceptSendToEndpointDefinition> interceptSendTos = new ArrayList<>();
 
     public RouteConfigurationDefinition() {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index b8fa6e4..b33981d 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -940,7 +940,7 @@ public class ModelParser extends BaseParser {
         return doParse(new RouteConfigurationDefinition(),
             optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
             switch (key) {
-                case "interceptFrom": doAdd(doParseInterceptFromDefinition(), def.getIntercepts(), def::setIntercepts); break;
+                case "interceptFrom": doAdd(doParseInterceptFromDefinition(), def.getInterceptFroms(), def::setInterceptFroms); break;
                 case "interceptSendToEndpoint": doAdd(doParseInterceptSendToEndpointDefinition(), def.getInterceptSendTos(), def::setInterceptSendTos); break;
                 case "intercept": doAdd(doParseInterceptDefinition(), def.getIntercepts(), def::setIntercepts); break;
                 case "onCompletion": doAdd(doParseOnCompletionDefinition(), def.getOnCompletions(), def::setOnCompletions); break;
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
index 80aa3fe..fc347ff 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
@@ -20,6 +20,7 @@ import org.apache.camel.component.mock.MockEndpoint
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.dsl.yaml.support.model.MyException
 import org.apache.camel.dsl.yaml.support.model.MyFailingProcessor
+import org.junit.jupiter.api.Disabled
 
 class RouteConfigurationTest extends YamlTestSupport {
     def "route-configuration"() {
@@ -106,4 +107,54 @@ class RouteConfigurationTest extends YamlTestSupport {
         MockEndpoint.assertIsSatisfied(context)
     }
 
+    // TODO: fix me
+    /*
+    def "route-configuration-id"() {
+        setup:
+        // global configurations
+        loadRoutes """
+                - beans:
+                  - name: myFailingProcessor
+                    type: ${MyFailingProcessor.name}
+                - route-configuration:
+                    - id: handleError
+                    - on-exception:
+                        handled:
+                          constant: "true"
+                        exception:
+                          - ${MyException.name}
+                        steps:
+                          - transform:
+                              constant: "Sorry"
+                          - to: "mock:on-exception"  
+            """
+        // routes
+        loadRoutes """
+                - from:
+                    uri: "direct:start"
+                    steps:
+                      - process: 
+                          ref: "myFailingProcessor"            
+                - from:
+                    uri: "direct:start2"
+                    steps:
+                      - process: 
+                          ref: "myFailingProcessor"            
+            """
+
+        withMock('mock:on-exception') {
+            expectedBodiesReceived 'Sorry'
+        }
+
+        when:
+        context.start()
+
+        withTemplate {
+            to('direct:start').withBody('hello').send()
+            to('direct:start2').withBody('hello2').send()
+        }
+        then:
+        MockEndpoint.assertIsSatisfied(context)
+    }*/
+
 }

[camel] 09/22: CAMEL-16833: LambdaEndpointRouteBuilder

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

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

commit 69771aa7e887458b5ad127facd39e5c7df2416ce
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 15:14:32 2021 +0200

    CAMEL-16833: LambdaEndpointRouteBuilder
---
 .../builder/endpoint/EndpointRouteBuilder.java     |  6 +-
 .../endpoint/LambdaEndpointRouteBuilder.java       | 35 +++++++++++
 .../endpoint/LambdaEndpointRouteBuilderTest.java   | 70 ++++++++++++++++++++++
 3 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
index 649b86e..77ad7fc 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
@@ -41,15 +41,15 @@ public abstract class EndpointRouteBuilder extends RouteBuilder implements Endpo
      * Add routes to a context using a lambda expression. It can be used as following:
      *
      * <pre>
-     * RouteBuilder.addRoutes(context, rb -&gt;
-     *     rb.from(direct("inbound")).bean(MyBean.class)));
+     * EndpointRouteBuilder.addEndpointRoutes(context, rb -&gt;
+     *     rb.from(rb.direct("inbound")).bean(MyBean.class)));
      * </pre>
      *
      * @param  context   the camel context to add routes
      * @param  rbc       a lambda expression receiving the {@code RouteBuilder} to use for creating routes
      * @throws Exception if an error occurs
      */
-    public static void addEndpointRoutes(CamelContext context, ThrowingConsumer<EndpointRouteBuilder, Exception> rbc)
+    public static void addEndpointRoutes(CamelContext context, LambdaEndpointRouteBuilder rbc)
             throws Exception {
         context.addRoutes(new EndpointRouteBuilder(context) {
             @Override
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilder.java
new file mode 100644
index 0000000..d03121c
--- /dev/null
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilder.java
@@ -0,0 +1,35 @@
+/*
+ * 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.builder.endpoint;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.util.function.ThrowingConsumer;
+
+/**
+ * Functional interface for adding routes to a context using a lambda expression. It can be used as following:
+ *
+ * <pre>
+ * EndpointRouteBuilder.addEndpointRoutes(context, rb ->
+ *     rb.from(rb.direct("inbound")).bean(MyBean.class)));
+ * </pre>
+ *
+ * @see EndpointRouteBuilder#addEndpointRoutes(CamelContext, LambdaEndpointRouteBuilder)
+ */
+@FunctionalInterface
+public interface LambdaEndpointRouteBuilder extends ThrowingConsumer<EndpointRouteBuilder, Exception> {
+
+}
diff --git a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilderTest.java b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilderTest.java
new file mode 100644
index 0000000..fb105fc
--- /dev/null
+++ b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/LambdaEndpointRouteBuilderTest.java
@@ -0,0 +1,70 @@
+package org.apache.camel.builder.endpoint;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class LambdaEndpointRouteBuilderTest extends BaseEndpointDslTest {
+
+    @Test
+    public void testLambda() throws Exception {
+        assertEquals(0, context.getRoutesSize());
+
+        LambdaEndpointRouteBuilder builder = rb -> rb.from(rb.direct("start")).to(rb.mock("result"));
+        context.addRoutes(new EndpointRouteBuilder(context) {
+            @Override
+            public void configure() throws Exception {
+                builder.accept(this);
+            }
+        });
+        context.start();
+
+        assertEquals(1, context.getRoutesSize());
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testLambdaTwo() throws Exception {
+        assertEquals(0, context.getRoutesSize());
+
+        EndpointRouteBuilder.addEndpointRoutes(context, rb -> rb.from(rb.direct("start")).to(rb.mock("result")));
+
+        context.start();
+
+        assertEquals(1, context.getRoutesSize());
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testLambdaSimple() throws Exception {
+        assertEquals(0, context.getRoutesSize());
+
+        EndpointRouteBuilder.addEndpointRoutes(context,
+                rb -> rb.from(rb.direct("start")).transform(rb.simple("Hello ${body}")).to(rb.mock("result")));
+
+        context.start();
+
+        assertEquals(1, context.getRoutesSize());
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}

[camel] 05/22: CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.

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

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

commit 2e44237f5bd29119161a91e8a6a97f3394606fa3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 13:00:47 2021 +0200

    CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.
---
 .../java/org/apache/camel/builder/AdviceWith.java  |  4 +
 .../org/apache/camel/builder/RouteBuilder.java     | 11 ++-
 .../org/apache/camel/model/RouteDefinition.java    | 30 +++++++
 .../org/apache/camel/model/RoutesDefinition.java   | 30 ++++---
 .../RoutesConfigurationBuilderIdOrPatternTest.java | 93 ++++++++++++++++++++++
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 6 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
index 81ddafd..b7c23b5 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java
@@ -229,6 +229,10 @@ public final class AdviceWith {
         // mixed in correctly as well
         RouteDefinition merged = routes.route(definition);
 
+        // must re-prepare the merged route before it can be used
+        merged.markUnprepared();
+        routes.prepareRoute(merged);
+
         // add the new merged route
         model.getRouteDefinitions().add(0, merged);
 
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index c9ebeea..d5185c8d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -478,6 +478,11 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
         populateTransformers();
         populateValidators();
         populateRouteTemplates();
+
+        // ensure routes are prepared before being populated
+        for (RouteDefinition route : routeCollection.getRoutes()) {
+            routeCollection.prepareRoute(route);
+        }
         populateRoutes();
 
         if (this instanceof OnCamelContextEvent) {
@@ -549,10 +554,10 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
             }
 
             configure();
-            // mark all route definitions as custom prepared because
-            // a route builder prepares the route definitions correctly already
+
             for (RouteDefinition route : getRouteCollection().getRoutes()) {
-                route.markPrepared();
+                // ensure the route is prepared after configure method is complete
+                getRouteCollection().prepareRoute(route);
             }
 
             for (RouteBuilderLifecycleStrategy interceptor : lifecycleInterceptors) {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index e6a3d0d..d3ef4dd 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -57,6 +57,7 @@ import org.apache.camel.spi.RoutePolicy;
 public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute {
     private final AtomicBoolean prepared = new AtomicBoolean();
     private FromDefinition input;
+    private String routeConfiguration;
     private String group;
     private String streamCache;
     private String trace;
@@ -203,6 +204,18 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
     }
 
     /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     *
+     * @param  routeConfiguration id or pattern
+     * @return                    the builder
+     */
+    public RouteDefinition routeConfiguration(String routeConfiguration) {
+        setRouteConfiguration(routeConfiguration);
+        return this;
+    }
+
+    /**
      * Set the group name for this route
      *
      * @param  name the group name
@@ -718,6 +731,23 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
     }
 
     /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     */
+    public String getRouteConfiguration() {
+        return routeConfiguration;
+    }
+
+    /**
+     * The route configuration id or pattern this route should use for configuration. Multiple id/pattern can be
+     * separated by comma.
+     */
+    @XmlAttribute
+    public void setRouteConfiguration(String routeConfiguration) {
+        this.routeConfiguration = routeConfiguration;
+    }
+
+    /**
      * The group that this route belongs to; could be the name of the RouteBuilder class or be explicitly configured in
      * the XML.
      * <p/>
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 2df9432..f4df5fa 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -32,6 +32,7 @@ import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.builder.EndpointConsumerBuilder;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
+import org.apache.camel.support.PatternHelper;
 
 /**
  * A series of Camel routes
@@ -203,6 +204,14 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
         if (handler != null) {
             route.setErrorHandlerFactoryIfNull(handler);
         }
+        getRoutes().add(route);
+        return route;
+    }
+
+    public void prepareRoute(RouteDefinition route) {
+        if (route.isPrepared()) {
+            return;
+        }
 
         // merge global and route scoped together
         List<OnExceptionDefinition> oe = new ArrayList<>(onExceptions);
@@ -214,23 +223,26 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
             List<RouteConfigurationDefinition> globalConfigurations
                     = getCamelContext().adapt(ModelCamelContext.class).getRouteConfigurationDefinitions();
             if (globalConfigurations != null) {
-                globalConfigurations.forEach(g -> {
-                    oe.addAll(g.getOnExceptions());
-                    icp.addAll(g.getIntercepts());
-                    ifrom.addAll(g.getInterceptFroms());
-                    ito.addAll(g.getInterceptSendTos());
-                    oc.addAll(g.getOnCompletions());
-                });
+                globalConfigurations.stream()
+                        // global configurations have no id assigned or is a wildcard
+                        // if the route has a route configuration assigned then use pattern matching
+                        .filter(g -> (g.getId() == null || g.getId().equals("*"))
+                                || (PatternHelper.matchPattern(g.getId(), route.getRouteConfiguration())))
+                        .forEach(g -> {
+                            oe.addAll(g.getOnExceptions());
+                            icp.addAll(g.getIntercepts());
+                            ifrom.addAll(g.getInterceptFroms());
+                            ito.addAll(g.getInterceptSendTos());
+                            oc.addAll(g.getOnCompletions());
+                        });
             }
         }
 
         // must prepare the route before we can add it to the routes list
         RouteDefinitionHelper.prepareRoute(getCamelContext(), route, oe, icp, ifrom, ito, oc);
 
-        getRoutes().add(route);
         // mark this route as prepared
         route.markPrepared();
-        return route;
     }
 
     /**
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
new file mode 100644
index 0000000..2a45ad7
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.RouteConfigurationsBuilder;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.RouteConfigurationBuilder;
+import org.apache.camel.support.OrderedComparator;
+import org.junit.jupiter.api.Test;
+
+public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testRoutesConfigurationOnException() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        //        routes.add(new RouteBuilder() {
+        //            @Override
+        //            public void configure() throws Exception {
+        //                from("direct:start")
+        //                        .throwException(new IllegalArgumentException("Foo"));
+        //            }
+        //        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .routeConfiguration("handle*")
+                        .throwException(new IllegalArgumentException("Foo2"));
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // named routes configuration
+                routeConfiguration("handleError").onException(Exception.class).handled(true).to("mock:error");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:error").expectedBodiesReceived("Bye World");
+
+        //        try {
+        //            template.sendBody("direct:start", "Hello World");
+        //            fail("Should throw exception");
+        //        } catch (Exception e) {
+        // expected
+        //        }
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index b5be6f8..53df0c2 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1001,6 +1001,7 @@ public class ModelParser extends BaseParser {
                 case "group": def.setGroup(val); break;
                 case "logMask": def.setLogMask(val); break;
                 case "messageHistory": def.setMessageHistory(val); break;
+                case "routeConfiguration": def.setRouteConfiguration(val); break;
                 case "routePolicyRef": def.setRoutePolicyRef(val); break;
                 case "shutdownRoute": def.setShutdownRoute(val); break;
                 case "shutdownRunningTask": def.setShutdownRunningTask(val); break;

[camel] 03/22: Polihed

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

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

commit 3b521f8f642f49b6e63d3049019f92f43134cbcc
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 08:56:07 2021 +0200

    Polihed
---
 .../src/main/java/org/apache/camel/builder/LambdaRouteBuilder.java      | 2 +-
 .../src/main/java/org/apache/camel/builder/RouteBuilder.java            | 2 +-
 .../java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/LambdaRouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/LambdaRouteBuilder.java
index 48cf43c..55886bc 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/LambdaRouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/LambdaRouteBuilder.java
@@ -24,7 +24,7 @@ import org.apache.camel.util.function.ThrowingConsumer;
  *
  * <pre>
  * RouteBuilder.addRoutes(context, rb ->
- *     rb.from("direct:inbound").bean(ProduceTemplateBean.class)));
+ *     rb.from("direct:inbound").bean(MyBean.class)));
  * </pre>
  *
  * @see RouteBuilder#addRoutes(CamelContext, LambdaRouteBuilder)
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
index bc697b1..c9ebeea 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java
@@ -86,7 +86,7 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
      *
      * <pre>
      * RouteBuilder.addRoutes(context, rb ->
-     *     rb.from("direct:inbound").bean(ProduceTemplateBean.class)));
+     *     rb.from("direct:inbound").bean(MyBean.class)));
      * </pre>
      *
      * @param  context   the camel context to add routes
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
index f9e9190..649b86e 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteBuilder.java
@@ -42,7 +42,7 @@ public abstract class EndpointRouteBuilder extends RouteBuilder implements Endpo
      *
      * <pre>
      * RouteBuilder.addRoutes(context, rb -&gt;
-     *     rb.from("direct:inbound").bean(ProduceTemplateBean.class)));
+     *     rb.from(direct("inbound")).bean(MyBean.class)));
      * </pre>
      *
      * @param  context   the camel context to add routes

[camel] 16/22: Deprecat classic startup logging level

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

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

commit 00fe78a045e25f9ce4294b4be901115bddad8d87
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 09:03:11 2021 +0200

    Deprecat classic startup logging level
---
 core/camel-api/src/main/java/org/apache/camel/StartupSummaryLevel.java | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/core/camel-api/src/main/java/org/apache/camel/StartupSummaryLevel.java b/core/camel-api/src/main/java/org/apache/camel/StartupSummaryLevel.java
index d025d67..9e21bca 100644
--- a/core/camel-api/src/main/java/org/apache/camel/StartupSummaryLevel.java
+++ b/core/camel-api/src/main/java/org/apache/camel/StartupSummaryLevel.java
@@ -24,7 +24,9 @@ import javax.xml.bind.annotation.XmlEnum;
 @XmlEnum
 public enum StartupSummaryLevel {
 
+    @Deprecated
     Classic,
+
     Verbose,
     Default,
     Brief,

[camel] 08/22: CAMEL-16757: polished

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

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

commit 83f19b4fdb8d73b9a876fbb5cc87096298c7ce6d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 14:59:00 2021 +0200

    CAMEL-16757: polished
---
 .../main/java/org/apache/camel/model/RouteConfigurationDefinition.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
index 3ffb1f1..ae3e8e8 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
@@ -35,7 +35,7 @@ import org.apache.camel.spi.Metadata;
 @XmlAccessorType(XmlAccessType.FIELD)
 public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<RouteConfigurationDefinition> {
 
-    // TODO: Model for ErrorHandler
+    // TODO: Model for ErrorHandler (requires to move error handler model from spring-xml, blueprint to core)
 
     @XmlElementRef
     private List<OnExceptionDefinition> onExceptions = new ArrayList<>();

[camel] 12/22: CAMEL-16757: YAML DSL to support route configuration

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

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

commit b2215618f277dee0707348fc5ca31b39d6deb233
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 16:54:26 2021 +0200

    CAMEL-16757: YAML DSL to support route configuration
---
 .../RouteConfigurationDefinitionDeserializer.java  | 33 ++++++++++++++++++++--
 .../src/generated/resources/camel-yaml-dsl.json    |  3 ++
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
index f96fb58..9311269 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
@@ -3,6 +3,10 @@ package org.apache.camel.dsl.yaml.deserializers;
 import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerBase;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerResolver;
+import org.apache.camel.model.InterceptDefinition;
+import org.apache.camel.model.InterceptFromDefinition;
+import org.apache.camel.model.InterceptSendToEndpointDefinition;
+import org.apache.camel.model.OnCompletionDefinition;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RouteConfigurationDefinition;
 import org.apache.camel.spi.annotations.YamlProperty;
@@ -18,6 +22,7 @@ import org.snakeyaml.engine.v2.nodes.SequenceNode;
           order = YamlDeserializerResolver.ORDER_DEFAULT,
           nodes = "route-configuration",
           properties = {
+                  @YamlProperty(name = "id", type = "string"),
                   @YamlProperty(name = "intercept", type = "array:org.apache.camel.model.InterceptDefinition"),
                   @YamlProperty(name = "intercept-from", type = "array:org.apache.camel.model.InterceptFromDefinition"),
                   @YamlProperty(name = "intercept-send-to-endpoint",
@@ -49,10 +54,34 @@ public class RouteConfigurationDefinitionDeserializer extends YamlDeserializerBa
                 final String key = asText(tuple.getKeyNode());
                 final Node val = tuple.getValueNode();
                 switch (key) {
+                    case "id": {
+                        target.setId(asText(val));
+                        break;
+                    }
                     case "on-exception":
                         setDeserializationContext(val, dc);
-                        OnExceptionDefinition obj = asType(val, OnExceptionDefinition.class);
-                        target.getOnExceptions().add(obj);
+                        OnExceptionDefinition oed = asType(val, OnExceptionDefinition.class);
+                        target.getOnExceptions().add(oed);
+                        break;
+                    case "on-completion":
+                        setDeserializationContext(val, dc);
+                        OnCompletionDefinition ocd = asType(val, OnCompletionDefinition.class);
+                        target.getOnCompletions().add(ocd);
+                        break;
+                    case "intercept":
+                        setDeserializationContext(val, dc);
+                        InterceptDefinition id = asType(val, InterceptDefinition.class);
+                        target.getIntercepts().add(id);
+                        break;
+                    case "intercept-from":
+                        setDeserializationContext(val, dc);
+                        InterceptFromDefinition ifd = asType(val, InterceptFromDefinition.class);
+                        target.getInterceptFroms().add(ifd);
+                        break;
+                    case "intercept-send-to-endpoint":
+                        setDeserializationContext(val, dc);
+                        InterceptSendToEndpointDefinition isted = asType(val, InterceptSendToEndpointDefinition.class);
+                        target.getInterceptSendTos().add(isted);
                         break;
                 }
             }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 924421b..90d56ae 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2041,6 +2041,9 @@
         }, {
           "type" : "object",
           "properties" : {
+            "id" : {
+              "type" : "string"
+            },
             "intercept" : {
               "type" : "array",
               "items" : {

[camel] 21/22: CAMEL-16757: yaml dsl test with route-configuration-id

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

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

commit afbbb2ce56d033984ad0f1b0dc6ba3d2c0ead31d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 12:04:04 2021 +0200

    CAMEL-16757: yaml dsl test with route-configuration-id
---
 .../camel/dsl/yaml/RouteConfigurationTest.groovy   | 45 +++++++++++++---------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
index fc347ff..15550bf 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
@@ -16,16 +16,18 @@
  */
 package org.apache.camel.dsl.yaml
 
+import org.apache.camel.Exchange
 import org.apache.camel.component.mock.MockEndpoint
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.dsl.yaml.support.model.MyException
 import org.apache.camel.dsl.yaml.support.model.MyFailingProcessor
+import org.junit.jupiter.api.Assertions
 import org.junit.jupiter.api.Disabled
 
 class RouteConfigurationTest extends YamlTestSupport {
     def "route-configuration"() {
         setup:
-            loadRoutes """
+        loadRoutes """
                 - beans:
                   - name: myFailingProcessor
                     type: ${MyFailingProcessor.name}
@@ -46,18 +48,18 @@ class RouteConfigurationTest extends YamlTestSupport {
                           ref: "myFailingProcessor"            
             """
 
-            withMock('mock:on-exception') {
-                expectedBodiesReceived 'Sorry'
-            }
+        withMock('mock:on-exception') {
+            expectedBodiesReceived 'Sorry'
+        }
 
         when:
-            context.start()
+        context.start()
 
-            withTemplate {
-                to('direct:start').withBody('hello').send()
-            }
+        withTemplate {
+            to('direct:start').withBody('hello').send()
+        }
         then:
-            MockEndpoint.assertIsSatisfied(context)
+        MockEndpoint.assertIsSatisfied(context)
     }
 
     def "route-configuration-separate"() {
@@ -107,8 +109,6 @@ class RouteConfigurationTest extends YamlTestSupport {
         MockEndpoint.assertIsSatisfied(context)
     }
 
-    // TODO: fix me
-    /*
     def "route-configuration-id"() {
         setup:
         // global configurations
@@ -130,13 +130,16 @@ class RouteConfigurationTest extends YamlTestSupport {
             """
         // routes
         loadRoutes """
-                - from:
-                    uri: "direct:start"
+                - route:
+                    route-configuration-id: handleError 
+                    from:
+                        uri: "direct:start"
                     steps:
                       - process: 
                           ref: "myFailingProcessor"            
-                - from:
-                    uri: "direct:start2"
+                - route:
+                    from:
+                        uri: "direct:start2"
                     steps:
                       - process: 
                           ref: "myFailingProcessor"            
@@ -149,12 +152,18 @@ class RouteConfigurationTest extends YamlTestSupport {
         when:
         context.start()
 
+        Exchange out1
+        Exchange out2
         withTemplate {
-            to('direct:start').withBody('hello').send()
-            to('direct:start2').withBody('hello2').send()
+            out1 = to('direct:start').withBody('hello').send()
+            out2 = to('direct:start2').withBody('hello2').send()
         }
+
         then:
         MockEndpoint.assertIsSatisfied(context)
-    }*/
+
+        Assertions.assertFalse(out1.isFailed())
+        Assertions.assertTrue(out2.isFailed())
+    }
 
 }

[camel] 07/22: CAMEL-16757: YAML DSL to support route configuration

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

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

commit 1748351edab6de6cf926da8d76e44f09b3f1db6f
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 13:31:01 2021 +0200

    CAMEL-16757: YAML DSL to support route configuration
---
 .../camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java     | 4 ++++
 .../camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json        | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
index 9170fcb..074a387 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteDefinitionDeserializer.java
@@ -37,6 +37,7 @@ import org.snakeyaml.engine.v2.nodes.NodeTuple;
           properties = {
                   @YamlProperty(name = "id", type = "string"),
                   @YamlProperty(name = "group", type = "string"),
+                  @YamlProperty(name = "route-configuration", type = "string"),
                   @YamlProperty(name = "from", type = "object:org.apache.camel.model.FromDefinition", required = true),
                   @YamlProperty(name = "steps", type = "array:org.apache.camel.model.ProcessorDefinition", required = true)
           })
@@ -70,6 +71,9 @@ public class RouteDefinitionDeserializer extends YamlDeserializerBase<RouteDefin
                 case "group":
                     target.setGroup(asText(val));
                     break;
+                case "route-configuration":
+                    target.setRouteConfiguration(asText(val));
+                    break;
                 case "from":
                     target.setInput(asType(val, FromDefinition.class));
                     break;
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 51527d7..924421b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2095,6 +2095,9 @@
           "id" : {
             "type" : "string"
           },
+          "route-configuration" : {
+            "type" : "string"
+          },
           "steps" : {
             "type" : "array",
             "items" : {

[camel] 18/22: CAMEL-16757: Added DEBUG logging when a route is using route configuration ids. Added summary logging if verbose level.

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

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

commit 68d3778779016ed62c729d9c2f00412f12313e03
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 09:27:29 2021 +0200

    CAMEL-16757: Added DEBUG logging when a route is using route configuration ids. Added summary logging if verbose level.
---
 .../camel/impl/engine/AbstractCamelContext.java    | 17 +++++++++++++++
 .../engine/DefaultSupervisingRouteController.java  | 25 +++++++++++++++++++---
 .../org/apache/camel/model/RoutesDefinition.java   |  9 ++++++++
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 268a5c4..1fbad34 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -2965,6 +2965,7 @@ public abstract class AbstractCamelContext extends BaseService
             int total = 0;
             int disabled = 0;
             List<String> lines = new ArrayList<>();
+            List<String> configs = new ArrayList<>();
             routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder));
             for (RouteStartupOrder order : routeStartupOrder) {
                 total++;
@@ -2977,6 +2978,11 @@ public abstract class AbstractCamelContext extends BaseService
                 String uri = order.getRoute().getEndpoint().getEndpointBaseUri();
                 uri = URISupport.sanitizeUri(uri);
                 lines.add(String.format("    %s %s (%s)", status, id, uri));
+
+                String cid = order.getRoute().getConfigurationId();
+                if (cid != null) {
+                    configs.add(String.format("    %s (%s)", id, cid));
+                }
             }
             for (Route route : routes) {
                 if (!route.isAutoStartup()) {
@@ -2991,6 +2997,11 @@ public abstract class AbstractCamelContext extends BaseService
                     String uri = route.getEndpoint().getEndpointBaseUri();
                     uri = URISupport.sanitizeUri(uri);
                     lines.add(String.format("    %s %s (%s)", status, id, uri));
+
+                    String cid = route.getConfigurationId();
+                    if (cid != null) {
+                        configs.add(String.format("    %s (%s)", id, cid));
+                    }
                 }
             }
             if (disabled > 0) {
@@ -3003,6 +3014,12 @@ public abstract class AbstractCamelContext extends BaseService
                 for (String line : lines) {
                     LOG.info(line);
                 }
+                if (startupSummaryLevel == StartupSummaryLevel.Verbose) {
+                    LOG.info("Routes configuration summary");
+                    for (String line : configs) {
+                        LOG.info(line);
+                    }
+                }
             }
         }
 
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
index ece2f9b..158dbe3 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultSupervisingRouteController.java
@@ -481,6 +481,7 @@ public class DefaultSupervisingRouteController extends DefaultRouteController im
         int restarting = 0;
         int exhausted = 0;
         List<String> lines = new ArrayList<>();
+        List<String> configs = new ArrayList<>();
         for (RouteHolder route : routes) {
             String id = route.getId();
             String status = getRouteStatus(id).name();
@@ -491,7 +492,11 @@ public class DefaultSupervisingRouteController extends DefaultRouteController im
                 // use basic endpoint uri to not log verbose details or potential sensitive data
                 String uri = route.get().getEndpoint().getEndpointBaseUri();
                 uri = URISupport.sanitizeUri(uri);
-                lines.add(String.format("\t%s %s (%s)", status, id, uri));
+                lines.add(String.format("    %s %s (%s)", status, id, uri));
+                String cid = route.get().getConfigurationId();
+                if (cid != null) {
+                    configs.add(String.format("    %s (%s)", id, cid));
+                }
             }
         }
         for (RouteHolder route : routeManager.routes.keySet()) {
@@ -503,7 +508,11 @@ public class DefaultSupervisingRouteController extends DefaultRouteController im
             String uri = route.get().getEndpoint().getEndpointBaseUri();
             uri = URISupport.sanitizeUri(uri);
             BackOff backOff = getBackOff(id);
-            lines.add(String.format("\t%s %s (%s) with %s", status, id, uri, backOff));
+            lines.add(String.format("    %s %s (%s) with %s", status, id, uri, backOff));
+            String cid = route.get().getConfigurationId();
+            if (cid != null) {
+                configs.add(String.format("    %s (%s)", id, cid));
+            }
         }
         for (RouteHolder route : routeManager.exhausted.keySet()) {
             total++;
@@ -513,7 +522,11 @@ public class DefaultSupervisingRouteController extends DefaultRouteController im
             // use basic endpoint uri to not log verbose details or potential sensitive data
             String uri = route.get().getEndpoint().getEndpointBaseUri();
             uri = URISupport.sanitizeUri(uri);
-            lines.add(String.format("\t%s %s (%s)", status, id, uri));
+            lines.add(String.format("    %s %s (%s)", status, id, uri));
+            String cid = route.get().getConfigurationId();
+            if (cid != null) {
+                configs.add(String.format("    %s (%s)", id, cid));
+            }
         }
 
         if (restarting == 0 && exhausted == 0) {
@@ -527,6 +540,12 @@ public class DefaultSupervisingRouteController extends DefaultRouteController im
             for (String line : lines) {
                 LOG.info(line);
             }
+            if (getCamelContext().getStartupSummaryLevel() == StartupSummaryLevel.Verbose) {
+                LOG.info("Routes configuration summary");
+                for (String line : configs) {
+                    LOG.info(line);
+                }
+            }
         }
     }
 
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 4151ff0..f978ab4 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -33,6 +33,8 @@ import org.apache.camel.builder.EndpointConsumerBuilder;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.PatternHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * A series of Camel routes
@@ -42,6 +44,9 @@ import org.apache.camel.support.PatternHelper;
 @XmlAccessorType(XmlAccessType.FIELD)
 public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinition>
         implements RouteContainer, CamelContextAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RoutesDefinition.class);
+
     @XmlElementRef
     private List<RouteDefinition> routes = new ArrayList<>();
     @XmlTransient
@@ -241,6 +246,10 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
         // must prepare the route before we can add it to the routes list
         RouteDefinitionHelper.prepareRoute(getCamelContext(), route, oe, icp, ifrom, ito, oc);
 
+        if (LOG.isDebugEnabled() && route.getRouteConfigurationId() != null) {
+            LOG.debug("Route: {} is using routeConfigurationsId: {}", route.getId(), route.getRouteConfigurationId());
+        }
+
         // mark this route as prepared
         route.markPrepared();
     }

[camel] 10/22: CAMEL-16757: camel-endpointdsl to have route configuration builder also.

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

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

commit 4bd662a01bb647a84c07c6bcbcba0935d01aadb5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 15:29:09 2021 +0200

    CAMEL-16757: camel-endpointdsl to have route configuration builder also.
---
 .../apache/camel/test/junit5/CamelTestSupport.java | 14 +++-
 .../apache/camel/test/junit4/CamelTestSupport.java | 14 +++-
 .../EndpointRouteConfigurationBuilder.java         | 91 ++++++++++++++++++++++
 .../endpoint/EndpointRoutesConfigurationTest.java  | 57 ++++++++++++++
 4 files changed, 172 insertions(+), 4 deletions(-)

diff --git a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
index 0a93950..1a38a28 100644
--- a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
+++ b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/junit5/CamelTestSupport.java
@@ -40,6 +40,7 @@ import org.apache.camel.NoSuchEndpointException;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RouteConfigurationsBuilder;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.Service;
@@ -506,9 +507,18 @@ public abstract class CamelTestSupport
 
         if (isUseRouteBuilder()) {
             RoutesBuilder[] builders = createRouteBuilders();
+            // add configuration before routes
             for (RoutesBuilder builder : builders) {
-                LOG.debug("Using created route builder: {}", builder);
-                context.addRoutes(builder);
+                if (builder instanceof RouteConfigurationsBuilder) {
+                    LOG.debug("Using created route configuration: {}", builder);
+                    context.addRoutesConfigurations((RouteConfigurationsBuilder) builder);
+                }
+            }
+            for (RoutesBuilder builder : builders) {
+                if (!(builder instanceof RouteConfigurationsBuilder)) {
+                    LOG.debug("Using created route builder: {}", builder);
+                    context.addRoutes(builder);
+                }
             }
             replaceFromEndpoints();
             boolean skip = "true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"));
diff --git a/components/camel-test/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java b/components/camel-test/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
index fd83f71..e7a8a79 100644
--- a/components/camel-test/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
+++ b/components/camel-test/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
@@ -56,6 +56,7 @@ import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.Route;
+import org.apache.camel.RouteConfigurationsBuilder;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.Service;
@@ -444,9 +445,18 @@ public abstract class CamelTestSupport extends TestSupport {
 
         if (isUseRouteBuilder()) {
             RoutesBuilder[] builders = createRouteBuilders();
+            // add configuration before routes
             for (RoutesBuilder builder : builders) {
-                LOG.debug("Using created route builder: {}", builder);
-                context.addRoutes(builder);
+                if (builder instanceof RouteConfigurationsBuilder) {
+                    log.debug("Using created route configuration: {}", builder);
+                    context.addRoutesConfigurations((RouteConfigurationsBuilder) builder);
+                }
+            }
+            for (RoutesBuilder builder : builders) {
+                if (!(builder instanceof RouteConfigurationsBuilder)) {
+                    log.debug("Using created route builder: {}", builder);
+                    context.addRoutes(builder);
+                }
             }
             replaceFromEndpoints();
             boolean skip = "true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"));
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteConfigurationBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteConfigurationBuilder.java
new file mode 100644
index 0000000..7122067
--- /dev/null
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointRouteConfigurationBuilder.java
@@ -0,0 +1,91 @@
+/*
+ * 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.builder.endpoint;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RouteConfigurationsBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RouteConfigurationDefinition;
+import org.apache.camel.model.RouteConfigurationsDefinition;
+
+/**
+ * A <a href="http://camel.apache.org/dsl.html">Java DSL</a> which is used for building route configuration(s).
+ */
+public abstract class EndpointRouteConfigurationBuilder extends EndpointRouteBuilder implements RouteConfigurationsBuilder {
+
+    private final AtomicBoolean initializedConfiguration = new AtomicBoolean();
+    private RouteConfigurationsDefinition routeConfigurationCollection = new RouteConfigurationsDefinition();
+
+    @Override
+    public void configure() throws Exception {
+        // noop
+    }
+
+    public abstract void configuration() throws Exception;
+
+    public RouteConfigurationsDefinition getRouteConfigurationCollection() {
+        return routeConfigurationCollection;
+    }
+
+    public void setRouteConfigurationCollection(RouteConfigurationsDefinition routeConfigurationCollection) {
+        this.routeConfigurationCollection = routeConfigurationCollection;
+    }
+
+    /**
+     * Creates a new route configuration
+     *
+     * @return the builder
+     */
+    public RouteConfigurationDefinition routeConfiguration() {
+        return routeConfiguration(null);
+    }
+
+    /**
+     * Creates a new route configuration
+     *
+     * @return the builder
+     */
+    public RouteConfigurationDefinition routeConfiguration(String id) {
+        getRouteConfigurationCollection().setCamelContext(getCamelContext());
+        RouteConfigurationDefinition answer = getRouteConfigurationCollection().routeConfiguration(id);
+        configureRouteConfiguration(answer);
+        return answer;
+    }
+
+    @Override
+    public void addRouteConfigurationsToCamelContext(CamelContext context) throws Exception {
+        setCamelContext(context);
+        routeConfigurationCollection.setCamelContext(context);
+        if (initializedConfiguration.compareAndSet(false, true)) {
+            configuration();
+        }
+        populateRoutesConfiguration();
+    }
+
+    protected void populateRoutesConfiguration() throws Exception {
+        CamelContext camelContext = getContext();
+        if (camelContext == null) {
+            throw new IllegalArgumentException("CamelContext has not been injected!");
+        }
+        getRouteConfigurationCollection().setCamelContext(camelContext);
+        camelContext.getExtension(Model.class)
+                .addRouteConfigurations(getRouteConfigurationCollection().getRouteConfigurations());
+    }
+
+}
diff --git a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/EndpointRoutesConfigurationTest.java b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/EndpointRoutesConfigurationTest.java
new file mode 100644
index 0000000..a67e5a7
--- /dev/null
+++ b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/EndpointRoutesConfigurationTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.builder.endpoint;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class EndpointRoutesConfigurationTest extends BaseEndpointDslTest {
+
+    @Test
+    public void testEndpointRoutesConfiguration() throws Exception {
+        getMockEndpoint("mock:error").expectedBodiesReceived("Hello World", "Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder[] createRouteBuilders() throws Exception {
+        return new RouteBuilder[] {
+                new EndpointRouteBuilder() {
+                    @Override
+                    public void configure() throws Exception {
+                        from(direct("start"))
+                                .throwException(new IllegalArgumentException("Foo"));
+
+                        from(direct("start2"))
+                                .throwException(new IllegalArgumentException("Foo2"));
+                    }
+                },
+                new EndpointRouteConfigurationBuilder() {
+                    @Override
+                    public void configuration() throws Exception {
+                        // global routes configuration
+                        routeConfiguration().onException(Exception.class).handled(true).to(mock("error"));
+                    }
+                }
+        };
+    }
+
+}

[camel] 11/22: CAMEL-16757: camel-endpointdsl to have route configuration builder also.

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

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

commit 10aafb19a48777c17a665d88835cd16acce87685
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 15:56:56 2021 +0200

    CAMEL-16757: camel-endpointdsl to have route configuration builder also.
---
 .../camel/model/RoutesConfigurationBuilderIdOrPatternTest.java      | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
index 963f2a3..c21ce74 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -118,7 +118,8 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
             public void configuration() throws Exception {
                 // named routes configuration
                 routeConfiguration("generalError").onException(Exception.class).handled(true).to("mock:error");
-                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0).handled(true).to("mock:io");
+                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0)
+                        .handled(true).to("mock:io");
             }
         });
         context.start();
@@ -171,7 +172,8 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
                 // has no name so its the default
                 routeConfiguration().onException(Exception.class).handled(true).to("mock:error");
                 // special for io, but only if included
-                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0).handled(true).to("mock:io");
+                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0)
+                        .handled(true).to("mock:io");
             }
         });
         context.start();

[camel] 22/22: CAMEL-16757: Added route configuration docs

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

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

commit 8ee3b0644d5686feb198ecf9a8b50fedaba1a15b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 14:32:25 2021 +0200

    CAMEL-16757: Added route configuration docs
---
 docs/user-manual/modules/ROOT/nav.adoc             |   1 +
 docs/user-manual/modules/ROOT/pages/index.adoc     |   1 +
 .../modules/ROOT/pages/route-configuration.adoc    | 282 +++++++++++++++++++++
 3 files changed, 284 insertions(+)

diff --git a/docs/user-manual/modules/ROOT/nav.adoc b/docs/user-manual/modules/ROOT/nav.adoc
index 4facacc..e877c00 100644
--- a/docs/user-manual/modules/ROOT/nav.adoc
+++ b/docs/user-manual/modules/ROOT/nav.adoc
@@ -82,6 +82,7 @@
 ** xref:lambda-route-builder.adoc[LambdaRouteBuilder]
 ** xref:route-controller.adoc[RouteController]
 ** xref:route-policy.adoc[RoutePolicy]
+** xref:route-configuration.adoc[RouteConfiguration]
 ** xref:route-template.adoc[RouteTemplate]
 ** xref:routes.adoc[Routes]
 ** xref:stream-caching.adoc[Stream caching]
diff --git a/docs/user-manual/modules/ROOT/pages/index.adoc b/docs/user-manual/modules/ROOT/pages/index.adoc
index 86bce1c..36a57b0 100644
--- a/docs/user-manual/modules/ROOT/pages/index.adoc
+++ b/docs/user-manual/modules/ROOT/pages/index.adoc
@@ -117,6 +117,7 @@ camel routes without them knowing
 * xref:lambda-route-builder.adoc[LambdaRouteBuilder]
 * xref:route-controller.adoc[RouteController]
 * xref:route-policy.adoc[RoutePolicy]
+* xref:route-configuration.adoc[RouteConfiguration]
 * xref:route-template.adoc[RouteTemplate]
 * xref:routes.adoc[Routes]
 * xref:stream-caching.adoc[Stream caching]
diff --git a/docs/user-manual/modules/ROOT/pages/route-configuration.adoc b/docs/user-manual/modules/ROOT/pages/route-configuration.adoc
new file mode 100644
index 0000000..c506540
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/route-configuration.adoc
@@ -0,0 +1,282 @@
+[[RouteConfiguration]]
+= Route Configuration
+
+Camel 3.12 introduces route configuration which is used for separating configurations
+from the routes. This can be used in situations such as configuring different error handling across a set of routes.
+In previous versions of Camel this was more cumbersome to do, as you would either have
+to copy the same configuration to a set of routes or rely on global error handling configuration.
+
+Now you can configure a number of route configurations, and then specify on each route
+which configuration to use (you can use match by ids, wildcards, and regular expression).
+
+The route configuration is supported by all DSL's, so useable by: Java, XML, Groovy, XML, Kotlin and so forth.
+
+In the route configuration you can setup common strategies for:
+
+- error handling via `onException`
+- interceptors via `intercept`, `interceptFrom`, `interceptSendTo`
+- on completions via `onCompletion`
+
+
+== Route Configuration Builder in Java DSL
+
+With Java DSL you can use `RouteConfigurationBuilder` to specify the configuration as shown below.
+The builder is similar to `RouteBuilder` so its familiar how to use.
+
+[source,java]
+----
+public class MyJavaErrorHandler extends RouteConfigurationBuilder {
+
+    @Override
+    public void configuration() throws Exception {
+        routeConfiguration("javaError")
+            .onException(Exception.class).handled(true)
+            .log("Java WARN: ${exception.message}");
+    }
+}
+----
+
+NOTE: The `RouteConfigurationBuilder` uses `configuration` as the method where the configuration is coded.
+This is on purpose to not use the `configure` method which the regular Java DSL `RouteBuilder`
+uses for coding Camel routes.
+
+In the example above, then there is only one route configuration which has been assigned the ID _javaError_.
+This ID allows us to refer to this configuration later when you want to assign which routes are using the configuration.
+
+This configuration is a basic configuration that just catches and handles all exceptions and logs a WARN message.
+
+=== Assigning route configurations to routes
+
+To use this configuration in your routes, then you can assign it with `routeConfigurationId` as shown:
+
+[source,java]
+----
+public class MyJavaRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("timer:java?period=2s")
+            // refer to the route configuration by the id to use for this route
+            .routeConfigurationId("javaError")
+            .setBody(method(MyJavaRouteBuilder.class, "randomNumber"))
+            .log("Random number ${body}")
+            .filter(simple("${body} < 30"))
+                .throwException(new IllegalArgumentException("The number is too low"));
+    }
+
+    public static int randomNumber() {
+        return new Random().nextInt(100);
+    }
+}
+----
+
+In the `routeConfigurationId` the configuration to use is specified by the ID, eg _javaError_.
+
+Multiple configurations can be assigned (separated by comma), such as:
+
+[source,java]
+----
+.routeConfigurationId("javaError,myAudit")
+----
+
+The route configurations supports matching by:
+
+- match by exact ID name. This is the sample we have seen above.
+- match by wildcard
+- match by regular expression.
+
+Wildcards is match that the text before the * is matched against the given configuration and if it also starts with the same characters its a match. For instance you can do:
+
+[source,java]
+----
+.routeConfigurationId("java*,myAudit")
+----
+
+Here we use wildcard in _java*_ which means any configuration that starts with java is a match.
+
+Match by regular expression is just like match by wildcard but using regex instead.
+
+[source,java]
+----
+.routeConfigurationId(".*error.*")
+----
+
+Here we want to match any routes that has _error_ in the name.
+
+=== Adding route configurations to CamelContext
+
+Because a `RouteConfigurationBuilder` is also a `RouteBuilder` then you add route configurations
+the same way for `RouteBuilder` such as using the API on `CamelContext`
+
+[source,java]
+----
+CamelContext context = ...
+// add the route configuration
+context.addRoutes(new MyJavaErrorHandler());
+// add the regular route
+context.addRoutes(new MyJavaRouteBuilder());
+----
+
+If you use Spring Boot, then your Camel routes and route configurations can be auto-discovered
+by the spring boot component scanning. This requires to add `@Component` annotation to the class.
+
+See the example https://github.com/apache/camel-spring-boot-examples/tree/main/routes-configuration[camel-example-spring-boot-routes-configuration].
+
+
+=== Route configuration with Endpoint DSL
+
+The xref:Endpoint-dsl.adoc[Endpoint DSL] can also be used for route configurations.
+This requires to add `camel-endpointdsl` to the classpath, and then use
+`org.apache.camel.builder.endpoint.EndpointRouteConfigurationBuilder`,
+which offers the _type safe_ DSL for Camel endpoints.
+
+
+== Default route configurations
+
+Route configurations are either given an explicit unique ID, or the configuration is _nameless_.
+A _nameless_ configuration is used as default/fallback configuration, for routes which has *NOT*
+been explicit assigned route configurations.
+
+Suppose you have one _nameless_ configuration and another named _javaError_:
+
+[source,java]
+----
+public class MyJavaErrorHandler extends RouteConfigurationBuilder {
+
+    @Override
+    public void configuration() throws Exception {
+        routeConfiguration()
+            .onException(Exception.class).handled(true)
+            .log("WARN: ${exception.message}");
+
+        routeConfiguration("retryError")
+            .onException(Exception.class).maximumRedeliveries(5);
+    }
+}
+----
+
+And the follow two routes:
+
+[source,java]
+----
+   from("file:cheese").routeId("cheese")
+        .to("kafka:cheese");
+
+   from("file:beer").routeId("beer")
+        .routeConfigurationId("retryError")
+        .to("jms:beer");
+----
+
+In the example above, then the _cheese_ route has no route configurations assigned, so the route
+will use the default configuration, which in case of an exception will log a warning.
+
+The _beer_ route on the other hand have route configuration _retryError_ assigned, and this
+configuration will in case of an exception retry again up till 5 times and then if still an error
+then fail and rollback.
+
+If you add more routes, then those routes can also be assigned the _retryError_ configuration
+if they should also retry in case of error.
+
+
+== Route Configuration in XML
+
+When using XML DSL then you can code your route configurations in XML files as shown below:
+
+[source,xml]
+----
+<routeConfiguration id="xmlError">
+    <onException>
+        <exception>java.lang.Exception</exception>
+        <handled><constant>true</constant></handled>
+        <log message="XML WARN: ${exception.message}"/>
+    </onException>
+</routeConfiguration>
+----
+
+And in the XML routes you can assign which configurations to use:
+
+[source,xml]
+----
+<route routeConfigurationId="xmlError">
+    <from uri="timer:xml?period=5s"/>
+    <log message="I am XML"/>
+    <throwException exceptionType="java.lang.Exception" message="Some kind of XML error"/>
+</route>
+----
+
+In this example the route is assigned the _xmlError_ route configuration by the exact ID.
+
+
+== Route Configuration in YAML
+
+When using YAML DSL then you can code your route configurations in YAML files as shown below:
+
+[source,yaml]
+----
+- route-configuration:
+    - id: "yamlError"
+    - on-exception:
+        handled:
+          constant: "true"
+        exception:
+          - "java.lang.Exception"
+        steps:
+          - log:
+              message: "YAML WARN ${exception.message}"
+----
+
+And in the YAML routes you can assign which configurations to use:
+
+[source,yaml]
+----
+- route:
+    # refer to the route configuration by the id to use for this route
+    route-configuration-id: "yamlError"
+    from: "timer:yaml?period=3s"
+    steps:
+      - set-body:
+          simple: "Timer fired ${header.CamelTimerCounter} times"
+      - to:
+          uri: "log:yaml"
+          parameters:
+            show-body-type: false
+            show-exchange-pattern: false
+      - throw-exception:
+          exception-type: "java.lang.IllegalArgumentException"
+          message: "Error from yaml"
+----
+
+In this example the route is assigned the _yamlError_ route configuration by the exact ID.
+
+== Logging Summary
+
+If you set `startup-summary-level=verbose` then Camel will log on for each route which route configurations they have been assigned.
+
+This option can be configured via Java API and also in `application.properties` for Camel on Spring Boot, Quarkus, and Camel standalone via `camel-main`
+
+[source,java]
+----
+camelContext.setStartupSummaryLevel(StartupSummaryLevel.Verbose);
+----
+
+And with Spring Boot:
+
+[source,properties]
+----
+camel.spring-boot.startup-summary-level = verbose
+----
+
+And in Camel Main / Quarkus:
+
+[source,properties]
+----
+camel.main.startup-summary-level = verbose
+----
+
+== See Also
+
+See the examples:
+
+- https://github.com/apache/camel-examples/tree/main/examples/routes-configuration[camel-example-routes-configuration]
+- https://github.com/apache/camel-spring-boot-examples/tree/main/routes-configuration[camel-example-spring-boot-routes-configuration]
+

[camel] 02/22: CAMEL-16757: routes configuration for intercept, on completion

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

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

commit 90824ad1050077dca392489f49bc522ee47a2951
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 07:36:50 2021 +0200

    CAMEL-16757: routes configuration for intercept, on completion
---
 .../org/apache/camel/catalog/models.properties     |   5 +-
 ...sConfiguration.json => routeConfiguration.json} |   8 +-
 .../camel/catalog/models/routeConfigurations.json  |  16 ++
 .../camel/catalog/models/routesConfigurations.json |  17 --
 .../camel/catalog/models/templateBeanFactory.json  |  17 --
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  82 ++++----
 .../camel/model/RouteConfigurationDefinition.java  |  60 ++++++
 .../model/RoutesConfigurationBuilderTest.java      | 225 ++++++++++++++++++++-
 8 files changed, 345 insertions(+), 85 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
index fd5fa5c..e0d7e06 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
@@ -145,6 +145,8 @@ rollback
 roundRobin
 route
 routeBuilder
+routeConfiguration
+routeConfigurations
 routeContext
 routeContextRef
 routeTemplate
@@ -152,8 +154,6 @@ routeTemplateContext
 routeTemplateContextRef
 routeTemplates
 routes
-routesConfiguration
-routesConfigurations
 routingSlip
 rss
 saga
@@ -189,7 +189,6 @@ syslog
 tarfile
 template
 templateBean
-templateBeanFactory
 templateParameter
 templateScript
 threadPool
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
similarity index 76%
rename from catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json
rename to catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
index c4a5307..515c123 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
@@ -1,12 +1,12 @@
 {
   "model": {
     "kind": "model",
-    "name": "routesConfiguration",
-    "title": "Routes Configuration",
-    "description": "Global configuration for Camel routes",
+    "name": "routeConfiguration",
+    "title": "Route Configuration",
+    "description": "Reusable configuration for Camel route(s).",
     "deprecated": false,
     "label": "configuration",
-    "javaType": "org.apache.camel.model.RoutesConfigurationDefinition",
+    "javaType": "org.apache.camel.model.RouteConfigurationDefinition",
     "input": false,
     "output": false
   },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json
new file mode 100644
index 0000000..d9d128f
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfigurations.json
@@ -0,0 +1,16 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "routeConfigurations",
+    "title": "Route Configurations",
+    "description": "A series of route configurations",
+    "deprecated": false,
+    "label": "configuration",
+    "javaType": "org.apache.camel.model.RouteConfigurationsDefinition",
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json
deleted file mode 100644
index 8bd9060..0000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfigurations.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "model": {
-    "kind": "model",
-    "name": "routesConfigurations",
-    "title": "Routes Configurations",
-    "description": "A series of global configuration for Camel routes",
-    "deprecated": false,
-    "label": "configuration",
-    "javaType": "org.apache.camel.model.RoutesConfigurationsDefinition",
-    "input": false,
-    "output": false
-  },
-  "properties": {
-    "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
-    "description": { "kind": "element", "displayName": "Description", "required": false, "type": "object", "javaType": "org.apache.camel.model.DescriptionDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" }
-  }
-}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json
deleted file mode 100644
index 538a54b..0000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/templateBeanFactory.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "model": {
-    "kind": "model",
-    "name": "templateBeanFactory",
-    "title": "Template Bean Factory",
-    "description": "A route template bean factory (local bean)",
-    "deprecated": false,
-    "label": "configuration",
-    "javaType": "org.apache.camel.model.RouteTemplateBeanFactoryDefinition",
-    "input": false,
-    "output": false
-  },
-  "properties": {
-    "language": { "kind": "attribute", "displayName": "Language", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "bean", "groovy", "joor", "language", "mvel", "ognl" ], "deprecated": false, "autowired": false, "secret": false, "description": "The language to use for creating the bean (such as groovy, joor)" },
-    "script": { "kind": "value", "displayName": "Script", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The script to execute that creates the bean. If the script use the prefix resource: such as resource:classpath:com\/foo\/myscript.groovy, resource:file:\/var\/myscript.groovy, then its loaded from the external resource." }
-  }
-}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 1000a99..a9e8def 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -1265,6 +1265,22 @@ To refer to a Java org.apache.camel.builder.RouteBuilder instance to use.
     </xs:annotation>
   </xs:element>
 
+  <xs:element name="routeConfiguration" type="tns:routeConfigurationDefinition">
+    <xs:annotation>
+      <xs:documentation xml:lang="en"><![CDATA[
+Reusable configuration for Camel route(s).
+      ]]></xs:documentation>
+    </xs:annotation>
+  </xs:element>
+
+  <xs:element name="routeConfigurations" type="tns:routeConfigurationsDefinition">
+    <xs:annotation>
+      <xs:documentation xml:lang="en"><![CDATA[
+A series of route configurations
+      ]]></xs:documentation>
+    </xs:annotation>
+  </xs:element>
+
   <xs:element name="routeContext" type="tns:camelRouteContextFactoryBean">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -1329,22 +1345,6 @@ A series of Camel routes
     </xs:annotation>
   </xs:element>
 
-  <xs:element name="routesConfiguration" type="tns:routesConfigurationDefinition">
-    <xs:annotation>
-      <xs:documentation xml:lang="en"><![CDATA[
-Global configuration for Camel routes
-      ]]></xs:documentation>
-    </xs:annotation>
-  </xs:element>
-
-  <xs:element name="routesConfigurations" type="tns:routesConfigurationsDefinition">
-    <xs:annotation>
-      <xs:documentation xml:lang="en"><![CDATA[
-A series of global configuration for Camel routes
-      ]]></xs:documentation>
-    </xs:annotation>
-  </xs:element>
-
   <xs:element name="routingSlip" type="tns:routingSlipDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -10627,6 +10627,29 @@ Reference to the route builder instance.
     </xs:complexContent>
   </xs:complexType>
 
+  <xs:complexType name="routeConfigurationDefinition">
+    <xs:complexContent>
+      <xs:extension base="tns:optionalIdentifiedDefinition">
+        <xs:sequence>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onException"/>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onCompletion"/>
+          <xs:choice maxOccurs="unbounded" minOccurs="0">
+            <xs:element ref="tns:intercept"/>
+            <xs:element ref="tns:interceptFrom"/>
+          </xs:choice>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptFrom"/>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptSendToEndpoint"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name="routeConfigurationsDefinition">
+    <xs:sequence>
+      <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:routeConfiguration"/>
+    </xs:sequence>
+  </xs:complexType>
+
   <xs:complexType name="routeContextRefDefinition">
     <xs:sequence/>
     <xs:attribute name="ref" type="xs:string" use="required">
@@ -10922,33 +10945,6 @@ Description of the parameter.
     </xs:complexContent>
   </xs:complexType>
 
-  <xs:complexType name="routesConfigurationDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:optionalIdentifiedDefinition">
-        <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onException"/>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onCompletion"/>
-          <xs:choice maxOccurs="unbounded" minOccurs="0">
-            <xs:element ref="tns:intercept"/>
-            <xs:element ref="tns:interceptFrom"/>
-          </xs:choice>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptFrom"/>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:interceptSendToEndpoint"/>
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-
-  <xs:complexType name="routesConfigurationsDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:optionalIdentifiedDefinition">
-        <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:routesConfiguration"/>
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-
   <xs:complexType name="routesDefinition">
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
index e4b4090..3ffb1f1 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
@@ -135,4 +135,64 @@ public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<R
         return answer;
     }
 
+    /**
+     * <a href="http://camel.apache.org/oncompletion.html">On completion</a> callback for doing custom routing when the
+     * {@link org.apache.camel.Exchange} is complete.
+     *
+     * @return the on completion builder to configure
+     */
+    public OnCompletionDefinition onCompletion() {
+        OnCompletionDefinition answer = new OnCompletionDefinition();
+        // is global scoped by default
+        answer.setRouteScoped(false);
+        onCompletions.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts every processing step.
+     *
+     * @return the builder
+     */
+    public InterceptDefinition intercept() {
+        InterceptDefinition answer = new InterceptDefinition();
+        intercepts.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts incoming messages on any inputs in this route
+     *
+     * @return the builder
+     */
+    public InterceptFromDefinition interceptFrom() {
+        InterceptFromDefinition answer = new InterceptFromDefinition();
+        interceptFroms.add(answer);
+        return answer;
+    }
+
+    /**
+     * Adds a route for an interceptor that intercepts incoming messages on the given endpoint.
+     *
+     * @param  uri endpoint uri
+     * @return     the builder
+     */
+    public InterceptFromDefinition interceptFrom(String uri) {
+        InterceptFromDefinition answer = new InterceptFromDefinition(uri);
+        interceptFroms.add(answer);
+        return answer;
+    }
+
+    /**
+     * Applies a route for an interceptor if an exchange is send to the given endpoint
+     *
+     * @param  uri endpoint uri
+     * @return     the builder
+     */
+    public InterceptSendToEndpointDefinition interceptSendToEndpoint(String uri) {
+        InterceptSendToEndpointDefinition answer = new InterceptSendToEndpointDefinition(uri);
+        interceptSendTos.add(answer);
+        return answer;
+    }
+
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
index 38e31b0..5e70d18 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderTest.java
@@ -35,7 +35,7 @@ public class RoutesConfigurationBuilderTest extends ContextTestSupport {
     }
 
     @Test
-    public void testRoutesConfiguration() throws Exception {
+    public void testRoutesConfigurationOnException() throws Exception {
         List<RoutesBuilder> routes = new ArrayList<>();
 
         routes.add(new RouteBuilder() {
@@ -84,4 +84,227 @@ public class RoutesConfigurationBuilderTest extends ContextTestSupport {
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testRoutesConfigurationOnCompletion() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        // route scoped that overrides the global scoped
+                        .onCompletion().to("mock:done2").end()
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().onCompletion().to("mock:done");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:done").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:done2").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationIntercept() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setBody(constant("A"))
+                        .setBody(constant("B"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .setBody(constant("D"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().intercept().to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("Hello World", "A", "B", "Bye World", "C", "D");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationInterceptFrom() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("seda:start")
+                        .setBody(constant("A"))
+                        .setBody(constant("B"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .setBody(constant("D"))
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().interceptFrom("direct*").to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("Bye World");
+
+        template.sendBody("seda:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationInterceptSendTo() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setBody(constant("A"))
+                        .to("mock:foo")
+                        .setBody(constant("B"))
+                        .to("mock:bar")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .setBody(constant("C"))
+                        .to("mock:foo")
+                        .setBody(constant("D"))
+                        .to("mock:bar")
+                        .to("mock:result");
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // global routes configuration
+                routeConfiguration().interceptSendToEndpoint("mock:foo").to("mock:step");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:step").expectedBodiesReceived("A", "C");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
 }

[camel] 13/22: CAMEL-16757: YAML DSL to support route configuration

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

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

commit 0a6b029340427032ab928f46eba677f65fe4c98a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 17:11:00 2021 +0200

    CAMEL-16757: YAML DSL to support route configuration
---
 .../src/main/java/org/apache/camel/impl/DefaultModel.java    | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index cc5db4c..475a975 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -120,7 +120,11 @@ public class DefaultModel implements Model {
         if (routesConfiguration == null) {
             return;
         }
-        this.routesConfigurations.add(routesConfiguration);
+        // only add if not already exists (route-loader may let Java DSL add route configuration twice
+        // because it extends RouteBuilder as base class)
+        if (!this.routesConfigurations.contains(routesConfiguration)) {
+            this.routesConfigurations.add(routesConfiguration);
+        }
     }
 
     @Override
@@ -128,7 +132,11 @@ public class DefaultModel implements Model {
         if (routesConfigurations == null || routesConfigurations.isEmpty()) {
             return;
         }
-        this.routesConfigurations.addAll(routesConfigurations);
+        // only add if not already exists (route-loader may let Java DSL add route configuration twice
+        // because it extends RouteBuilder as base class)
+        for (RouteConfigurationDefinition rc : routesConfigurations) {
+            addRouteConfiguration(rc);
+        }
     }
 
     @Override

[camel] 01/22: Merge branch 'CAMEL-16757' into CAMEL-16757b

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

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

commit 58d633ef6293df3f253643631c69cdd32ee99069
Merge: 54a9346 0ce9094
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 06:54:18 2021 +0200

    Merge branch 'CAMEL-16757' into CAMEL-16757b

 .../org/apache/camel/catalog/models.properties     |   2 +
 .../camel/catalog/models/routesConfiguration.json  |  17 +++
 .../camel/catalog/models/routesConfigurations.json |  17 +++
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  43 +++++++
 .../main/java/org/apache/camel/CamelContext.java   |   8 ++
 .../java/org/apache/camel/CamelContextAware.java   |   2 +-
 ...tAware.java => RouteConfigurationsBuilder.java} |  28 +----
 .../java/org/apache/camel/spi/RoutesLoader.java    |  19 ++-
 .../camel/impl/engine/AbstractCamelContext.java    |  17 ++-
 .../org/apache/camel/impl/DefaultCamelContext.java |  22 ++++
 .../java/org/apache/camel/impl/DefaultModel.java   |  23 ++++
 .../camel/impl/lw/LightweightCamelContext.java     |  22 ++++
 .../impl/lw/LightweightRuntimeCamelContext.java    |   6 +
 .../services/org/apache/camel/model.properties     |   3 +-
 .../resources/org/apache/camel/model/jaxb.index    |   2 +
 .../org/apache/camel/model/routeConfiguration.json |  17 +++
 .../apache/camel/model/routeConfigurations.json    |  16 +++
 .../apache/camel/model/templateBeanFactory.json    |  17 ---
 .../org/apache/camel/builder/BuilderSupport.java   |  33 ++++-
 .../org/apache/camel/builder/RouteBuilder.java     |  22 +++-
 .../camel/builder/RouteConfigurationBuilder.java   |  91 ++++++++++++++
 .../main/java/org/apache/camel/model/Model.java    |  21 ++++
 .../camel/model/RouteConfigurationDefinition.java  | 138 +++++++++++++++++++++
 ...ion.java => RouteConfigurationsDefinition.java} |  87 ++++++-------
 .../camel/model/RouteTemplatesDefinition.java      |   3 +-
 .../org/apache/camel/model/RoutesDefinition.java   |  28 ++++-
 .../apache/camel/model/rest/RestsDefinition.java   |   3 +-
 .../java/org/apache/camel/ContextTestSupport.java  |  13 +-
 .../model/RoutesConfigurationBuilderTest.java      |  87 +++++++++++++
 ...outesConfigurationMultipleRouteBuilderTest.java |  65 ++++++++++
 .../camel/model/RoutesConfigurationTest.java       |  59 +++++++++
 .../org/apache/camel/main/RoutesConfigurer.java    |  39 ++++--
 .../java/org/apache/camel/xml/in/ModelParser.java  |  47 +++++++
 .../dsl/support/RouteBuilderLoaderSupport.java     |   2 +
 .../camel/dsl/xml/io/XmlRoutesBuilderLoader.java   |  34 +++--
 .../dsl/xml/jaxb/JaxbXmlRoutesBuilderLoader.java   |  13 +-
 .../camel-yaml-dsl-deserializers/pom.xml           |   2 +
 .../dsl/yaml/deserializers/CustomResolver.java     |   3 +
 .../RouteConfigurationDefinitionDeserializer.java  |  64 ++++++++++
 .../src/generated/resources/camel-yaml-dsl.json    |  39 ++++++
 .../camel/dsl/yaml/YamlRoutesBuilderLoader.java    |  22 +++-
 .../camel/dsl/yaml/RouteConfigurationTest.groovy   | 109 ++++++++++++++++
 .../packaging/ModelXmlParserGeneratorMojo.java     |   4 +-
 43 files changed, 1172 insertions(+), 137 deletions(-)


[camel] 06/22: CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.

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

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

commit 15eb07bc4d14142df7d89c3aeafc7672592d44e1
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 2 13:09:36 2021 +0200

    CAMEL-16757: Java DSL should prepare route after configure method just like the other DSLs do. Make it possible for route configurations to be specificied per route which ones to use via id or pattern matching.
---
 .../RoutesConfigurationBuilderIdOrPatternTest.java | 155 +++++++++++++++++++--
 1 file changed, 141 insertions(+), 14 deletions(-)

diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
index 2a45ad7..963f2a3 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.model;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -27,6 +28,8 @@ import org.apache.camel.builder.RouteConfigurationBuilder;
 import org.apache.camel.support.OrderedComparator;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.fail;
+
 public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSupport {
 
     @Override
@@ -38,18 +41,18 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
     public void testRoutesConfigurationOnException() throws Exception {
         List<RoutesBuilder> routes = new ArrayList<>();
 
-        //        routes.add(new RouteBuilder() {
-        //            @Override
-        //            public void configure() throws Exception {
-        //                from("direct:start")
-        //                        .throwException(new IllegalArgumentException("Foo"));
-        //            }
-        //        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .throwException(new IllegalArgumentException("Foo"));
+            }
+        });
         routes.add(new RouteBuilder() {
             @Override
             public void configure() throws Exception {
                 from("direct:start2")
-                        .routeConfiguration("handle*")
+                        .routeConfiguration("handleError")
                         .throwException(new IllegalArgumentException("Foo2"));
             }
         });
@@ -79,15 +82,139 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
 
         getMockEndpoint("mock:error").expectedBodiesReceived("Bye World");
 
-        //        try {
-        //            template.sendBody("direct:start", "Hello World");
-        //            fail("Should throw exception");
-        //        } catch (Exception e) {
-        // expected
-        //        }
+        try {
+            template.sendBody("direct:start", "Hello World");
+            fail("Should throw exception");
+        } catch (Exception e) {
+            // expected
+        }
         template.sendBody("direct:start2", "Bye World");
 
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testRoutesConfigurationOnExceptionPattern() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .routeConfiguration("general*")
+                        .throwException(new IllegalArgumentException("Foo"));
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .routeConfiguration("io*")
+                        .throwException(new IOException("Foo2"));
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // named routes configuration
+                routeConfiguration("generalError").onException(Exception.class).handled(true).to("mock:error");
+                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0).handled(true).to("mock:io");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:error").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:io").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testRoutesConfigurationOnExceptionDefault() throws Exception {
+        List<RoutesBuilder> routes = new ArrayList<>();
+
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").routeId("foo")
+                        .throwException(new IllegalArgumentException("Foo"));
+            }
+        });
+        routes.add(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2").routeId("foo2")
+                        .throwException(new IOException("Foo2"));
+            }
+        });
+        routes.add(new RouteConfigurationBuilder() {
+            @Override
+            public void configuration() throws Exception {
+                // has no name so its the default
+                routeConfiguration().onException(Exception.class).handled(true).to("mock:error");
+                // special for io, but only if included
+                routeConfiguration("ioError").onException(IOException.class).maximumRedeliveries(3).redeliveryDelay(0).handled(true).to("mock:io");
+            }
+        });
+        context.start();
+
+        // sort routes according to ordered
+        routes.sort(OrderedComparator.get());
+
+        // first add the routes configurations as they are globally for all routes
+        for (RoutesBuilder builder : routes) {
+            if (builder instanceof RouteConfigurationsBuilder) {
+                RouteConfigurationsBuilder rcb = (RouteConfigurationsBuilder) builder;
+                context.addRoutesConfigurations(rcb);
+            }
+        }
+        // then add the routes
+        for (RoutesBuilder builder : routes) {
+            context.addRoutes(builder);
+        }
+
+        getMockEndpoint("mock:error").expectedBodiesReceived("Hello World", "Bye World");
+        getMockEndpoint("mock:io").expectedMessageCount(0);
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+        assertMockEndpointsSatisfied();
+
+        context.removeRoute("foo2");
+
+        // now re-configure route2 to use ioError route configuration
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2").routeId("foo2")
+                        .routeConfiguration("ioError")
+                        .throwException(new IOException("Foo2"));
+            }
+        });
+        // try again
+        resetMocks();
+        getMockEndpoint("mock:error").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:io").expectedBodiesReceived("Bye World");
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+        assertMockEndpointsSatisfied();
+    }
+
 }