This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 17abb262e78 CAMEL-22195: camel-resilience4j - Fix using record and
ignore exceptions (which can be wrapped) and only trigger fallback accordingly.
17abb262e78 is described below
commit 17abb262e786c41252592950c3ace2943aba6b4f
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jun 25 08:11:51 2025 +0200
CAMEL-22195: camel-resilience4j - Fix using record and ignore exceptions
(which can be wrapped) and only trigger fallback accordingly.
---
.../camel/catalog/models/circuitBreaker.json | 3 ++-
.../resilience4j/ResilienceProcessor.java | 7 +++++++
.../ResilienceIgnoreExceptionTest.java | 14 +++++++++++++
.../ResilienceRecordExceptionTest.java | 9 +++++++++
.../ResilienceRecordIgnoreExceptionTest.java | 23 ++++++++++++++++------
.../java/org/apache/camel/ExchangePropertyKey.java | 3 +++
.../apache/camel/spi/CircuitBreakerConstants.java | 3 +++
.../org/apache/camel/model/circuitBreaker.json | 3 ++-
8 files changed, 57 insertions(+), 8 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/circuitBreaker.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/circuitBreaker.json
index 575c3a45fbf..0b0aa850821 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/circuitBreaker.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/circuitBreaker.json
@@ -27,6 +27,7 @@
"CamelResponseFromFallback": { "index": 1, "kind": "exchangeProperty",
"displayName": "Response From Fallback", "label": "producer", "required":
false, "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "description": "Whether the exchange was processed by the
onFallback by the circuit breaker" },
"CamelResponseShortCircuited": { "index": 2, "kind": "exchangeProperty",
"displayName": "Response Short Circuited", "label": "producer", "required":
false, "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "description": "Whether the exchange was short circuited by
the breaker" },
"CamelResponseTimedOut": { "index": 3, "kind": "exchangeProperty",
"displayName": "Response Timed Out", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the exchange timed out during processing by the
circuit breaker" },
- "CamelResponseRejected": { "index": 4, "kind": "exchangeProperty",
"displayName": "Response Rejected", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker rejected processing the
exchange" }
+ "CamelResponseRejected": { "index": 4, "kind": "exchangeProperty",
"displayName": "Response Rejected", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker rejected processing the
exchange" },
+ "CamelResponseIgnored": { "index": 5, "kind": "exchangeProperty",
"displayName": "Response Ignored", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker ignored an exception during
processing" }
}
}
diff --git
a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java
b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java
index c3b0c4d1e5a..8e9bbcf4e4b 100644
---
a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java
+++
b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceProcessor.java
@@ -635,6 +635,10 @@ public class ResilienceProcessor extends
AsyncProcessorSupport
id, throwable);
}
// exception should be ignored
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_FROM_FALLBACK,
false);
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SHORT_CIRCUITED,
false);
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_IGNORED,
true);
exchange.setException(null);
return exchange;
}
@@ -645,6 +649,9 @@ public class ResilienceProcessor extends
AsyncProcessorSupport
id, throwable);
}
// exception is a success
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SUCCESSFUL_EXECUTION,
true);
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_FROM_FALLBACK,
false);
+
exchange.setProperty(ExchangePropertyKey.CIRCUIT_BREAKER_RESPONSE_SHORT_CIRCUITED,
false);
exchange.setException(null);
return exchange;
}
diff --git
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceIgnoreExceptionTest.java
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceIgnoreExceptionTest.java
index 016e23c4b22..04c004fe877 100644
---
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceIgnoreExceptionTest.java
+++
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceIgnoreExceptionTest.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.CircuitBreakerConstants;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
@@ -29,6 +30,7 @@ public class ResilienceIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testHello() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
true);
template.sendBody("direct:start", "Hello World");
MockEndpoint.assertIsSatisfied(context);
}
@@ -36,6 +38,11 @@ public class ResilienceIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testFile() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("file");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_IGNORED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
template.sendBody("direct:start", "file");
MockEndpoint.assertIsSatisfied(context);
}
@@ -43,6 +50,8 @@ public class ResilienceIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testKaboom() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Fallback
message");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
true);
template.sendBody("direct:start", "kaboom");
MockEndpoint.assertIsSatisfied(context);
}
@@ -50,6 +59,11 @@ public class ResilienceIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testIo() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("io");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_IGNORED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
template.sendBody("direct:start", "io");
MockEndpoint.assertIsSatisfied(context);
}
diff --git
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordExceptionTest.java
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordExceptionTest.java
index 72d20cd8058..c4e6046fde2 100644
---
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordExceptionTest.java
+++
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordExceptionTest.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.CircuitBreakerConstants;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
@@ -29,6 +30,7 @@ public class ResilienceRecordExceptionTest extends
CamelTestSupport {
@Test
public void testHello() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
true);
template.sendBody("direct:start", "Hello World");
MockEndpoint.assertIsSatisfied(context);
}
@@ -36,6 +38,9 @@ public class ResilienceRecordExceptionTest extends
CamelTestSupport {
@Test
public void testFile() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Fallback
message");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
true);
template.sendBody("direct:start", "file");
MockEndpoint.assertIsSatisfied(context);
}
@@ -43,6 +48,7 @@ public class ResilienceRecordExceptionTest extends
CamelTestSupport {
@Test
public void testKaboom() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("kaboom");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
true);
template.sendBody("direct:start", "kaboom");
MockEndpoint.assertIsSatisfied(context);
}
@@ -50,6 +56,9 @@ public class ResilienceRecordExceptionTest extends
CamelTestSupport {
@Test
public void testIo() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Fallback
message");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
true);
template.sendBody("direct:start", "io");
MockEndpoint.assertIsSatisfied(context);
}
diff --git
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordIgnoreExceptionTest.java
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordIgnoreExceptionTest.java
index 1517d027f4e..0b1f29d86f2 100644
---
a/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordIgnoreExceptionTest.java
+++
b/components/camel-resilience4j/src/test/java/org/apache/camel/component/resilience4j/ResilienceRecordIgnoreExceptionTest.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.CircuitBreakerConstants;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
@@ -29,6 +30,7 @@ public class ResilienceRecordIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testHello() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
true);
template.sendBody("direct:start", "Hello World");
MockEndpoint.assertIsSatisfied(context);
}
@@ -36,21 +38,30 @@ public class ResilienceRecordIgnoreExceptionTest extends
CamelTestSupport {
@Test
public void testFile() throws Exception {
getMockEndpoint("mock:result").expectedBodiesReceived("file");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_IGNORED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
false);
template.sendBody("direct:start", "file");
MockEndpoint.assertIsSatisfied(context);
}
@Test
- public void testIo() throws Exception {
- getMockEndpoint("mock:result").expectedBodiesReceived("Fallback
message");
- template.sendBody("direct:start", "io");
+ public void testKaboom() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("kaboom");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
true);
+ template.sendBody("direct:start", "kaboom");
MockEndpoint.assertIsSatisfied(context);
}
@Test
- public void testKaboom() throws Exception {
- getMockEndpoint("mock:result").expectedBodiesReceived("kaboom");
- template.sendBody("direct:start", "kaboom");
+ public void testIo() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("Fallback
message");
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SUCCESSFUL_EXECUTION,
false);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED,
true);
+
getMockEndpoint("mock:result").expectedPropertyReceived(CircuitBreakerConstants.RESPONSE_FROM_FALLBACK,
true);
+ template.sendBody("direct:start", "io");
MockEndpoint.assertIsSatisfied(context);
}
diff --git
a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
index b4232869aa1..56e42160d02 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
@@ -40,6 +40,7 @@ public enum ExchangePropertyKey {
CIRCUIT_BREAKER_RESPONSE_SHORT_CIRCUITED(CircuitBreakerConstants.RESPONSE_SHORT_CIRCUITED),
CIRCUIT_BREAKER_RESPONSE_TIMED_OUT(CircuitBreakerConstants.RESPONSE_TIMED_OUT),
CIRCUIT_BREAKER_RESPONSE_REJECTED(CircuitBreakerConstants.RESPONSE_REJECTED),
+ CIRCUIT_BREAKER_RESPONSE_IGNORED(CircuitBreakerConstants.RESPONSE_IGNORED),
CLAIM_CHECK_REPOSITORY(Exchange.CLAIM_CHECK_REPOSITORY),
CORRELATION_ID(Exchange.CORRELATION_ID),
DUPLICATE_MESSAGE(Exchange.DUPLICATE_MESSAGE),
@@ -126,6 +127,8 @@ public enum ExchangePropertyKey {
return CIRCUIT_BREAKER_RESPONSE_TIMED_OUT;
case CircuitBreakerConstants.RESPONSE_REJECTED:
return CIRCUIT_BREAKER_RESPONSE_REJECTED;
+ case CircuitBreakerConstants.RESPONSE_IGNORED:
+ return CIRCUIT_BREAKER_RESPONSE_IGNORED;
case Exchange.CLAIM_CHECK_REPOSITORY:
return CLAIM_CHECK_REPOSITORY;
case Exchange.CORRELATION_ID:
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/CircuitBreakerConstants.java
b/core/camel-api/src/main/java/org/apache/camel/spi/CircuitBreakerConstants.java
index 64371505b80..d4421043a27 100644
---
a/core/camel-api/src/main/java/org/apache/camel/spi/CircuitBreakerConstants.java
+++
b/core/camel-api/src/main/java/org/apache/camel/spi/CircuitBreakerConstants.java
@@ -33,5 +33,8 @@ public interface CircuitBreakerConstants {
@Metadata(label = "circuitBreaker", description = "Whether the circuit
breaker rejected processing the exchange",
javaType = "boolean")
String RESPONSE_REJECTED = "CamelCircuitBreakerResponseRejected";
+ @Metadata(label = "circuitBreaker", description = "Whether the circuit
breaker ignored an exception during processing",
+ javaType = "boolean")
+ String RESPONSE_IGNORED = "CamelCircuitBreakerResponseIgnored";
}
diff --git
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/circuitBreaker.json
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/circuitBreaker.json
index 575c3a45fbf..0b0aa850821 100644
---
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/circuitBreaker.json
+++
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/circuitBreaker.json
@@ -27,6 +27,7 @@
"CamelResponseFromFallback": { "index": 1, "kind": "exchangeProperty",
"displayName": "Response From Fallback", "label": "producer", "required":
false, "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "description": "Whether the exchange was processed by the
onFallback by the circuit breaker" },
"CamelResponseShortCircuited": { "index": 2, "kind": "exchangeProperty",
"displayName": "Response Short Circuited", "label": "producer", "required":
false, "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "description": "Whether the exchange was short circuited by
the breaker" },
"CamelResponseTimedOut": { "index": 3, "kind": "exchangeProperty",
"displayName": "Response Timed Out", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the exchange timed out during processing by the
circuit breaker" },
- "CamelResponseRejected": { "index": 4, "kind": "exchangeProperty",
"displayName": "Response Rejected", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker rejected processing the
exchange" }
+ "CamelResponseRejected": { "index": 4, "kind": "exchangeProperty",
"displayName": "Response Rejected", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker rejected processing the
exchange" },
+ "CamelResponseIgnored": { "index": 5, "kind": "exchangeProperty",
"displayName": "Response Ignored", "label": "producer", "required": false,
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "description": "Whether the circuit breaker ignored an exception during
processing" }
}
}