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, "",
