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

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

commit dbe14a530b89fcbf5e1864fe8471f7d7782867f1
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Apr 13 11:32:02 2024 +0200

    CAMEL-20666: Add errorHandler on route for EIP model (XML and YAML DSL) to 
be consistent.
---
 .../org/apache/camel/catalog/models/route.json     |  9 ++--
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  1 +
 .../camel/spring/config/ErrorHandlerRouteTest.java | 58 ++++++++++++++++++++++
 .../camel/spring/config/errorHandlerRoute.xml      | 41 +++++++++++++++
 .../java/org/apache/camel/impl/DefaultModel.java   |  2 +-
 .../META-INF/org/apache/camel/model/route.json     |  9 ++--
 .../org/apache/camel/model/RouteDefinition.java    | 18 ++++++-
 .../camel/model/RouteTemplateDefinition.java       |  1 +
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |  1 +
 .../test/resources/routeInlinedErrorHandler.xml    | 32 ++++++++++++
 .../org/apache/camel/yaml/out/ModelWriter.java     |  1 +
 .../modules/ROOT/pages/error-handler.adoc          | 20 +++++++-
 .../camel/maven/packaging/SchemaGeneratorMojo.java |  8 +++
 14 files changed, 191 insertions(+), 11 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/route.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/route.json
index 8c9a21bbb1c..0451e8ceeb8 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/route.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/route.json
@@ -29,9 +29,10 @@
     "shutdownRoute": { "index": 14, "kind": "attribute", "displayName": 
"Shutdown Route", "label": "advanced", "required": false, "type": "enum", 
"javaType": "org.apache.camel.ShutdownRoute", "enum": [ "Default", "Defer" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
control how to shutdown the route." },
     "shutdownRunningTask": { "index": 15, "kind": "attribute", "displayName": 
"Shutdown Running Task", "label": "advanced", "required": false, "type": 
"enum", "javaType": "org.apache.camel.ShutdownRunningTask", "enum": [ 
"CompleteCurrentTaskOnly", "CompleteAllTasks" ], "deprecated": false, 
"autowired": false, "secret": false, "description": "To control how to shut 
down the route." },
     "precondition": { "index": 16, "kind": "attribute", "displayName": 
"Precondition", "label": "advanced", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "The predicate of the precondition in simple 
language to evaluate in order to determine if this route should be included or 
not." },
-    "inputType": { "index": 17, "kind": "element", "displayName": "Input 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.InputTypeDefinition", "deprecated": false, "autowired": 
false, "secret": false, "description": "Declare the expected data type of the 
input message. If the actual message type is different at runtime, camel look 
for a required org.apache.camel.spi.Transformer and apply if exists. The type 
name consists of two parts,  [...]
-    "outputType": { "index": 18, "kind": "element", "displayName": "Output 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.OutputTypeDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Declare the expected data 
type of the output message. If the actual message type is different at runtime, 
camel look for a required org.apache.camel.spi.Transformer and apply if exists. 
The type name consists of two par [...]
-    "input": { "index": 19, "kind": "element", "displayName": "Input", 
"required": true, "type": "object", "javaType": 
"org.apache.camel.model.FromDefinition", "oneOf": [ "from" ], "deprecated": 
false, "autowired": false, "secret": false, "description": "Input to the 
route." },
-    "outputs": { "index": 20, "kind": "element", "displayName": "Outputs", 
"required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", "oneOf": [ 
"aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", 
"convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", 
"doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", 
"intercept", "interceptFrom", "interceptSendToEndpoint", "kamelet", "load [...]
+    "errorHandler": { "index": 17, "kind": "element", "displayName": "Error 
Handler", "label": "error", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.ErrorHandlerDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the error handler to 
use for this route" },
+    "inputType": { "index": 18, "kind": "element", "displayName": "Input 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.InputTypeDefinition", "deprecated": false, "autowired": 
false, "secret": false, "description": "Declare the expected data type of the 
input message. If the actual message type is different at runtime, camel look 
for a required org.apache.camel.spi.Transformer and apply if exists. The type 
name consists of two parts,  [...]
+    "outputType": { "index": 19, "kind": "element", "displayName": "Output 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.OutputTypeDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Declare the expected data 
type of the output message. If the actual message type is different at runtime, 
camel look for a required org.apache.camel.spi.Transformer and apply if exists. 
The type name consists of two par [...]
+    "input": { "index": 20, "kind": "element", "displayName": "Input", 
"required": true, "type": "object", "javaType": 
"org.apache.camel.model.FromDefinition", "oneOf": [ "from" ], "deprecated": 
false, "autowired": false, "secret": false, "description": "Input to the 
route." },
+    "outputs": { "index": 21, "kind": "element", "displayName": "Outputs", 
"required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", "oneOf": [ 
"aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", 
"convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", 
"doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", 
"intercept", "interceptFrom", "interceptSendToEndpoint", "kamelet", "load [...]
   }
 }
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 96c6a29de58..b31aac91b34 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
@@ -12176,6 +12176,7 @@ Reference to the routes in the xml dsl.
       <xs:extension base="tns:output">
         <xs:sequence>
           <xs:element maxOccurs="unbounded" minOccurs="0" name="routeProperty" 
type="tns:propertyDefinition"/>
+          <xs:element minOccurs="0" ref="tns:errorHandler"/>
           <xs:element minOccurs="0" ref="tns:from"/>
           <xs:element minOccurs="0" ref="tns:inputType"/>
           <xs:element minOccurs="0" ref="tns:outputType"/>
diff --git 
a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/config/ErrorHandlerRouteTest.java
 
b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/config/ErrorHandlerRouteTest.java
new file mode 100644
index 00000000000..d62267dc49c
--- /dev/null
+++ 
b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/config/ErrorHandlerRouteTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.spring.config;
+
+import java.util.List;
+
+import org.apache.camel.Channel;
+import org.apache.camel.Route;
+import org.apache.camel.impl.engine.DefaultRoute;
+import org.apache.camel.processor.errorhandler.DeadLetterChannel;
+import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
+import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.spring.SpringTestSupport;
+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.assertEquals;
+
+public class ErrorHandlerRouteTest extends SpringTestSupport {
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/spring/config/errorHandlerRoute.xml");
+    }
+
+    @Test
+    public void testEndpointConfiguration() throws Exception {
+        SpringCamelContext context = 
applicationContext.getBeansOfType(SpringCamelContext.class).values().iterator().next();
+        List<Route> list = context.getRoutes();
+        assertEquals(1, list.size(), "Number routes created" + list);
+        for (Route route : list) {
+            DefaultRoute consumerRoute = 
assertIsInstanceOf(DefaultRoute.class, route);
+            Channel channel = unwrapChannel(consumerRoute.getProcessor());
+
+            DeadLetterChannel deadLetterChannel = 
assertIsInstanceOf(DeadLetterChannel.class, channel.getErrorHandler());
+            RedeliveryPolicy redeliveryPolicy = 
deadLetterChannel.getRedeliveryPolicy();
+
+            assertEquals(1, redeliveryPolicy.getMaximumRedeliveries(), 
"getMaximumRedeliveries()");
+            assertEquals(true, redeliveryPolicy.isUseExponentialBackOff(), 
"isUseExponentialBackOff()");
+        }
+    }
+
+}
diff --git 
a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/errorHandlerRoute.xml
 
b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/errorHandlerRoute.xml
new file mode 100644
index 00000000000..16954274ca4
--- /dev/null
+++ 
b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/errorHandlerRoute.xml
@@ -0,0 +1,41 @@
+<?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";>
+        <jmxAgent id="agent" disabled="true"/>
+        <route>
+            <errorHandler>
+                <deadLetterChannel deadLetterUri="mock:exceptionProcessor">
+                    <redeliveryPolicy maximumRedeliveries="1" 
redeliveryDelay="30000" useExponentialBackOff="true"/>
+                </deadLetterChannel>
+            </errorHandler>
+            <from uri="seda:a"/>
+            <to uri="seda:b"/>
+        </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 3c6e890502e..9a3383055c5 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
@@ -255,7 +255,7 @@ public class DefaultModel implements Model {
                                 
r.setErrorHandlerRef(toBeInlined.getErrorHandlerRef());
                                 
r.setPrecondition(toBeInlined.getPrecondition());
                                 if (toBeInlined.isErrorHandlerFactorySet()) {
-                                    
r.setErrorHandlerFactory(toBeInlined.getErrorHandlerFactory());
+                                    
r.setErrorHandler(toBeInlined.getErrorHandler());
                                 }
                             }
                         }
diff --git 
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/route.json
 
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/route.json
index 8c9a21bbb1c..0451e8ceeb8 100644
--- 
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/route.json
+++ 
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/route.json
@@ -29,9 +29,10 @@
     "shutdownRoute": { "index": 14, "kind": "attribute", "displayName": 
"Shutdown Route", "label": "advanced", "required": false, "type": "enum", 
"javaType": "org.apache.camel.ShutdownRoute", "enum": [ "Default", "Defer" ], 
"deprecated": false, "autowired": false, "secret": false, "description": "To 
control how to shutdown the route." },
     "shutdownRunningTask": { "index": 15, "kind": "attribute", "displayName": 
"Shutdown Running Task", "label": "advanced", "required": false, "type": 
"enum", "javaType": "org.apache.camel.ShutdownRunningTask", "enum": [ 
"CompleteCurrentTaskOnly", "CompleteAllTasks" ], "deprecated": false, 
"autowired": false, "secret": false, "description": "To control how to shut 
down the route." },
     "precondition": { "index": 16, "kind": "attribute", "displayName": 
"Precondition", "label": "advanced", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "The predicate of the precondition in simple 
language to evaluate in order to determine if this route should be included or 
not." },
-    "inputType": { "index": 17, "kind": "element", "displayName": "Input 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.InputTypeDefinition", "deprecated": false, "autowired": 
false, "secret": false, "description": "Declare the expected data type of the 
input message. If the actual message type is different at runtime, camel look 
for a required org.apache.camel.spi.Transformer and apply if exists. The type 
name consists of two parts,  [...]
-    "outputType": { "index": 18, "kind": "element", "displayName": "Output 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.OutputTypeDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Declare the expected data 
type of the output message. If the actual message type is different at runtime, 
camel look for a required org.apache.camel.spi.Transformer and apply if exists. 
The type name consists of two par [...]
-    "input": { "index": 19, "kind": "element", "displayName": "Input", 
"required": true, "type": "object", "javaType": 
"org.apache.camel.model.FromDefinition", "oneOf": [ "from" ], "deprecated": 
false, "autowired": false, "secret": false, "description": "Input to the 
route." },
-    "outputs": { "index": 20, "kind": "element", "displayName": "Outputs", 
"required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", "oneOf": [ 
"aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", 
"convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", 
"doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", 
"intercept", "interceptFrom", "interceptSendToEndpoint", "kamelet", "load [...]
+    "errorHandler": { "index": 17, "kind": "element", "displayName": "Error 
Handler", "label": "error", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.ErrorHandlerDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the error handler to 
use for this route" },
+    "inputType": { "index": 18, "kind": "element", "displayName": "Input 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.InputTypeDefinition", "deprecated": false, "autowired": 
false, "secret": false, "description": "Declare the expected data type of the 
input message. If the actual message type is different at runtime, camel look 
for a required org.apache.camel.spi.Transformer and apply if exists. The type 
name consists of two parts,  [...]
+    "outputType": { "index": 19, "kind": "element", "displayName": "Output 
Type", "label": "advanced", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.OutputTypeDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Declare the expected data 
type of the output message. If the actual message type is different at runtime, 
camel look for a required org.apache.camel.spi.Transformer and apply if exists. 
The type name consists of two par [...]
+    "input": { "index": 20, "kind": "element", "displayName": "Input", 
"required": true, "type": "object", "javaType": 
"org.apache.camel.model.FromDefinition", "oneOf": [ "from" ], "deprecated": 
false, "autowired": false, "secret": false, "description": "Input to the 
route." },
+    "outputs": { "index": 21, "kind": "element", "displayName": "Outputs", 
"required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.ProcessorDefinition<?>>", "oneOf": [ 
"aggregate", "bean", "choice", "circuitBreaker", "claimCheck", "convertBodyTo", 
"convertHeaderTo", "convertVariableTo", "delay", "doCatch", "doFinally", 
"doTry", "dynamicRouter", "enrich", "filter", "idempotentConsumer", 
"intercept", "interceptFrom", "interceptSendToEndpoint", "kamelet", "load [...]
   }
 }
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 fea85633ba5..9941dd27a3b 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
@@ -56,7 +56,7 @@ import org.apache.camel.spi.RoutePolicy;
  */
 @Metadata(label = "configuration")
 @XmlRootElement(name = "route")
-@XmlType(propOrder = { "routeProperties", "input", "inputType", "outputType", 
"outputs" })
+@XmlType(propOrder = { "routeProperties", "errorHandler", "input", 
"inputType", "outputType", "outputs" })
 @XmlAccessorType(XmlAccessType.PROPERTY)
 // must use XmlAccessType.PROPERTY as there is some custom logic needed to be 
executed in the setter methods
 public class RouteDefinition extends OutputDefinition<RouteDefinition>
@@ -80,6 +80,7 @@ public class RouteDefinition extends 
OutputDefinition<RouteDefinition>
     private String shutdownRunningTask;
     private String errorHandlerRef;
     private ErrorHandlerFactory errorHandlerFactory;
+    private ErrorHandlerDefinition errorHandler;
     // keep state whether the error handler is context scoped or not
     // (will by default be context scoped of no explicit error handler
     // configured)
@@ -1067,6 +1068,21 @@ public class RouteDefinition extends 
OutputDefinition<RouteDefinition>
         return errorHandlerRef;
     }
 
+    public ErrorHandlerDefinition getErrorHandler() {
+        return errorHandler;
+    }
+
+    /**
+     * Sets the error handler to use for this route
+     */
+    @XmlElement
+    public void setErrorHandler(ErrorHandlerDefinition errorHandler) {
+        this.errorHandler = errorHandler;
+        if (errorHandler != null) {
+            this.errorHandlerFactory = errorHandler.getErrorHandlerType();
+        }
+    }
+
     /**
      * Sets the error handler if one is not already set
      */
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
index baeecddbff1..8cff7141914 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateDefinition.java
@@ -403,6 +403,7 @@ public class RouteTemplateDefinition extends 
OptionalIdentifiedDefinition<RouteT
             // only set factory if not already set
             copy.setErrorHandlerFactory(route.getErrorHandlerFactory());
         }
+        copy.setErrorHandler(route.getErrorHandler());
 
         // and then copy over the rest
         // (do not copy id as it is used for route template id)
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 d8807a60ffa..8b16a1acddd 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
@@ -1087,6 +1087,7 @@ public class ModelParser extends BaseParser {
                 case "from": def.setInput(doParseFromDefinition()); break;
                 case "inputType": 
def.setInputType(doParseInputTypeDefinition()); break;
                 case "outputType": 
def.setOutputType(doParseOutputTypeDefinition()); break;
+                case "errorHandler": 
def.setErrorHandler(doParseErrorHandlerDefinition()); break;
                 case "kamelet": 
def.setKamelet(Boolean.valueOf(doParseText())); break;
                 case "rest": def.setRest(Boolean.valueOf(doParseText())); 
break;
                 case "routeProperty": doAdd(doParsePropertyDefinition(), 
def.getRouteProperties(), def::setRouteProperties); break;
diff --git 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index eb9433c08bb..944d33689e7 100644
--- 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -2115,6 +2115,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("group", def.getGroup());
         doWriteAttribute("errorHandlerRef", def.getErrorHandlerRef());
         doWriteList(null, "routeProperty", def.getRouteProperties(), 
this::doWritePropertyDefinition);
+        doWriteElement("errorHandler", def.getErrorHandler(), 
this::doWriteErrorHandlerDefinition);
         doWriteElement(null, def.getInput(), this::doWriteFromDefinitionRef);
         doWriteElement(null, def.getInputType(), 
this::doWriteInputTypeDefinitionRef);
         doWriteElement(null, def.getOutputType(), 
this::doWriteOutputTypeDefinitionRef);
diff --git a/core/camel-xml-io/src/test/resources/routeInlinedErrorHandler.xml 
b/core/camel-xml-io/src/test/resources/routeInlinedErrorHandler.xml
new file mode 100644
index 00000000000..75bb0c65682
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeInlinedErrorHandler.xml
@@ -0,0 +1,32 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring";>
+
+  <route>
+    <errorHandler>
+      <deadLetterChannel deadLetterUri="mock:dead">
+        <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="123"
+                          logStackTrace="false"/>
+      </deadLetterChannel>
+    </errorHandler>
+    <from uri="seda:a"/>
+    <to uri="seda:b"/>
+  </route>
+</routes>
diff --git 
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
 
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index f4d114a2d51..77d425c592b 100644
--- 
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ 
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -2115,6 +2115,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("group", def.getGroup());
         doWriteAttribute("errorHandlerRef", def.getErrorHandlerRef());
         doWriteList(null, "routeProperty", def.getRouteProperties(), 
this::doWritePropertyDefinition);
+        doWriteElement("errorHandler", def.getErrorHandler(), 
this::doWriteErrorHandlerDefinition);
         doWriteElement(null, def.getInput(), this::doWriteFromDefinitionRef);
         doWriteElement(null, def.getInputType(), 
this::doWriteInputTypeDefinitionRef);
         doWriteElement(null, def.getOutputType(), 
this::doWriteOutputTypeDefinitionRef);
diff --git a/docs/user-manual/modules/ROOT/pages/error-handler.adoc 
b/docs/user-manual/modules/ROOT/pages/error-handler.adoc
index 4812073019e..37920f7630e 100644
--- a/docs/user-manual/modules/ROOT/pages/error-handler.adoc
+++ b/docs/user-manual/modules/ROOT/pages/error-handler.adoc
@@ -246,7 +246,6 @@ the `errorHandlerRef` attribute on the `route` tag.
 [source,xml]
 ----
     <camelContext xmlns="http://camel.apache.org/schema/spring";>
-        <template id="myTemplate"/>
         <!-- set the errorHandlerRef to our DeadLetterChannel, this applies 
for this route only -->
         <route errorHandlerRef="myDeadLetterErrorHandler">
             <from uri="direct:in"/>
@@ -282,6 +281,25 @@ etc.
     </bean>
 ----
 
+In *Camel 4.6* you can now inline `<errorHandler>` directly in the routes. The 
example above can be done as follows:
+
+[source,xml]
+----
+    <camelContext xmlns="http://camel.apache.org/schema/spring";>
+        <route>
+            <errorHandler>
+                <deadLetterChannel deadLetterUri="mock:dead">
+                    <redeliveryPolicy maximumRedeliveries="3" 
redeliveryDelay="250"/>
+                </deadLetterChannel>
+            </errorHandler>
+            <from uri="direct:in"/>
+            <process ref="myFailureProcessor"/>
+            <to uri="mock:result"/>
+        </route>
+    </camelContext>
+----
+
+
 == Using the transactional error handler
 
 The transactional error handler is based on spring transaction. This
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SchemaGeneratorMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SchemaGeneratorMojo.java
index 334a352cf9e..b435fdeb40c 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SchemaGeneratorMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SchemaGeneratorMojo.java
@@ -857,6 +857,14 @@ public class SchemaGeneratorMojo extends 
AbstractGeneratorMojo {
                 null, false, null, null, false, false);
         eipOptions.add(ep);
 
+        // error handler
+        docComment = findJavaDoc(null, "errorHandler", null, classElement, 
true);
+        ep = createOption("errorHandler", "Error Handler", "element", 
"org.apache.camel.model.ErrorHandlerDefinition", false,
+                "",
+                "error", docComment, false,
+                null, false, null, null, false, false);
+        eipOptions.add(ep);
+
         // input type
         docComment = findJavaDoc(null, "inputType", null, classElement, true);
         ep = createOption("inputType", "Input Type", "element", 
"org.apache.camel.model.InputTypeDefinition", false, "",

Reply via email to