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 2024/03/18 05:13:03 UTC

(camel) branch camel-4.4.x updated: CAMEL-20568: Set error handler on route level in YAML DSL (#13489) (#13501)

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

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


The following commit(s) were added to refs/heads/camel-4.4.x by this push:
     new ae2a191cc44 CAMEL-20568: Set error handler on route level in YAML DSL (#13489) (#13501)
ae2a191cc44 is described below

commit ae2a191cc44264ffd245d5789b0ff4e5a790044f
Author: Christoph Deppisch <cd...@redhat.com>
AuthorDate: Mon Mar 18 06:12:57 2024 +0100

    CAMEL-20568: Set error handler on route level in YAML DSL (#13489) (#13501)
    
    Allow to set error handler on route level in Camel YAML DSL
    
    (cherry picked from commit c0228d4f12c6a34859e69337bd0017a855fe195c)
---
 .../dsl/yaml/deserializers/CustomResolver.java     |  2 +
 .../ErrorHandlerBuilderDeserializer.java           | 33 ++------
 ...rializer.java => ErrorHandlerDeserializer.java} | 50 +-----------
 .../deserializers/RouteDefinitionDeserializer.java |  9 +++
 .../generated/resources/schema/camelYamlDsl.json   | 89 +++++++++++++++++++++-
 .../org/apache/camel/dsl/yaml/RoutesTest.groovy    | 88 ++++++++++++++++++++-
 6 files changed, 197 insertions(+), 74 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/CustomResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/CustomResolver.java
index c0ccc80eac7..ab9415ece5d 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/CustomResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/CustomResolver.java
@@ -87,6 +87,8 @@ public class CustomResolver implements YamlDeserializerResolver {
             case "beans":
                 return beansDeserializer;
             case "errorHandler":
+                return new ErrorHandlerDeserializer();
+            case "org.apache.camel.ErrorHandlerFactory":
                 return new ErrorHandlerBuilderDeserializer();
             case "org.apache.camel.model.ProcessorDefinition":
                 return new ProcessorDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java
index 545fc9e300e..daf18aa1d3a 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.dsl.yaml.deserializers;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerResolver;
@@ -27,7 +26,6 @@ import org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition;
 import org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition;
 import org.apache.camel.model.errorhandler.NoErrorHandlerDefinition;
 import org.apache.camel.model.errorhandler.RefErrorHandlerDefinition;
-import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.YamlIn;
 import org.apache.camel.spi.annotations.YamlProperty;
 import org.apache.camel.spi.annotations.YamlType;
@@ -36,16 +34,11 @@ import org.snakeyaml.engine.v2.nodes.MappingNode;
 import org.snakeyaml.engine.v2.nodes.Node;
 import org.snakeyaml.engine.v2.nodes.NodeTuple;
 
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asMappingNode;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asText;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asType;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.getDeserializationContext;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.setDeserializationContext;
+import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.*;
 
 @YamlIn
 @YamlType(
-          inline = false,
-          nodes = { "error-handler", "errorHandler" },
+          types = ErrorHandlerFactory.class,
           order = YamlDeserializerResolver.ORDER_DEFAULT,
           properties = {
                   @YamlProperty(name = "deadLetterChannel",
@@ -69,15 +62,6 @@ import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.setDeseri
           })
 public class ErrorHandlerBuilderDeserializer implements ConstructNode {
 
-    private static CamelContextCustomizer customizer(ErrorHandlerFactory builder) {
-        return new CamelContextCustomizer() {
-            @Override
-            public void configure(CamelContext camelContext) {
-                camelContext.getCamelContextExtension().setErrorHandlerFactory(builder);
-            }
-        };
-    }
-
     @Override
     public Object construct(Node node) {
         final MappingNode bn = asMappingNode(node);
@@ -92,17 +76,16 @@ public class ErrorHandlerBuilderDeserializer implements ConstructNode {
             key = org.apache.camel.util.StringHelper.dashToCamelCase(key);
             switch (key) {
                 case "deadLetterChannel":
-                    return customizer(asType(val, DeadLetterChannelDefinition.class));
+                    return asType(val, DeadLetterChannelDefinition.class);
                 case "defaultErrorHandler":
-                    return customizer(asType(val, DefaultErrorHandlerDefinition.class));
+                    return asType(val, DefaultErrorHandlerDefinition.class);
                 case "jtaTransactionErrorHandler":
-                    return customizer(asType(val, JtaTransactionErrorHandlerDefinition.class));
+                case "springTransactionErrorHandler":
+                    return asType(val, JtaTransactionErrorHandlerDefinition.class);
                 case "noErrorHandler":
-                    return customizer(asType(val, NoErrorHandlerDefinition.class));
+                    return asType(val, NoErrorHandlerDefinition.class);
                 case "refErrorHandler":
-                    return customizer(asType(val, RefErrorHandlerDefinition.class));
-                case "springTransactionErrorHandler":
-                    return customizer(asType(val, JtaTransactionErrorHandlerDefinition.class));
+                    return asType(val, RefErrorHandlerDefinition.class);
                 default:
                     throw new UnsupportedFieldException(val, key);
             }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerDeserializer.java
similarity index 55%
copy from dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java
copy to dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerDeserializer.java
index 545fc9e300e..d9a89cd5f5f 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerBuilderDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/ErrorHandlerDeserializer.java
@@ -18,29 +18,13 @@ package org.apache.camel.dsl.yaml.deserializers;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ErrorHandlerFactory;
-import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerResolver;
-import org.apache.camel.dsl.yaml.common.exception.UnsupportedFieldException;
-import org.apache.camel.dsl.yaml.common.exception.YamlDeserializationException;
-import org.apache.camel.model.errorhandler.DeadLetterChannelDefinition;
-import org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition;
-import org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition;
-import org.apache.camel.model.errorhandler.NoErrorHandlerDefinition;
-import org.apache.camel.model.errorhandler.RefErrorHandlerDefinition;
 import org.apache.camel.spi.CamelContextCustomizer;
 import org.apache.camel.spi.annotations.YamlIn;
 import org.apache.camel.spi.annotations.YamlProperty;
 import org.apache.camel.spi.annotations.YamlType;
 import org.snakeyaml.engine.v2.api.ConstructNode;
-import org.snakeyaml.engine.v2.nodes.MappingNode;
 import org.snakeyaml.engine.v2.nodes.Node;
-import org.snakeyaml.engine.v2.nodes.NodeTuple;
-
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asMappingNode;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asText;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.asType;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.getDeserializationContext;
-import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.setDeserializationContext;
 
 @YamlIn
 @YamlType(
@@ -67,7 +51,9 @@ import static org.apache.camel.dsl.yaml.common.YamlDeserializerSupport.setDeseri
                                 type = "object:org.apache.camel.model.errorhandler.SpringTransactionErrorHandlerDefinition",
                                 oneOf = "errorHandler"),
           })
-public class ErrorHandlerBuilderDeserializer implements ConstructNode {
+public class ErrorHandlerDeserializer implements ConstructNode {
+
+    private final ErrorHandlerBuilderDeserializer delegate = new ErrorHandlerBuilderDeserializer();
 
     private static CamelContextCustomizer customizer(ErrorHandlerFactory builder) {
         return new CamelContextCustomizer() {
@@ -80,34 +66,6 @@ public class ErrorHandlerBuilderDeserializer implements ConstructNode {
 
     @Override
     public Object construct(Node node) {
-        final MappingNode bn = asMappingNode(node);
-        final YamlDeserializationContext dc = getDeserializationContext(node);
-
-        for (NodeTuple tuple : bn.getValue()) {
-            String key = asText(tuple.getKeyNode());
-            Node val = tuple.getValueNode();
-
-            setDeserializationContext(val, dc);
-
-            key = org.apache.camel.util.StringHelper.dashToCamelCase(key);
-            switch (key) {
-                case "deadLetterChannel":
-                    return customizer(asType(val, DeadLetterChannelDefinition.class));
-                case "defaultErrorHandler":
-                    return customizer(asType(val, DefaultErrorHandlerDefinition.class));
-                case "jtaTransactionErrorHandler":
-                    return customizer(asType(val, JtaTransactionErrorHandlerDefinition.class));
-                case "noErrorHandler":
-                    return customizer(asType(val, NoErrorHandlerDefinition.class));
-                case "refErrorHandler":
-                    return customizer(asType(val, RefErrorHandlerDefinition.class));
-                case "springTransactionErrorHandler":
-                    return customizer(asType(val, JtaTransactionErrorHandlerDefinition.class));
-                default:
-                    throw new UnsupportedFieldException(val, key);
-            }
-        }
-
-        throw new YamlDeserializationException(node, "Unable to determine the error handler type for the node");
+        return customizer((ErrorHandlerFactory) delegate.construct(node));
     }
 }
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 eed0d6a2e08..413065acf39 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
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.dsl.yaml.deserializers;
 
+import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerBase;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerResolver;
@@ -50,6 +51,8 @@ import org.snakeyaml.engine.v2.nodes.NodeTuple;
                   @YamlProperty(name = "messageHistory", type = "boolean"),
                   @YamlProperty(name = "logMask", type = "boolean"),
                   @YamlProperty(name = "trace", type = "boolean"),
+                  @YamlProperty(name = "errorHandlerRef", type = "string"),
+                  @YamlProperty(name = "errorHandler", type = "object:org.apache.camel.ErrorHandlerFactory"),
                   @YamlProperty(name = "shutdownRoute", type = "enum:Default,Defer",
                                 defaultValue = "Default",
                                 description = "To control how to shut down the route."),
@@ -128,6 +131,12 @@ public class RouteDefinitionDeserializer extends YamlDeserializerBase<RouteDefin
                 case "trace":
                     target.setTrace(asText(val));
                     break;
+                case "errorHandlerRef":
+                    target.setErrorHandlerRef(asText(val));
+                    break;
+                case "errorHandler":
+                    target.setErrorHandlerFactory(asType(val, ErrorHandlerFactory.class));
+                    break;
                 case "inputType":
                     target.setInputType(asType(val, InputTypeDefinition.class));
                     break;
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index 126d3f1404f..be1a20b7e4a 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -207,6 +207,85 @@
           }
         }
       },
+      "org.apache.camel.ErrorHandlerFactory" : {
+        "type" : "object",
+        "additionalProperties" : false,
+        "anyOf" : [ {
+          "oneOf" : [ {
+            "type" : "object",
+            "required" : [ "deadLetterChannel" ],
+            "properties" : {
+              "deadLetterChannel" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.DeadLetterChannelDefinition"
+              }
+            }
+          }, {
+            "not" : {
+              "anyOf" : [ {
+                "required" : [ "deadLetterChannel" ]
+              }, {
+                "required" : [ "defaultErrorHandler" ]
+              }, {
+                "required" : [ "jtaTransactionErrorHandler" ]
+              }, {
+                "required" : [ "noErrorHandler" ]
+              }, {
+                "required" : [ "refErrorHandler" ]
+              }, {
+                "required" : [ "springTransactionErrorHandler" ]
+              } ]
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "defaultErrorHandler" ],
+            "properties" : {
+              "defaultErrorHandler" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.DefaultErrorHandlerDefinition"
+              }
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "jtaTransactionErrorHandler" ],
+            "properties" : {
+              "jtaTransactionErrorHandler" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.JtaTransactionErrorHandlerDefinition"
+              }
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "noErrorHandler" ],
+            "properties" : {
+              "noErrorHandler" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.NoErrorHandlerDefinition"
+              }
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "refErrorHandler" ],
+            "properties" : {
+              "refErrorHandler" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.RefErrorHandlerDefinition"
+              }
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "springTransactionErrorHandler" ],
+            "properties" : {
+              "springTransactionErrorHandler" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.errorhandler.SpringTransactionErrorHandlerDefinition"
+              }
+            }
+          } ]
+        } ],
+        "properties" : {
+          "deadLetterChannel" : { },
+          "defaultErrorHandler" : { },
+          "jtaTransactionErrorHandler" : { },
+          "noErrorHandler" : { },
+          "refErrorHandler" : { },
+          "springTransactionErrorHandler" : { }
+        }
+      },
       "org.apache.camel.dsl.yaml.deserializers.BeansDeserializer" : {
         "type" : "array",
         "additionalProperties" : false,
@@ -214,7 +293,7 @@
           "$ref" : "#/items/definitions/org.apache.camel.model.app.RegistryBeanDefinition"
         }
       },
-      "org.apache.camel.dsl.yaml.deserializers.ErrorHandlerBuilderDeserializer" : {
+      "org.apache.camel.dsl.yaml.deserializers.ErrorHandlerDeserializer" : {
         "type" : "object",
         "additionalProperties" : false,
         "anyOf" : [ {
@@ -5094,6 +5173,12 @@
           "description" : {
             "type" : "string"
           },
+          "errorHandler" : {
+            "$ref" : "#/items/definitions/org.apache.camel.ErrorHandlerFactory"
+          },
+          "errorHandlerRef" : {
+            "type" : "string"
+          },
           "from" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.FromDefinition"
           },
@@ -16206,7 +16291,7 @@
         "$ref" : "#/items/definitions/org.apache.camel.dsl.yaml.deserializers.BeansDeserializer"
       },
       "errorHandler" : {
-        "$ref" : "#/items/definitions/org.apache.camel.dsl.yaml.deserializers.ErrorHandlerBuilderDeserializer"
+        "$ref" : "#/items/definitions/org.apache.camel.dsl.yaml.deserializers.ErrorHandlerDeserializer"
       },
       "from" : {
         "$ref" : "#/items/definitions/org.apache.camel.dsl.yaml.deserializers.RouteFromDefinitionDeserializer"
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RoutesTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RoutesTest.groovy
index 4e4a2e5b4c6..ee19ea61da6 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RoutesTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RoutesTest.groovy
@@ -19,6 +19,8 @@ package org.apache.camel.dsl.yaml
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.model.LogDefinition
 import org.apache.camel.model.RouteDefinition
+import org.apache.camel.model.errorhandler.DeadLetterChannelDefinition
+import org.apache.camel.model.errorhandler.RefErrorHandlerDefinition
 import org.junit.jupiter.api.Assertions
 
 class RoutesTest extends YamlTestSupport {
@@ -164,6 +166,91 @@ class RoutesTest extends YamlTestSupport {
             }
     }
 
+    def "load route with error handler ref"() {
+        when:
+        loadRoutes '''
+                - route:
+                    errorHandlerRef: "myErrorHandler"
+                    from: 
+                      uri: "direct:info"
+                      steps:
+                        - log: "message"
+            '''
+        then:
+        context.routeDefinitions.size() == 1
+
+        with(context.routeDefinitions[0], RouteDefinition) {
+            input.endpointUri == 'direct:info'
+            with (outputs[0], LogDefinition) {
+                message == 'message'
+            }
+            errorHandlerFactorySet
+            errorHandlerFactory.class == RefErrorHandlerDefinition.class
+            with (errorHandlerFactory, RefErrorHandlerDefinition) {
+                ref == "myErrorHandler"
+            }
+        }
+    }
+
+    def "load route with error handler"() {
+        when:
+        loadRoutes '''
+                - route:
+                    errorHandler: 
+                      refErrorHandler: 
+                        ref: "myErrorHandler"
+                    from: 
+                      uri: "direct:info"
+                      steps:
+                        - log: "message"
+            '''
+        then:
+        context.routeDefinitions.size() == 1
+
+        with(context.routeDefinitions[0], RouteDefinition) {
+            input.endpointUri == 'direct:info'
+            with (outputs[0], LogDefinition) {
+                message == 'message'
+            }
+            errorHandlerFactorySet
+            errorHandlerFactory.class == RefErrorHandlerDefinition.class
+            with (errorHandlerFactory, RefErrorHandlerDefinition) {
+                ref == "myErrorHandler"
+            }
+        }
+    }
+
+    def "load route with error handler properties"() {
+        when:
+        loadRoutes '''
+                - route:
+                    errorHandler: 
+                      deadLetterChannel: 
+                        deadLetterUri: "mock:on-error"
+                        redeliveryPolicy:
+                          maximumRedeliveries: 3
+                    from: 
+                      uri: "direct:info"
+                      steps:
+                        - log: "message"
+            '''
+        then:
+        context.routeDefinitions.size() == 1
+
+        with(context.routeDefinitions[0], RouteDefinition) {
+            input.endpointUri == 'direct:info'
+            with (outputs[0], LogDefinition) {
+                message == 'message'
+            }
+            errorHandlerFactorySet
+            errorHandlerFactory.class == DeadLetterChannelDefinition.class
+            with (errorHandlerFactory, DeadLetterChannelDefinition) {
+                deadLetterUri == 'mock:on-error'
+                redeliveryPolicy.maximumRedeliveries == "3"
+            }
+        }
+    }
+
     def "load route with input/output types"() {
         when:
         loadRoutes '''
@@ -191,7 +278,6 @@ class RoutesTest extends YamlTestSupport {
         }
     }
 
-
     def "load route inlined camelCase"() {
         when:
         loadRoutes '''