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/07/06 10:22:57 UTC

[camel] 01/03: CAMEL-16757: camel-core - Global error handling, interceptor in all DSL

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

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

commit f4d48681aa2ed2842b4d22eb11637db4acd93e49
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jul 6 10:46:54 2021 +0200

    CAMEL-16757: camel-core - Global error handling, interceptor in all DSL
---
 .../org/apache/camel/catalog/models.properties     |   1 +
 .../camel/catalog/models/routesConfiguration.json  |  17 +++
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  25 ++++
 .../org/apache/camel/impl/DefaultCamelContext.java |  22 ++++
 .../java/org/apache/camel/impl/DefaultModel.java   |  23 ++++
 .../camel/impl/lw/LightweightCamelContext.java     |  16 +++
 .../services/org/apache/camel/model.properties     |   1 +
 .../resources/org/apache/camel/model/jaxb.index    |   1 +
 .../apache/camel/model/routesConfiguration.json    |  17 +++
 .../org/apache/camel/builder/RouteBuilder.java     |  26 +++-
 .../main/java/org/apache/camel/model/Model.java    |   7 ++
 .../camel/model/RoutesConfigurationDefinition.java | 138 +++++++++++++++++++++
 .../org/apache/camel/model/RoutesDefinition.java   |  24 +++-
 ...outesConfigurationMultipleRouteBuilderTest.java |  65 ++++++++++
 .../camel/model/RoutesConfigurationTest.java       |  51 ++++++++
 .../java/org/apache/camel/xml/in/ModelParser.java  |  14 +++
 .../dsl/yaml/deserializers/ModelDeserializers.java |  70 +++++++++++
 .../deserializers/ModelDeserializersResolver.java  |   2 +
 .../src/generated/resources/camel-yaml-dsl.json    |  35 ++++++
 19 files changed, 551 insertions(+), 4 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 d0d5f2f..400daee 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
@@ -152,6 +152,7 @@ routeTemplateContext
 routeTemplateContextRef
 routeTemplates
 routes
+routesConfiguration
 routingSlip
 rss
 saga
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/routesConfiguration.json
new file mode 100644
index 0000000..c4a5307
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routesConfiguration.json
@@ -0,0 +1,17 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "routesConfiguration",
+    "title": "Routes Configuration",
+    "description": "Global configuration for Camel routes",
+    "deprecated": false,
+    "label": "configuration",
+    "javaType": "org.apache.camel.model.RoutesConfigurationDefinition",
+    "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/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index b4767ff..d700d96 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
@@ -1329,6 +1329,14 @@ 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="routingSlip" type="tns:routingSlipDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -10837,6 +10845,23 @@ 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="routesDefinition">
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 8544303..896a753 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -58,6 +58,7 @@ import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.RouteTemplatesDefinition;
+import org.apache.camel.model.RoutesConfigurationDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.language.ExpressionDefinition;
@@ -287,6 +288,27 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
     }
 
     @Override
+    public void addRoutesConfiguration(RoutesConfigurationDefinition routesConfiguration) {
+        if (model == null && isLightweight()) {
+            throw new IllegalStateException("Access to model not supported in lightweight mode");
+        }
+        model.addRoutesConfiguration(routesConfiguration);
+    }
+
+    @Override
+    public void addRoutesConfigurations(List<RoutesConfigurationDefinition> routesConfigurations) {
+        if (model == null && isLightweight()) {
+            throw new IllegalStateException("Access to model not supported in lightweight mode");
+        }
+        model.addRoutesConfigurations(routesConfigurations);
+    }
+
+    @Override
+    public List<RoutesConfigurationDefinition> getRoutesConfigurationDefinition() {
+        return model.getRoutesConfigurationDefinition();
+    }
+
+    @Override
     public List<RouteDefinition> getRouteDefinitions() {
         if (model == null && isLightweight()) {
             throw new IllegalStateException("Access to model not supported in lightweight mode");
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 5802e61..e70d4ea 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
@@ -52,6 +52,7 @@ import org.apache.camel.model.RouteFilters;
 import org.apache.camel.model.RouteTemplateBeanDefinition;
 import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.RouteTemplateParameterDefinition;
+import org.apache.camel.model.RoutesConfigurationDefinition;
 import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
 import org.apache.camel.model.transformer.TransformerDefinition;
@@ -79,6 +80,7 @@ public class DefaultModel implements Model {
 
     private ModelReifierFactory modelReifierFactory = new DefaultModelReifierFactory();
     private final List<ModelLifecycleStrategy> modelLifecycleStrategies = new ArrayList<>();
+    private final List<RoutesConfigurationDefinition> routesConfigurations = new ArrayList<>();
     private final List<RouteDefinition> routeDefinitions = new ArrayList<>();
     private final List<RouteTemplateDefinition> routeTemplateDefinitions = new ArrayList<>();
     private final List<RestDefinition> restDefinitions = new ArrayList<>();
@@ -114,6 +116,27 @@ public class DefaultModel implements Model {
     }
 
     @Override
+    public void addRoutesConfiguration(RoutesConfigurationDefinition routesConfiguration) {
+        if (routesConfiguration == null) {
+            return;
+        }
+        this.routesConfigurations.add(routesConfiguration);
+    }
+
+    @Override
+    public void addRoutesConfigurations(List<RoutesConfigurationDefinition> routesConfigurations) {
+        if (routesConfigurations == null || routesConfigurations.isEmpty()) {
+            return;
+        }
+        this.routesConfigurations.addAll(routesConfigurations);
+    }
+
+    @Override
+    public List<RoutesConfigurationDefinition> getRoutesConfigurationDefinition() {
+        return routesConfigurations;
+    }
+
+    @Override
     public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
         if (routeDefinitions == null || routeDefinitions.isEmpty()) {
             return;
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 14cd80c..bf5b72e 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -63,6 +63,7 @@ import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.Resilience4jConfigurationDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateDefinition;
+import org.apache.camel.model.RoutesConfigurationDefinition;
 import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
 import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.model.rest.RestDefinition;
@@ -1687,6 +1688,21 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public void addRoutesConfiguration(RoutesConfigurationDefinition routesConfiguration) {
+        getModelCamelContext().addRoutesConfiguration(routesConfiguration);
+    }
+
+    @Override
+    public void addRoutesConfigurations(List<RoutesConfigurationDefinition> routesConfigurations) {
+        getModelCamelContext().addRoutesConfigurations(routesConfigurations);
+    }
+
+    @Override
+    public List<RoutesConfigurationDefinition> getRoutesConfigurationDefinition() {
+        return getModelCamelContext().getRoutesConfigurationDefinition();
+    }
+
+    @Override
     public List<RouteDefinition> getRouteDefinitions() {
         return getModelCamelContext().getRouteDefinitions();
     }
diff --git a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
index 2b03f53..0aa905d 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
+++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
@@ -142,6 +142,7 @@ routeTemplate
 routeTemplateContextRef
 routeTemplates
 routes
+routesConfiguration
 routingSlip
 rss
 saga
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
index c134380..c211311 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
@@ -71,6 +71,7 @@ RouteTemplateDefinition
 RouteTemplateParameterDefinition
 RouteTemplateScriptDefinition
 RouteTemplatesDefinition
+RoutesConfigurationDefinition
 RoutesDefinition
 RoutingSlipDefinition
 SagaCompletionMode
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routesConfiguration.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routesConfiguration.json
new file mode 100644
index 0000000..c4a5307
--- /dev/null
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routesConfiguration.json
@@ -0,0 +1,17 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "routesConfiguration",
+    "title": "Routes Configuration",
+    "description": "Global configuration for Camel routes",
+    "deprecated": false,
+    "label": "configuration",
+    "javaType": "org.apache.camel.model.RoutesConfigurationDefinition",
+    "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/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 5f9c6db..b04ad8a 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
@@ -34,11 +34,13 @@ import org.apache.camel.model.InterceptDefinition;
 import org.apache.camel.model.InterceptFromDefinition;
 import org.apache.camel.model.InterceptSendToEndpointDefinition;
 import org.apache.camel.model.Model;
+import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.model.OnCompletionDefinition;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.RouteTemplatesDefinition;
+import org.apache.camel.model.RoutesConfigurationDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
 import org.apache.camel.model.rest.RestDefinition;
@@ -201,6 +203,18 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
     }
 
     /**
+     * Global routes configuration
+     *
+     * @return the builder
+     */
+    public RoutesConfigurationDefinition routesConfiguration() {
+        RoutesConfigurationDefinition answer = new RoutesConfigurationDefinition();
+        getContext().adapt(ModelCamelContext.class).addRoutesConfiguration(answer);
+        configureRoutesConfiguration(answer);
+        return answer;
+    }
+
+    /**
      * Creates a new route template
      *
      * @return the builder
@@ -462,8 +476,8 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
         configureRoutes(context);
         configureRests(context);
 
-        // but populate rests before routes, as we want to turn rests into
-        // routes
+        // but populate rests before routes, as we want to turn rests into routes
+        populateRoutesConfiguration();
         populateRests();
         populateTransformers();
         populateValidators();
@@ -551,6 +565,10 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
         }
     }
 
+    protected void populateRoutesConfiguration() throws Exception {
+        // noop
+    }
+
     protected void populateRouteTemplates() throws Exception {
         CamelContext camelContext = getContext();
         if (camelContext == null) {
@@ -673,4 +691,8 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild
     protected void configureRouteTemplate(RouteTemplateDefinition routeTemplate) {
         // noop
     }
+
+    protected void configureRoutesConfiguration(RoutesConfigurationDefinition routesConfiguration) {
+        // noop
+    }
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
index 041881b..10ff07e 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
@@ -49,6 +49,13 @@ public interface Model {
      */
     List<ModelLifecycleStrategy> getModelLifecycleStrategies();
 
+    // TODO: better names
+    void addRoutesConfigurations(List<RoutesConfigurationDefinition> routesConfigurations);
+
+    void addRoutesConfiguration(RoutesConfigurationDefinition routesConfiguration);
+
+    List<RoutesConfigurationDefinition> getRoutesConfigurationDefinition();
+
     /**
      * Returns a list of the current route definitions
      *
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesConfigurationDefinition.java
new file mode 100644
index 0000000..56b7372
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesConfigurationDefinition.java
@@ -0,0 +1,138 @@
+/*
+ * 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.Arrays;
+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.XmlRootElement;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Global configuration for Camel routes
+ */
+@Metadata(label = "configuration")
+@XmlRootElement(name = "routesConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RoutesConfigurationDefinition extends OptionalIdentifiedDefinition<RoutesDefinition> {
+
+    // TODO: Model for ErrorHandler
+
+    @XmlElementRef
+    private List<OnExceptionDefinition> onExceptions = new ArrayList<>();
+    @XmlElementRef
+    private List<OnCompletionDefinition> onCompletions = new ArrayList<>();
+    @XmlElementRef
+    private List<InterceptDefinition> intercepts = new ArrayList<>();
+    @XmlElementRef
+    private List<InterceptFromDefinition> interceptFroms = new ArrayList<>();
+    @XmlElementRef
+    private List<InterceptSendToEndpointDefinition> interceptSendTos = new ArrayList<>();
+
+    public RoutesConfigurationDefinition() {
+    }
+
+    @Override
+    public String toString() {
+        return "RoutesConfiguration: " + getId();
+    }
+
+    @Override
+    public String getShortName() {
+        return "routesConfiguration";
+    }
+
+    @Override
+    public String getLabel() {
+        return "RoutesConfiguration " + getId();
+    }
+
+    public List<OnExceptionDefinition> getOnExceptions() {
+        return onExceptions;
+    }
+
+    public void setOnExceptions(List<OnExceptionDefinition> onExceptions) {
+        this.onExceptions = onExceptions;
+    }
+
+    public List<OnCompletionDefinition> getOnCompletions() {
+        return onCompletions;
+    }
+
+    public void setOnCompletions(List<OnCompletionDefinition> onCompletions) {
+        this.onCompletions = onCompletions;
+    }
+
+    public List<InterceptDefinition> getIntercepts() {
+        return intercepts;
+    }
+
+    public void setIntercepts(List<InterceptDefinition> intercepts) {
+        this.intercepts = intercepts;
+    }
+
+    public List<InterceptFromDefinition> getInterceptFroms() {
+        return interceptFroms;
+    }
+
+    public void setInterceptFroms(List<InterceptFromDefinition> interceptFroms) {
+        this.interceptFroms = interceptFroms;
+    }
+
+    public List<InterceptSendToEndpointDefinition> getInterceptSendTos() {
+        return interceptSendTos;
+    }
+
+    public void setInterceptSendTos(List<InterceptSendToEndpointDefinition> interceptSendTos) {
+        this.interceptSendTos = interceptSendTos;
+    }
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+    /**
+     * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a> for catching certain exceptions and
+     * handling them.
+     *
+     * @param  exceptionType the exception to catch
+     * @return               the exception builder to configure
+     */
+    public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) {
+        OnExceptionDefinition answer = new OnExceptionDefinition(exceptionType);
+        onExceptions.add(answer);
+        return answer;
+    }
+
+    /**
+     * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a> for catching certain exceptions and
+     * handling them.
+     *
+     * @param  exceptions list of exceptions to catch
+     * @return            the exception builder to configure
+     */
+    public OnExceptionDefinition onException(Class<? extends Throwable>... exceptions) {
+        OnExceptionDefinition answer = new OnExceptionDefinition(Arrays.asList(exceptions));
+        onExceptions.add(answer);
+        return answer;
+    }
+
+}
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 b62df39..6f18e08 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
@@ -41,6 +41,7 @@ import org.apache.camel.spi.Metadata;
 public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinition> implements RouteContainer {
     @XmlElementRef
     private List<RouteDefinition> routes = new ArrayList<>();
+    // TODO: Use RoutesConfigurationDefinition instead
     @XmlTransient
     private List<InterceptDefinition> intercepts = new ArrayList<>();
     @XmlTransient
@@ -202,9 +203,28 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit
             route.setErrorHandlerFactoryIfNull(handler);
         }
 
+        // merge global and route scoped together
+        List<OnExceptionDefinition> oe = new ArrayList<>(onExceptions);
+        List<InterceptDefinition> icp = new ArrayList<>(intercepts);
+        List<InterceptFromDefinition> ifrom = new ArrayList<>(interceptFroms);
+        List<InterceptSendToEndpointDefinition> ito = new ArrayList<>(interceptSendTos);
+        List<OnCompletionDefinition> oc = new ArrayList<>(onCompletions);
+        if (getCamelContext() != null) {
+            List<RoutesConfigurationDefinition> globalConfigurations
+                    = getCamelContext().adapt(ModelCamelContext.class).getRoutesConfigurationDefinition();
+            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());
+                });
+            }
+        }
+
         // must prepare the route before we can add it to the routes list
-        RouteDefinitionHelper.prepareRoute(getCamelContext(), route, getOnExceptions(), getIntercepts(), getInterceptFroms(),
-                getInterceptSendTos(), getOnCompletions());
+        RouteDefinitionHelper.prepareRoute(getCamelContext(), route, oe, icp, ifrom, ito, oc);
 
         getRoutes().add(route);
         // mark this route as prepared
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationMultipleRouteBuilderTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationMultipleRouteBuilderTest.java
new file mode 100644
index 0000000..875db74
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationMultipleRouteBuilderTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class RoutesConfigurationMultipleRouteBuilderTest extends ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testRoutesConfiguration() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // global routes configuration
+                routesConfiguration().onException(Exception.class).handled(true).to("mock:error");
+            }
+        });
+
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .throwException(new IllegalArgumentException("Foo"));
+            }
+        });
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start2")
+                        .throwException(new IllegalArgumentException("Foo2"));
+            }
+        });
+
+        context.start();
+
+        getMockEndpoint("mock:error").expectedBodiesReceived("Hello World", "Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start2", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationTest.java
new file mode 100644
index 0000000..8977c55
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.model;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class RoutesConfigurationTest extends ContextTestSupport {
+
+    @Test
+    public void testRoutesConfiguration() 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 createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // global routes configuration
+                routesConfiguration().onException(Exception.class).handled(true).to("mock:error");
+
+                from("direct:start")
+                        .throwException(new IllegalArgumentException("Foo"));
+
+                from("direct:start2")
+                        .throwException(new IllegalArgumentException("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 d444e5e..72895e0 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
@@ -1112,6 +1112,20 @@ public class ModelParser extends BaseParser {
             return optionalIdentifiedDefinitionElementHandler().accept(def, key);
         }, noValueHandler());
     }
+    protected RoutesConfigurationDefinition doParseRoutesConfigurationDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RoutesConfigurationDefinition(),
+            optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "interceptFrom": doAdd(doParseInterceptFromDefinition(), def.getIntercepts(), def::setIntercepts); 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;
+                case "onException": doAdd(doParseOnExceptionDefinition(), def.getOnExceptions(), def::setOnExceptions); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
     public Optional<RoutesDefinition> parseRoutesDefinition()
             throws IOException, XmlPullParserException {
         String tag = getNextTag("routes", "route");
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 56ecd7b..666b14d 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -73,6 +73,7 @@ import org.apache.camel.model.RouteContextRefDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateParameterDefinition;
 import org.apache.camel.model.RouteTemplateScriptDefinition;
+import org.apache.camel.model.RoutesConfigurationDefinition;
 import org.apache.camel.model.RoutingSlipDefinition;
 import org.apache.camel.model.SagaActionUriDefinition;
 import org.apache.camel.model.SagaDefinition;
@@ -12880,6 +12881,75 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
     }
 
     @YamlType(
+            types = org.apache.camel.model.RoutesConfigurationDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            nodes = "routes-configuration",
+            properties = {
+                    @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", type = "array:org.apache.camel.model.InterceptSendToEndpointDefinition"),
+                    @YamlProperty(name = "on-completion", type = "array:org.apache.camel.model.OnCompletionDefinition"),
+                    @YamlProperty(name = "on-exception", type = "array:org.apache.camel.model.OnExceptionDefinition")
+            }
+    )
+    public static class RoutesConfigurationDefinitionDeserializer extends YamlDeserializerBase<RoutesConfigurationDefinition> {
+        public RoutesConfigurationDefinitionDeserializer() {
+            super(RoutesConfigurationDefinition.class);
+        }
+
+        @Override
+        protected RoutesConfigurationDefinition newInstance() {
+            return new RoutesConfigurationDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(RoutesConfigurationDefinition target, String propertyKey,
+                String propertyName, Node node) {
+            switch(propertyKey) {
+                case "intercept-from": {
+                    java.util.List<org.apache.camel.model.InterceptFromDefinition> val = asFlatList(node, org.apache.camel.model.InterceptFromDefinition.class);
+                    target.setInterceptFroms(val);
+                    break;
+                }
+                case "intercept-send-to-endpoint": {
+                    java.util.List<org.apache.camel.model.InterceptSendToEndpointDefinition> val = asFlatList(node, org.apache.camel.model.InterceptSendToEndpointDefinition.class);
+                    target.setInterceptSendTos(val);
+                    break;
+                }
+                case "intercept": {
+                    java.util.List<org.apache.camel.model.InterceptDefinition> val = asFlatList(node, org.apache.camel.model.InterceptDefinition.class);
+                    target.setIntercepts(val);
+                    break;
+                }
+                case "on-completion": {
+                    java.util.List<org.apache.camel.model.OnCompletionDefinition> val = asFlatList(node, org.apache.camel.model.OnCompletionDefinition.class);
+                    target.setOnCompletions(val);
+                    break;
+                }
+                case "on-exception": {
+                    java.util.List<org.apache.camel.model.OnExceptionDefinition> val = asFlatList(node, org.apache.camel.model.OnExceptionDefinition.class);
+                    target.setOnExceptions(val);
+                    break;
+                }
+                case "id": {
+                    String val = asText(node);
+                    target.setId(val);
+                    break;
+                }
+                case "description": {
+                    org.apache.camel.model.DescriptionDefinition val = asType(node, org.apache.camel.model.DescriptionDefinition.class);
+                    target.setDescription(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    @YamlType(
             inline = true,
             types = org.apache.camel.model.RoutingSlipDefinition.class,
             order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index 965e470..f525761 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -304,6 +304,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "org.apache.camel.model.RouteTemplateParameterDefinition": return new ModelDeserializers.RouteTemplateParameterDefinitionDeserializer();
             case "template-script": return new ModelDeserializers.RouteTemplateScriptDefinitionDeserializer();
             case "org.apache.camel.model.RouteTemplateScriptDefinition": return new ModelDeserializers.RouteTemplateScriptDefinitionDeserializer();
+            case "routes-configuration": return new ModelDeserializers.RoutesConfigurationDefinitionDeserializer();
+            case "org.apache.camel.model.RoutesConfigurationDefinition": return new ModelDeserializers.RoutesConfigurationDefinitionDeserializer();
             case "routing-slip": return new ModelDeserializers.RoutingSlipDefinitionDeserializer();
             case "org.apache.camel.model.RoutingSlipDefinition": return new ModelDeserializers.RoutingSlipDefinitionDeserializer();
             case "rss": return new ModelDeserializers.RssDataFormatDeserializer();
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 39f7343..031f947 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
@@ -2150,6 +2150,41 @@
           }
         } ]
       },
+      "org.apache.camel.model.RoutesConfigurationDefinition" : {
+        "type" : "object",
+        "properties" : {
+          "intercept" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.InterceptDefinition"
+            }
+          },
+          "intercept-from" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.InterceptFromDefinition"
+            }
+          },
+          "intercept-send-to-endpoint" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.InterceptSendToEndpointDefinition"
+            }
+          },
+          "on-completion" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.OnCompletionDefinition"
+            }
+          },
+          "on-exception" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.OnExceptionDefinition"
+            }
+          }
+        }
+      },
       "org.apache.camel.model.RoutingSlipDefinition" : {
         "oneOf" : [ {
           "type" : "string"