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 2023/07/15 08:35:25 UTC

[camel] 01/03: CAMEL-19607: camel-core - Fix error handler redeliveryPolicyRef

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

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

commit f676ef022817249ae34b823b4eb3b3b9fe8962a1
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Jul 15 09:32:55 2023 +0200

    CAMEL-19607: camel-core - Fix error handler redeliveryPolicyRef
---
 ...SpringDefaultErrorHandlerRedeliveryRefTest.java | 30 +++++++++
 .../DefaultErrorHandlerRedeliveryRefTest.xml       | 44 +++++++++++++
 .../DefaultErrorHandlerDefinition.java             | 17 ++++-
 .../errorhandler/DeadLetterChannelReifier.java     |  7 +-
 .../errorhandler/DefaultErrorHandlerReifier.java   |  7 +-
 .../DefaultErrorHandlerRedeliveryRefTest.java      | 74 ++++++++++++++++++++++
 .../org/apache/camel/xml/in/ModelParserTest.java   | 42 ++++++++++++
 .../test/resources/errorHandlerConfiguration.xml   | 29 +++++++++
 ...rrorHandlerConfigurationRedeliveryPolicyRef.xml | 26 ++++++++
 .../apache/camel/dsl/yaml/ErrorHandlerTest.groovy  | 33 ++++++++++
 10 files changed, 306 insertions(+), 3 deletions(-)

diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringDefaultErrorHandlerRedeliveryRefTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringDefaultErrorHandlerRedeliveryRefTest.java
new file mode 100644
index 00000000000..fc5c21ff64b
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringDefaultErrorHandlerRedeliveryRefTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.processor;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.processor.DefaultErrorHandlerRedeliveryRefTest;
+
+import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+
+public class SpringDefaultErrorHandlerRedeliveryRefTest extends DefaultErrorHandlerRedeliveryRefTest {
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        return createSpringCamelContext(this,
+                "org/apache/camel/spring/processor/DefaultErrorHandlerRedeliveryRefTest.xml");
+    }
+}
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/DefaultErrorHandlerRedeliveryRefTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/DefaultErrorHandlerRedeliveryRefTest.xml
new file mode 100644
index 00000000000..a8dea3727dd
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/DefaultErrorHandlerRedeliveryRefTest.xml
@@ -0,0 +1,44 @@
+<?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
+    ">
+
+    <bean id="myPolicy" class="org.apache.camel.processor.errorhandler.RedeliveryPolicy">
+        <property name="maximumRedeliveries" value="2"/>
+        <property name="redeliveryDelay" value="0"/>
+    </bean>
+
+    <bean id="myProcessor" class="org.apache.camel.processor.DefaultErrorHandlerRedeliveryRefTest$MyProcessor"/>
+
+    <camelContext errorHandlerRef="eh" xmlns="http://camel.apache.org/schema/spring">
+
+        <errorHandler id="eh" redeliveryPolicyRef="myPolicy"/>
+
+        <route>
+            <from uri="direct:start"/>
+            <process ref="myProcessor"/>
+        </route>
+
+    </camelContext>
+</beans>
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/errorhandler/DefaultErrorHandlerDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/errorhandler/DefaultErrorHandlerDefinition.java
index 8727b35f787..74ab640435e 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/errorhandler/DefaultErrorHandlerDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/errorhandler/DefaultErrorHandlerDefinition.java
@@ -126,7 +126,7 @@ public class DefaultErrorHandlerDefinition extends BaseErrorHandlerDefinition {
         other.setRetryWhileRef(getRetryWhileRef());
         other.setUseOriginalBody(getUseOriginalBody());
         other.setUseOriginalMessage(getUseOriginalMessage());
-        if (getRedeliveryPolicy() != null) {
+        if (hasRedeliveryPolicy()) {
             other.setRedeliveryPolicy(getRedeliveryPolicy().copy());
         }
     }
@@ -405,6 +405,10 @@ public class DefaultErrorHandlerDefinition extends BaseErrorHandlerDefinition {
         return redeliveryPolicy;
     }
 
+    public boolean hasRedeliveryPolicy() {
+        return redeliveryPolicy != null;
+    }
+
     /**
      * Sets the redelivery settings
      */
@@ -809,4 +813,15 @@ public class DefaultErrorHandlerDefinition extends BaseErrorHandlerDefinition {
         return this;
     }
 
+    /**
+     * Sets a reference to a {@link RedeliveryPolicy} to be used for redelivery settings.
+     *
+     * @param  redeliveryPolicyRef the redelivrey policy reference
+     * @return                     the builder
+     */
+    public DefaultErrorHandlerDefinition redeliveryPolicyRef(String redeliveryPolicyRef) {
+        setRedeliveryPolicyRef(redeliveryPolicyRef);
+        return this;
+    }
+
 }
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
index 072a3e58d5f..31becf55359 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
@@ -107,8 +107,13 @@ public class DeadLetterChannelReifier extends ErrorHandlerReifier<DeadLetterChan
     }
 
     private RedeliveryPolicy resolveRedeliveryPolicy(DeadLetterChannelDefinition definition, CamelContext camelContext) {
+        if (definition.hasRedeliveryPolicy() && definition.getRedeliveryPolicyRef() != null) {
+            throw new IllegalArgumentException(
+                    "Cannot have both redeliveryPolicy and redeliveryPolicyRef set at the same time.");
+        }
+
         RedeliveryPolicy answer = null;
-        RedeliveryPolicyDefinition def = definition.getRedeliveryPolicy();
+        RedeliveryPolicyDefinition def = definition.hasRedeliveryPolicy() ? definition.getRedeliveryPolicy() : null;
         if (def == null && definition.getRedeliveryPolicyRef() != null) {
             // ref may point to a definition
             def = lookupByNameAndType(definition.getRedeliveryPolicyRef(), RedeliveryPolicyDefinition.class);
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
index 013849b8719..699b41307e1 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
@@ -100,8 +100,13 @@ public class DefaultErrorHandlerReifier extends ErrorHandlerReifier<DefaultError
     }
 
     private RedeliveryPolicy resolveRedeliveryPolicy(DefaultErrorHandlerDefinition definition, CamelContext camelContext) {
+        if (definition.hasRedeliveryPolicy() && definition.getRedeliveryPolicyRef() != null) {
+            throw new IllegalArgumentException(
+                    "Cannot have both redeliveryPolicy and redeliveryPolicyRef set at the same time.");
+        }
+
         RedeliveryPolicy answer = null;
-        RedeliveryPolicyDefinition def = definition.getRedeliveryPolicy();
+        RedeliveryPolicyDefinition def = definition.hasRedeliveryPolicy() ? definition.getRedeliveryPolicy() : null;
         if (def != null) {
             answer = ErrorHandlerReifier.createRedeliveryPolicy(def, camelContext, null);
         }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/DefaultErrorHandlerRedeliveryRefTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/DefaultErrorHandlerRedeliveryRefTest.java
new file mode 100644
index 00000000000..19da41520e2
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/DefaultErrorHandlerRedeliveryRefTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class DefaultErrorHandlerRedeliveryRefTest extends ContextTestSupport {
+
+    private static int counter;
+
+    @Test
+    public void testRedeliveryRefTest() throws Exception {
+        counter = 0;
+
+        try {
+            template.sendBody("direct:start", "Hello World");
+            fail("Should have thrown exception");
+        } catch (RuntimeCamelException e) {
+            // expected
+        }
+
+        // One call + 2 re-deliveries
+        assertEquals(3, counter);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                RedeliveryPolicy policy = new RedeliveryPolicy();
+                policy.maximumRedeliveries(2);
+                policy.redeliveryDelay(0);
+                getCamelContext().getRegistry().bind("myPolicy", policy);
+
+                errorHandler(defaultErrorHandler().redeliveryPolicyRef("myPolicy"));
+
+                from("direct:start").process(new MyProcessor());
+            }
+        };
+    }
+
+    public static class MyProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) throws Exception {
+            counter++;
+            throw new Exception("Forced exception by unit test");
+        }
+    }
+
+}
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
index dc42173eb4a..796cc2fa458 100644
--- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -30,12 +30,15 @@ import java.util.stream.Stream;
 
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.model.RouteConfigurationDefinition;
+import org.apache.camel.model.RouteConfigurationsDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplatesDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.SetBodyDefinition;
 import org.apache.camel.model.TemplatedRoutesDefinition;
 import org.apache.camel.model.ToDefinition;
+import org.apache.camel.model.errorhandler.DeadLetterChannelDefinition;
 import org.apache.camel.model.language.XPathExpression;
 import org.apache.camel.model.rest.ParamDefinition;
 import org.apache.camel.model.rest.RestDefinition;
@@ -45,7 +48,10 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class ModelParserTest {
 
@@ -240,6 +246,42 @@ public class ModelParserTest {
         Assertions.assertEquals(toUri, to.getEndpointUri());
     }
 
+    @Test
+    public void testErrorHandler() throws Exception {
+        Path dir = getResourceFolder();
+        Path path = new File(dir.toFile(), "errorHandlerConfiguration.xml").toPath();
+        ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE);
+        RouteConfigurationsDefinition routes = parser.parseRouteConfigurationsDefinition().orElse(null);
+        assertNotNull(routes);
+        assertEquals(1, routes.getRouteConfigurations().size());
+
+        RouteConfigurationDefinition cfg = routes.getRouteConfigurations().get(0);
+        assertInstanceOf(DeadLetterChannelDefinition.class, cfg.getErrorHandler().getErrorHandlerType());
+        DeadLetterChannelDefinition dlc = (DeadLetterChannelDefinition) cfg.getErrorHandler().getErrorHandlerType();
+        assertEquals("mock:dead", dlc.getDeadLetterUri());
+        assertTrue(dlc.hasRedeliveryPolicy());
+        assertEquals("2", dlc.getRedeliveryPolicy().getMaximumRedeliveries());
+        assertEquals("123", dlc.getRedeliveryPolicy().getRedeliveryDelay());
+        assertEquals("false", dlc.getRedeliveryPolicy().getLogStackTrace());
+    }
+
+    @Test
+    public void testErrorHandlerRedeliveryPolicyRef() throws Exception {
+        Path dir = getResourceFolder();
+        Path path = new File(dir.toFile(), "errorHandlerConfigurationRedeliveryPolicyRef.xml").toPath();
+        ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE);
+        RouteConfigurationsDefinition routes = parser.parseRouteConfigurationsDefinition().orElse(null);
+        assertNotNull(routes);
+        assertEquals(1, routes.getRouteConfigurations().size());
+
+        RouteConfigurationDefinition cfg = routes.getRouteConfigurations().get(0);
+        assertInstanceOf(DeadLetterChannelDefinition.class, cfg.getErrorHandler().getErrorHandlerType());
+        DeadLetterChannelDefinition dlc = (DeadLetterChannelDefinition) cfg.getErrorHandler().getErrorHandlerType();
+        assertEquals("mock:dead", dlc.getDeadLetterUri());
+        assertFalse(dlc.hasRedeliveryPolicy());
+        assertEquals("myPolicy", dlc.getRedeliveryPolicyRef());
+    }
+
     private Path getResourceFolder() {
         String url = getClass().getClassLoader().getResource("barInterceptorRoute.xml").toString();
         if (url.startsWith("file:")) {
diff --git a/core/camel-xml-io/src/test/resources/errorHandlerConfiguration.xml b/core/camel-xml-io/src/test/resources/errorHandlerConfiguration.xml
new file mode 100644
index 00000000000..81071092a93
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/errorHandlerConfiguration.xml
@@ -0,0 +1,29 @@
+<?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.
+
+-->
+<routeConfigurations xmlns="http://camel.apache.org/schema/spring">
+    <routeConfiguration>
+        <errorHandler>
+            <deadLetterChannel deadLetterUri="mock:dead">
+                <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="123"
+                                  logStackTrace="false"/>
+            </deadLetterChannel>
+        </errorHandler>
+    </routeConfiguration>
+</routeConfigurations>
diff --git a/core/camel-xml-io/src/test/resources/errorHandlerConfigurationRedeliveryPolicyRef.xml b/core/camel-xml-io/src/test/resources/errorHandlerConfigurationRedeliveryPolicyRef.xml
new file mode 100644
index 00000000000..24b7aa36ddb
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/errorHandlerConfigurationRedeliveryPolicyRef.xml
@@ -0,0 +1,26 @@
+<?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.
+
+-->
+<routeConfigurations xmlns="http://camel.apache.org/schema/spring">
+    <routeConfiguration>
+        <errorHandler>
+            <deadLetterChannel deadLetterUri="mock:dead" redeliveryPolicyRef="myPolicy"/>
+        </errorHandler>
+    </routeConfiguration>
+</routeConfigurations>
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ErrorHandlerTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ErrorHandlerTest.groovy
index b66d919020d..9e9bdb4f2ef 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ErrorHandlerTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ErrorHandlerTest.groovy
@@ -139,4 +139,37 @@ class ErrorHandlerTest extends YamlTestSupport {
             context.getErrorHandlerFactory() instanceof NoErrorHandlerDefinition
     }
 
+    def "error-handler (redelivery policy ref)"() {
+        setup:
+        loadRoutes """
+                - beans:
+                  - name: myFailingProcessor
+                    type: ${MyFailingProcessor.name}
+                  - name: myPolicy
+                    type: org.apache.camel.processor.errorhandler.RedeliveryPolicy
+                    properties:
+                      maximumRedeliveries: 3
+                      logStackTrace: true
+                - error-handler:
+                    default-error-handler:
+                      useOriginalMessage: true 
+                      redelivery-policy-ref: myPolicy
+                - from:
+                    uri: "direct:start"
+                    steps:
+                      - process:
+                          ref: "myFailingProcessor"
+            """
+
+        when:
+        context.start()
+        then:
+        with(context.getCamelContextExtension().getErrorHandlerFactory(), DefaultErrorHandlerDefinition) {
+            useOriginalMessage == "true"
+            hasRedeliveryPolicy() == false
+            redeliveryPolicyRef == "myPolicy"
+        }
+    }
+
+
 }