This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch useorig in repository https://gitbox.apache.org/repos/asf/camel.git
commit a0e6d631065d418aea82d76766e9327c7213e559 Author: Claus Ibsen <[email protected]> AuthorDate: Mon Aug 19 09:41:17 2024 +0200 CAMEL-20844: UseOriginalAggregationStrategy should store caught exception in exchange property so the error information is accessible afterwards. --- .../aggregate/UseOriginalAggregationStrategy.java | 16 +++++++++ ...litterUseOriginalNotPropagateExceptionTest.java | 13 ++++++-- ...UseOriginalPropagateExceptionSubRouteTest.java} | 38 ++++++++++++++++------ ...SplitterUseOriginalPropagateExceptionTest.java} | 26 ++++++++++----- .../ROOT/pages/camel-4x-upgrade-guide-4_8.adoc | 6 ++++ 5 files changed, 79 insertions(+), 20 deletions(-) diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/UseOriginalAggregationStrategy.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/UseOriginalAggregationStrategy.java index 1abb39047ce..1169e71d760 100644 --- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/UseOriginalAggregationStrategy.java +++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/UseOriginalAggregationStrategy.java @@ -70,6 +70,14 @@ public class UseOriginalAggregationStrategy implements AggregationStrategy { oldExchange.setException(exception); } } + exception = checkCaughtException(oldExchange, newExchange); + if (exception != null) { + if (original != null) { + original.setProperty(Exchange.EXCEPTION_CAUGHT, exception); + } else { + oldExchange.setProperty(Exchange.EXCEPTION_CAUGHT, exception); + } + } } return original != null ? original : oldExchange; } @@ -84,6 +92,14 @@ public class UseOriginalAggregationStrategy implements AggregationStrategy { } } + protected Exception checkCaughtException(Exchange oldExchange, Exchange newExchange) { + Exception caught = newExchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); + if (caught == null && oldExchange != null) { + caught = oldExchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); + } + return caught; + } + public Exchange getOriginal() { return original; } diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java index f4eb803902f..1ef4a9897a2 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java @@ -18,6 +18,7 @@ package org.apache.camel.processor; import org.apache.camel.CamelContext; import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; import org.apache.camel.builder.AggregationStrategies; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.CamelEvent; @@ -26,6 +27,7 @@ import org.apache.camel.support.EventNotifierSupport; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSupport { @@ -40,7 +42,7 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup } @Test - public void testUseOriginalNotPropgateException() throws Exception { + public void testUseOriginalNotPropagateException() throws Exception { assertEquals(0, notifier.getErrors()); getMockEndpoint("mock:line").expectedBodiesReceived("Hello", "World"); @@ -64,7 +66,14 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup return new RouteBuilder() { @Override public void configure() { - from("direct:start").split(body()).aggregationStrategy(AggregationStrategies.useOriginal(false)) + from("direct:start") + .onCompletion().process(e -> { + Exception caught = e.getException(); + assertNull(caught); + caught = e.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); + assertNull(caught); + }).end() + .split(body()).aggregationStrategy(AggregationStrategies.useOriginal(false)) .filter(simple("${body} == 'Kaboom'")) .throwException(new IllegalArgumentException("Forced error")).end().to("mock:line").end() .to("mock:result"); diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionSubRouteTest.java similarity index 63% copy from core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java copy to core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionSubRouteTest.java index f4eb803902f..7316c8ce647 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionSubRouteTest.java @@ -18,6 +18,7 @@ package org.apache.camel.processor; import org.apache.camel.CamelContext; import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; import org.apache.camel.builder.AggregationStrategies; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.CamelEvent; @@ -26,9 +27,10 @@ import org.apache.camel.support.EventNotifierSupport; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; -public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSupport { +public class SplitterUseOriginalPropagateExceptionSubRouteTest extends ContextTestSupport { private final MyEventNotifier notifier = new MyEventNotifier(); @@ -40,23 +42,23 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup } @Test - public void testUseOriginalNotPropgateException() throws Exception { + public void testUseOriginalPropagateException() throws Exception { assertEquals(0, notifier.getErrors()); getMockEndpoint("mock:line").expectedBodiesReceived("Hello", "World"); - getMockEndpoint("mock:result").expectedBodiesReceived("Hello,Kaboom,World"); + getMockEndpoint("mock:result").expectedMessageCount(0); try { template.sendBody("direct:start", "Hello,Kaboom,World"); + fail("Should fail"); } catch (Exception e) { - fail("Should not fail"); + // expected } assertMockEndpointsSatisfied(); - // there should only be 1 error as we do not propagate errors to the - // parent - assertEquals(1, notifier.getErrors()); + // there should be 1+1 error as we propagate error back to the parent + assertEquals(2, notifier.getErrors()); } @Override @@ -64,10 +66,26 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup return new RouteBuilder() { @Override public void configure() { - from("direct:start").split(body()).aggregationStrategy(AggregationStrategies.useOriginal(false)) - .filter(simple("${body} == 'Kaboom'")) - .throwException(new IllegalArgumentException("Forced error")).end().to("mock:line").end() + from("direct:start") + .onCompletion().process(e -> { + Exception caught = e.getException(); + assertNull(caught); + caught = e.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); + assertIsInstanceOf(IllegalArgumentException.class, caught); + assertEquals("Forced error", caught.getMessage()); + }).end() + .split(body()).aggregationStrategy(AggregationStrategies.useOriginal(true)) + .to("direct:sub") + .end() .to("mock:result"); + + from("direct:sub") + // simulate retrying error handler + .errorHandler(defaultErrorHandler().maximumRedeliveries(3).redeliveryDelay(0)) + .filter(simple("${body} == 'Kaboom'")) + .throwException(new IllegalArgumentException("Forced error")) + .end() + .to("mock:line"); } }; } diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionTest.java similarity index 71% copy from core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java copy to core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionTest.java index f4eb803902f..3bbf4ce430e 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalNotPropagateExceptionTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/SplitterUseOriginalPropagateExceptionTest.java @@ -18,6 +18,7 @@ package org.apache.camel.processor; import org.apache.camel.CamelContext; import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; import org.apache.camel.builder.AggregationStrategies; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.CamelEvent; @@ -26,9 +27,10 @@ import org.apache.camel.support.EventNotifierSupport; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; -public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSupport { +public class SplitterUseOriginalPropagateExceptionTest extends ContextTestSupport { private final MyEventNotifier notifier = new MyEventNotifier(); @@ -40,23 +42,23 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup } @Test - public void testUseOriginalNotPropgateException() throws Exception { + public void testUseOriginalPropagateException() throws Exception { assertEquals(0, notifier.getErrors()); getMockEndpoint("mock:line").expectedBodiesReceived("Hello", "World"); - getMockEndpoint("mock:result").expectedBodiesReceived("Hello,Kaboom,World"); + getMockEndpoint("mock:result").expectedMessageCount(0); try { template.sendBody("direct:start", "Hello,Kaboom,World"); + fail("Should fail"); } catch (Exception e) { - fail("Should not fail"); + // expected } assertMockEndpointsSatisfied(); - // there should only be 1 error as we do not propagate errors to the - // parent - assertEquals(1, notifier.getErrors()); + // there should be 1+1 error as we propagate error back to the parent + assertEquals(2, notifier.getErrors()); } @Override @@ -64,7 +66,15 @@ public class SplitterUseOriginalNotPropagateExceptionTest extends ContextTestSup return new RouteBuilder() { @Override public void configure() { - from("direct:start").split(body()).aggregationStrategy(AggregationStrategies.useOriginal(false)) + from("direct:start") + .onCompletion().process(e -> { + Exception caught = e.getException(); + assertNull(caught); + caught = e.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); + assertIsInstanceOf(IllegalArgumentException.class, caught); + assertEquals("Forced error", caught.getMessage()); + }).end() + .split(body()).aggregationStrategy(AggregationStrategies.useOriginal(true)) .filter(simple("${body} == 'Kaboom'")) .throwException(new IllegalArgumentException("Forced error")).end().to("mock:line").end() .to("mock:result"); diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc index 3775ba0a18b..214ce003a21 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc @@ -6,6 +6,12 @@ from both 4.0 to 4.1 and 4.1 to 4.2. == Upgrading Camel 4.7 to 4.8 +=== camel-core + +The `UseOriginalAggregationStrategy` class will now propagate the caught exception stored in the exchange property `Exchange.EXCEPTION_CAUGHT` +as well. For example when using the Splitter EIP with this, then any caught exception during splitting, would be stored +as well, which allows access to this information afterward, for example in an `onCompletion` where the caught exception +can be used to know some error happened during splitting. === Deprecated Components
