From 9481876c43b7ce9ec4cde08ab699bfb813270a15 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Fri, 15 Nov 2019 12:06:35 +0100 Subject: [PATCH] CAMEL-14182: Make Hystrix EIP general as Circuit Breaker EIP and allow to plugin other implementations (#3342) CAMEL-14182: Make Hystrix EIP general as Circuit Breaker EIP and allow to plugin other implementations. --- .../processor/HystrixProcessorFactory.java | 8 +- .../hystrix/processor/HystrixReifier.java | 10 +- ...rixDefinition => CircuitBreakerDefinition} | 0 .../HystrixBadRequestExceptionTest.java | 2 +- .../processor/HystrixCircuitOpenTest.java | 38 +++--- .../HystrixHierarchicalConfigTest.java | 20 +-- .../HystrixInheritErrorHandlerTest.java | 2 +- .../processor/HystrixManagementTest.java | 6 +- .../HystrixRouteConfigMaximumSizeTest.java | 18 ++- .../processor/HystrixRouteConfigTest.java | 15 +-- .../processor/HystrixRouteFallbackTest.java | 2 +- .../HystrixRouteFallbackViaNetworkTest.java | 2 +- .../hystrix/processor/HystrixRouteOkTest.java | 2 +- .../hystrix/processor/HystrixTimeoutTest.java | 2 +- .../HystrixTimeoutWithFallbackTest.java | 2 +- ...ingHystrixRouteHierarchicalConfigTest.java | 14 +-- .../BlueprintHystrixRouteFallbackTest.xml | 4 +- .../processor/BlueprintHystrixRouteOkTest.xml | 4 +- ...pringHystrixRouteConfigMaximumSizeTest.xml | 4 +- .../SpringHystrixRouteConfigRefTest.xml | 4 +- .../SpringHystrixRouteConfigTest.xml | 4 +- .../SpringHystrixRouteFallbackTest.xml | 4 +- ...ringHystrixRouteHierarchicalConfigTest.xml | 4 +- .../processor/SpringHystrixRouteOkTest.xml | 4 +- .../impl/engine/DefaultProcessorFactory.java | 13 +- .../src/main/docs/eips/hystrix-eip.adoc | 115 ++++++++++++------ .../src/main/docs/eips/onFallback-eip.adoc | 17 +-- ...ion.java => CircuitBreakerDefinition.java} | 84 +++++-------- .../model/HystrixConfigurationDefinition.java | 6 +- .../camel/model/ProcessorDefinition.java | 20 +-- ...eifier.java => CircuitBreakerReifier.java} | 10 +- .../camel/reifier/ProcessorReifier.java | 16 ++- .../main/MainConfigurationProperties.java | 2 +- .../ROOT/pages/camel-3-migration-guide.adoc | 8 ++ .../modules/ROOT/pages/hystrix-eip.adoc | 115 ++++++++++++------ .../modules/ROOT/pages/onFallback-eip.adoc | 17 +-- .../main/java/sample/camel/ClientRoute.java | 2 +- .../HystrixHierarchicalConfiguration.java | 5 +- .../HystrixHierarchicalConfigurationTest.java | 12 +- .../processor/HystrixMultiConfiguration.java | 9 +- .../HystrixMultiConfigurationTest.java | 1 - .../apache/camel/itest/CamelHystrixTest.xml | 4 +- 42 files changed, 352 insertions(+), 279 deletions(-) rename components/camel-hystrix/src/main/resources/META-INF/services/org/apache/camel/model/{HystrixDefinition => CircuitBreakerDefinition} (100%) rename core/camel-core-engine/src/main/java/org/apache/camel/model/{HystrixDefinition.java => CircuitBreakerDefinition.java} (69%) rename core/camel-core-engine/src/main/java/org/apache/camel/reifier/{HystrixReifier.java => CircuitBreakerReifier.java} (77%) diff --git a/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixProcessorFactory.java b/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixProcessorFactory.java index ffa3ad081a6..0a06abb5617 100644 --- a/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixProcessorFactory.java +++ b/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixProcessorFactory.java @@ -18,20 +18,20 @@ import org.apache.camel.Processor; import org.apache.camel.impl.engine.TypedProcessorFactory; -import org.apache.camel.model.HystrixDefinition; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.spi.RouteContext; /** * To integrate camel-hystrix with the Camel routes using the Hystrix EIP. */ -public class HystrixProcessorFactory extends TypedProcessorFactory { +public class HystrixProcessorFactory extends TypedProcessorFactory { public HystrixProcessorFactory() { - super(HystrixDefinition.class); + super(CircuitBreakerDefinition.class); } @Override - public Processor doCreateProcessor(RouteContext routeContext, HystrixDefinition definition) throws Exception { + public Processor doCreateProcessor(RouteContext routeContext, CircuitBreakerDefinition definition) throws Exception { return new HystrixReifier(definition).createProcessor(routeContext); } diff --git a/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixReifier.java b/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixReifier.java index 3efdef4628b..a2638519445 100644 --- a/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixReifier.java +++ b/components/camel-hystrix/src/main/java/org/apache/camel/component/hystrix/processor/HystrixReifier.java @@ -29,8 +29,8 @@ import org.apache.camel.CamelContext; import org.apache.camel.ExtendedCamelContext; import org.apache.camel.Processor; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.Model; import org.apache.camel.reifier.ProcessorReifier; import org.apache.camel.spi.BeanIntrospection; @@ -41,9 +41,9 @@ import static org.apache.camel.support.CamelContextHelper.lookup; import static org.apache.camel.support.CamelContextHelper.mandatoryLookup; -public class HystrixReifier extends ProcessorReifier { +public class HystrixReifier extends ProcessorReifier { - public HystrixReifier(HystrixDefinition definition) { + public HystrixReifier(CircuitBreakerDefinition definition) { super(definition); } @@ -223,8 +223,8 @@ HystrixConfigurationDefinition buildHystrixConfiguration(CamelContext camelConte // Extract properties from referenced configuration, the one configured // on camel context takes the precedence over those in the registry - if (definition.getHystrixConfigurationRef() != null) { - final String ref = definition.getHystrixConfigurationRef(); + if (definition.getConfigurationRef() != null) { + final String ref = definition.getConfigurationRef(); loadProperties(camelContext, properties, Suppliers.firstNotNull( () -> camelContext.getExtension(Model.class).getHystrixConfiguration(ref), diff --git a/components/camel-hystrix/src/main/resources/META-INF/services/org/apache/camel/model/HystrixDefinition b/components/camel-hystrix/src/main/resources/META-INF/services/org/apache/camel/model/CircuitBreakerDefinition similarity index 100% rename from components/camel-hystrix/src/main/resources/META-INF/services/org/apache/camel/model/HystrixDefinition rename to components/camel-hystrix/src/main/resources/META-INF/services/org/apache/camel/model/CircuitBreakerDefinition diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixBadRequestExceptionTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixBadRequestExceptionTest.java index 786df988b27..fc5abaf9f77 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixBadRequestExceptionTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixBadRequestExceptionTest.java @@ -45,7 +45,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { public void configure() throws Exception { from("direct:start") .to("log:start") - .hystrix() + .circuitBreaker() .throwException(new HystrixBadRequestException("Should not fallback")) .onFallback() .to("mock:fallback") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixCircuitOpenTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixCircuitOpenTest.java index 4c299c8742e..c362f763852 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixCircuitOpenTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixCircuitOpenTest.java @@ -99,26 +99,26 @@ class HystrixExceptionRoute extends RouteBuilder { @Override public void configure() throws Exception { from("direct:start") - .hystrix() - .hystrixConfiguration() - .executionTimeoutInMilliseconds(100) - .circuitBreakerRequestVolumeThreshold(REQUEST_VOLUME_THRESHOLD) - .metricsRollingStatisticalWindowInMilliseconds(1000) - .circuitBreakerSleepWindowInMilliseconds(2000) - .end() - .log("Hystrix processing start: ${threadName}") - .process(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - if (throwException) { - LOG.info("Will throw exception"); - throw new IOException("Route has failed"); - } else { - LOG.info("Will NOT throw exception"); + .circuitBreaker() + .hystrixConfiguration() + .executionTimeoutInMilliseconds(100) + .circuitBreakerRequestVolumeThreshold(REQUEST_VOLUME_THRESHOLD) + .metricsRollingStatisticalWindowInMilliseconds(1000) + .circuitBreakerSleepWindowInMilliseconds(2000) + .end() + .log("Hystrix processing start: ${threadName}") + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + if (throwException) { + LOG.info("Will throw exception"); + throw new IOException("Route has failed"); + } else { + LOG.info("Will NOT throw exception"); + } } - } - }) - .log("Hystrix processing end: ${threadName}") + }) + .log("Hystrix processing end: ${threadName}") .end() .log(HYSTRIX_RESPONSE_SHORT_CIRCUITED + " = ${exchangeProperty." + HYSTRIX_RESPONSE_SHORT_CIRCUITED + "}") .to("mock:result"); diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigTest.java index 5c4c65b8d61..5a73d9c6ac8 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigTest.java @@ -18,8 +18,8 @@ import org.apache.camel.CamelContext; import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.Model; import org.apache.camel.support.SimpleRegistry; import org.junit.Assert; @@ -45,8 +45,8 @@ public void testRegistryConfiguration() throws Exception { registry.bind("ref-hystrix", ref); final HystrixReifier reifier = new HystrixReifier( - new HystrixDefinition() - .hystrixConfiguration("ref-hystrix") + new CircuitBreakerDefinition() + .configuration("ref-hystrix") .hystrixConfiguration() .groupKey("local-conf-group-key") .requestLogEnabled(false) @@ -56,7 +56,7 @@ public void testRegistryConfiguration() throws Exception { Assert.assertEquals("local-conf-group-key", config.getGroupKey()); Assert.assertEquals("global-thread-key", config.getThreadPoolKey()); - Assert.assertEquals(new Integer(5), config.getCorePoolSize()); + Assert.assertEquals(Integer.valueOf(5), config.getCorePoolSize()); } @Test @@ -76,8 +76,8 @@ public void testContextConfiguration() throws Exception { context.getExtension(Model.class).addHystrixConfiguration("ref-hystrix", ref); final HystrixReifier reifier = new HystrixReifier( - new HystrixDefinition() - .hystrixConfiguration("ref-hystrix") + new CircuitBreakerDefinition() + .configuration("ref-hystrix") .hystrixConfiguration() .groupKey("local-conf-group-key") .requestLogEnabled(false) @@ -87,7 +87,7 @@ public void testContextConfiguration() throws Exception { Assert.assertEquals("local-conf-group-key", config.getGroupKey()); Assert.assertEquals("global-thread-key", config.getThreadPoolKey()); - Assert.assertEquals(new Integer(5), config.getCorePoolSize()); + Assert.assertEquals(Integer.valueOf(5), config.getCorePoolSize()); } @Test @@ -116,8 +116,8 @@ public void testMixedConfiguration() throws Exception { registry.bind("ref-hystrix", ref); final HystrixReifier reifier = new HystrixReifier( - new HystrixDefinition() - .hystrixConfiguration("ref-hystrix") + new CircuitBreakerDefinition() + .configuration("ref-hystrix") .hystrixConfiguration() .groupKey("local-conf-group-key") .requestLogEnabled(false) @@ -127,6 +127,6 @@ public void testMixedConfiguration() throws Exception { Assert.assertEquals("local-conf-group-key", config.getGroupKey()); Assert.assertEquals("global-thread-key", config.getThreadPoolKey()); - Assert.assertEquals(new Integer(5), config.getCorePoolSize()); + Assert.assertEquals(Integer.valueOf(5), config.getCorePoolSize()); } } diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixInheritErrorHandlerTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixInheritErrorHandlerTest.java index 561ddc5bb96..f67de0bc7ad 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixInheritErrorHandlerTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixInheritErrorHandlerTest.java @@ -43,7 +43,7 @@ public void configure() throws Exception { from("direct:start") .to("log:start") // turn on Camel's error handler on hystrix so it can do redeliveries - .hystrix().inheritErrorHandler(true) + .circuitBreaker().inheritErrorHandler(true) .to("mock:a") .throwException(new IllegalArgumentException("Forced")) .end() diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixManagementTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixManagementTest.java index f07a33a4ca9..ffd95aa4576 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixManagementTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixManagementTest.java @@ -102,10 +102,10 @@ public void configure() throws Exception { context.addService(stream); from("direct:start").routeId("start") - .hystrix().id("myHystrix") - .to("direct:foo") + .circuitBreaker().id("myHystrix") + .to("direct:foo") .onFallback() - .transform().constant("Fallback message") + .transform().constant("Fallback message") .end() .to("mock:result"); diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigMaximumSizeTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigMaximumSizeTest.java index ccbba7863a4..d1d286a41d6 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigMaximumSizeTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigMaximumSizeTest.java @@ -17,8 +17,8 @@ package org.apache.camel.component.hystrix.processor; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.Test; @@ -41,11 +41,8 @@ public void testGroupKeyAndThreadPoolKeyConfigFlagsDoNotScrapHystrixConfiguratio @Override public void configure() throws Exception { from("direct:foo") - .hystrix() - .hystrixConfiguration().groupKey("test1").metricsHealthSnapshotIntervalInMilliseconds(99999).end() - .groupKey("test2") - // ^^^ should only override the groupKey from the HystrixConfigurationDefinition; - // it should not discard the full HystrixConfigurationDefinition. + .circuitBreaker() + .hystrixConfiguration().groupKey("test2").metricsHealthSnapshotIntervalInMilliseconds(99999).end() .to("log:hello") .end(); @@ -55,9 +52,9 @@ public void configure() throws Exception { rb.configure(); RouteDefinition route = rb.getRouteCollection().getRoutes().get(0); - assertEquals(HystrixDefinition.class, route.getOutputs().get(0).getClass()); + assertEquals(CircuitBreakerDefinition.class, route.getOutputs().get(0).getClass()); - HystrixConfigurationDefinition config = ((HystrixDefinition) route.getOutputs().get(0)).getHystrixConfiguration(); + HystrixConfigurationDefinition config = ((CircuitBreakerDefinition) route.getOutputs().get(0)).getHystrixConfiguration(); assertEquals("test2", config.getGroupKey()); assertEquals(99999, config.getMetricsHealthSnapshotIntervalInMilliseconds().intValue()); } @@ -68,9 +65,10 @@ protected RouteBuilder createRouteBuilder() throws Exception { @Override public void configure() throws Exception { from("direct:start") - .hystrix() + .circuitBreaker() .hystrixConfiguration().groupKey("myCamelApp").requestLogEnabled(false).corePoolSize(5) - .maximumSize(15).allowMaximumSizeToDivergeFromCoreSize(true).end() + .maximumSize(15).allowMaximumSizeToDivergeFromCoreSize(true) + .end() .to("direct:foo") .onFallback() .transform().constant("Fallback message") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigTest.java index 84cdf701fec..1f831ec5351 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteConfigTest.java @@ -17,8 +17,8 @@ package org.apache.camel.component.hystrix.processor; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.Test; @@ -41,11 +41,8 @@ public void testGroupKeyAndThreadPoolKeyConfigFlagsDoNotScrapHystrixConfiguratio @Override public void configure() throws Exception { from("direct:foo") - .hystrix() - .hystrixConfiguration().groupKey("test1").metricsHealthSnapshotIntervalInMilliseconds(99999).end() - .groupKey("test2") - // ^^^ should only override the groupKey from the HystrixConfigurationDefinition; - // it should not discard the full HystrixConfigurationDefinition. + .circuitBreaker() + .hystrixConfiguration().groupKey("test2").metricsHealthSnapshotIntervalInMilliseconds(99999).end() .to("log:hello") .end(); @@ -55,9 +52,9 @@ public void configure() throws Exception { rb.configure(); RouteDefinition route = rb.getRouteCollection().getRoutes().get(0); - assertEquals(HystrixDefinition.class, route.getOutputs().get(0).getClass()); + assertEquals(CircuitBreakerDefinition.class, route.getOutputs().get(0).getClass()); - HystrixConfigurationDefinition config = ((HystrixDefinition) route.getOutputs().get(0)).getHystrixConfiguration(); + HystrixConfigurationDefinition config = ((CircuitBreakerDefinition) route.getOutputs().get(0)).getHystrixConfiguration(); assertEquals("test2", config.getGroupKey()); assertEquals(99999, config.getMetricsHealthSnapshotIntervalInMilliseconds().intValue()); } @@ -69,7 +66,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { @Override public void configure() throws Exception { from("direct:start") - .hystrix() + .circuitBreaker() .hystrixConfiguration().groupKey("myCamelApp").requestLogEnabled(false).corePoolSize(5).end() .to("direct:foo") .onFallback() diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackTest.java index 222542bc18b..ee97733822f 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackTest.java @@ -40,7 +40,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { public void configure() throws Exception { from("direct:start") .to("log:start") - .hystrix() + .circuitBreaker() .throwException(new IllegalArgumentException("Forced")) .onFallback() .transform().constant("Fallback message") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackViaNetworkTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackViaNetworkTest.java index 1901bde45d7..7a5e683dc5d 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackViaNetworkTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteFallbackViaNetworkTest.java @@ -40,7 +40,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { public void configure() throws Exception { from("direct:start") .to("log:start") - .hystrix() + .circuitBreaker() .throwException(new IllegalArgumentException("Forced")) .onFallbackViaNetwork() .transform().constant("Fallback message") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteOkTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteOkTest.java index 61282294c97..e7faf1c0cb7 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteOkTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixRouteOkTest.java @@ -39,7 +39,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { @Override public void configure() throws Exception { from("direct:start") - .hystrix() + .circuitBreaker() .to("direct:foo") .to("log:foo") .onFallback() diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutTest.java index 7e780573aff..ef73ffbeb0f 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutTest.java @@ -68,7 +68,7 @@ protected RoutesBuilder createRouteBuilder() throws Exception { @Override public void configure() throws Exception { from("direct:start") - .hystrix() + .circuitBreaker() // use 2 second timeout .hystrixConfiguration().executionTimeoutInMilliseconds(2000).end() .log("Hystrix processing start: ${threadName}") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutWithFallbackTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutWithFallbackTest.java index dfaae577040..7eabc78b1b8 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutWithFallbackTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/HystrixTimeoutWithFallbackTest.java @@ -46,7 +46,7 @@ protected RoutesBuilder createRouteBuilder() throws Exception { @Override public void configure() throws Exception { from("direct:start") - .hystrix() + .circuitBreaker() // use 2 second timeout .hystrixConfiguration().executionTimeoutInMilliseconds(2000).end() .log("Hystrix processing start: ${threadName}") diff --git a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.java b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.java index 1d0e32a09f9..efbb76c2435 100644 --- a/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.java +++ b/components/camel-hystrix/src/test/java/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.java @@ -16,8 +16,8 @@ */ package org.apache.camel.component.hystrix.processor; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.test.spring.CamelSpringTestSupport; import org.junit.Assert; @@ -36,7 +36,7 @@ protected AbstractApplicationContext createApplicationContext() { @Test public void testHystrix() throws Exception { RouteDefinition routeDefinition = context.getRouteDefinition("hystrix-route"); - HystrixDefinition hystrixDefinition = findHystrixDefinition(routeDefinition); + CircuitBreakerDefinition hystrixDefinition = findCircuitBreakerDefinition(routeDefinition); Assert.assertNotNull(hystrixDefinition); @@ -45,7 +45,7 @@ public void testHystrix() throws Exception { Assert.assertEquals("local-conf-group-key", config.getGroupKey()); Assert.assertEquals("global-thread-key", config.getThreadPoolKey()); - Assert.assertEquals(new Integer(5), config.getCorePoolSize()); + Assert.assertEquals(Integer.valueOf(5), config.getCorePoolSize()); getMockEndpoint("mock:result").expectedBodiesReceived("Bye World"); @@ -58,11 +58,11 @@ public void testHystrix() throws Exception { // Helper // ********************************************** - private HystrixDefinition findHystrixDefinition(RouteDefinition routeDefinition) throws Exception { + private CircuitBreakerDefinition findCircuitBreakerDefinition(RouteDefinition routeDefinition) throws Exception { return routeDefinition.getOutputs().stream() - .filter(HystrixDefinition.class::isInstance) - .map(HystrixDefinition.class::cast) + .filter(CircuitBreakerDefinition.class::isInstance) + .map(CircuitBreakerDefinition.class::cast) .findFirst() - .orElseThrow(() -> new IllegalStateException("Unable to find a HystrixDefinition")); + .orElseThrow(() -> new IllegalStateException("Unable to find a CircuitBreakerDefinition")); } } diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteFallbackTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteFallbackTest.xml index 9833f373de9..9b1b683d7d9 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteFallbackTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteFallbackTest.xml @@ -25,14 +25,14 @@ - + Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteOkTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteOkTest.xml index 160aa8c12e3..4c55703ad10 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteOkTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/BlueprintHystrixRouteOkTest.xml @@ -25,14 +25,14 @@ - + Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigMaximumSizeTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigMaximumSizeTest.xml index 983cac9327e..4d0aa788df0 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigMaximumSizeTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigMaximumSizeTest.xml @@ -26,7 +26,7 @@ - + @@ -34,7 +34,7 @@ Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigRefTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigRefTest.xml index 9e98679e8fc..40cdf25418b 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigRefTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigRefTest.xml @@ -29,14 +29,14 @@ - + Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigTest.xml index 134dad71e09..2c8a9a6a9ed 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteConfigTest.xml @@ -26,7 +26,7 @@ - + @@ -34,7 +34,7 @@ Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteFallbackTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteFallbackTest.xml index a2140430a67..39dbe9737c9 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteFallbackTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteFallbackTest.xml @@ -26,14 +26,14 @@ - + Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.xml index 61c8a10037f..2378bf28333 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteHierarchicalConfigTest.xml @@ -30,7 +30,7 @@ - + @@ -38,7 +38,7 @@ Fallback message - + diff --git a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteOkTest.xml b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteOkTest.xml index f985cca7fae..1e2b139c239 100644 --- a/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteOkTest.xml +++ b/components/camel-hystrix/src/test/resources/org/apache/camel/component/hystrix/processor/SpringHystrixRouteOkTest.xml @@ -26,14 +26,14 @@ - + Fallback message - + diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java index 26d35f0d3c3..d6f07fb574a 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java @@ -40,7 +40,7 @@ * to the name of the {@link ProcessorFactory} the Camel component implement, which gets called for creating * the {@link Processor}s for the EIP. *

- * The Hystrix EIP is such an example where {@link org.apache.camel.model.HystrixDefinition} is implemented + * The Hystrix EIP is such an example where the circuit breaker EIP (CircuitBreakerDefinition) is implemented * in the camel-hystrix component. */ public class DefaultProcessorFactory implements ProcessorFactory { @@ -82,23 +82,22 @@ public Processor createProcessor(RouteContext routeContext, NamedNode definition @Override public Processor createProcessor(CamelContext camelContext, String definitionName, Map args) throws Exception { - // currently only SendDynamicProcessor is supported - SendDynamicProcessor answer = null; if ("SendDynamicProcessor".equals(definitionName)) { String uri = (String) args.get("uri"); Expression expression = (Expression) args.get("expression"); ExchangePattern exchangePattern = (ExchangePattern) args.get("exchangePattern"); - answer = new SendDynamicProcessor(uri, expression); - answer.setCamelContext(camelContext); + SendDynamicProcessor processor = new SendDynamicProcessor(uri, expression); + processor.setCamelContext(camelContext); if (exchangePattern != null) { - answer.setPattern(exchangePattern); + processor.setPattern(exchangePattern); } + return processor; } else if ("UnitOfWorkProducer".equals(definitionName)) { Producer producer = (Producer) args.get("producer"); return new UnitOfWorkProducer(producer); } - return answer; + return null; } } diff --git a/core/camel-core-engine/src/main/docs/eips/hystrix-eip.adoc b/core/camel-core-engine/src/main/docs/eips/hystrix-eip.adoc index f398fd5c3a1..3fa4d1bd761 100644 --- a/core/camel-core-engine/src/main/docs/eips/hystrix-eip.adoc +++ b/core/camel-core-engine/src/main/docs/eips/hystrix-eip.adoc @@ -5,6 +5,9 @@ The Hystrix EIP provides integration with Netflix https://github.com/Netflix/Hystrix[Hystrix] to be used as circuit breaker in the Camel routes. Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable. +NOTE: Camel provides the Circuit Breaker EIP in the route model, which allows to plugin different implementations. +Hystrix is one such implementation. + Maven users will need to add the following dependency to their pom.xml to use this EIP: [source] @@ -29,38 +32,7 @@ The Hystrix EIP supports 2 options which are listed below: |=== // eip options: END -== Camel's Error Handler and Hystrix EIP - -By default the Hystrix EIP handles errors by itself. This means if the circuit breaker is open and -the message fails, then Camel's error handler is not reacting also. -However, you can enable Camels error handler with Hystrix by enabling the `inheritErrorHandler` option, as shown: - -[source,java] ----- -// Camel's error handler that will attempt to redeliver the message 3 times -errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0)); - -from("direct:start") - .to("log:start") - // turn on Camel's error handler on hystrix so it can do redeliveries - .hystrix().inheritErrorHandler(true) - .to("mock:a") - .throwException(new IllegalArgumentException("Forced")) - .end() - .to("log:result") - .to("mock:result"); ----- - -This example is from an unit test, where you can see the Hystrix EIP block has been hardcoded -to always fail by throwning an exception. Because the `inheritErrorHandler` has been enabled, -then Camel's error handler will attempt to call the Hystrix EIP block again. - -That means the `mock:a` endpoint will receive the message again, and a total of 1 + 3 = 4 message -(first time + 3 redeliveries). - -If we turn off the `inheritErrorHandler` option (default) then the Hystrix EIP will only be -executed once because it handled the error itself. - +See xref:hystrixConfiguration-eip.adoc[Hystrix Configuration] for all the configuration options on Hystrix EIP. == Samples @@ -68,7 +40,7 @@ Below is an example route showing an Hystrix endpoint that protects against slow [source,java] ---- from("direct:start") - .hystrix() + .circuitBreaker() .to("http://fooservice.com/slow") .onFallback() .transform().constant("Fallback message") @@ -82,21 +54,94 @@ And in XML DSL: - + Fallback message - + ---- +== Configuring Hystrix + +You can fine-tune Hystrix by the many xref:hystrixConfiguration-eip.adoc[Hystrix Configuration] options. +For example to use a 2 second execution timeout, you can do as follows: + +[source,java] +---- +from("direct:start") + .circuitBreaker() + // use 2 second timeout + .hystrixConfiguration().executionTimeoutInMilliseconds(2000).end() + .log("Hystrix processing start: ${threadName}") + .toD("direct:${body}") + .log("Hystrix processing end: ${threadName}") + .end() + .log("After Hystrix ${body}"); +---- + +And in XML: + +[source,xml] +---- + + + + + + + + + + +---- + +== Fallback + See xref:onFallback-eip.adoc[onFallback]. == Other examples You can find an example with the source code: https://github.com/apache/camel/tree/master/examples/camel-example-hystrix[camel-example-hystrix]. + +== Using Hystrix with Spring Boot + +See the xref:hystrix-component.adoc[Hystrix Component]. + +== Camel's Error Handler and Hystrix EIP + +By default the Hystrix EIP handles errors by itself. This means if the circuit breaker is open and +the message fails, then Camel's error handler is not reacting also. +However, you can enable Camels error handler with Hystrix by enabling the `inheritErrorHandler` option, as shown: + +[source,java] +---- +// Camel's error handler that will attempt to redeliver the message 3 times +errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0)); + +from("direct:start") + .to("log:start") + // turn on Camel's error handler on hystrix so it can do redeliveries + .circuitBreaker().inheritErrorHandler(true) + .to("mock:a") + .throwException(new IllegalArgumentException("Forced")) + .end() + .to("log:result") + .to("mock:result"); +---- + +This example is from an unit test, where you can see the Hystrix EIP block has been hardcoded +to always fail by throwing an exception. Because the `inheritErrorHandler` has been enabled, +then Camel's error handler will attempt to call the Hystrix EIP block again. + +That means the `mock:a` endpoint will receive the message again, and a total of 1 + 3 = 4 message +(first time + 3 redeliveries). + +If we turn off the `inheritErrorHandler` option (default) then the Hystrix EIP will only be +executed once because it handled the error itself. + diff --git a/core/camel-core-engine/src/main/docs/eips/onFallback-eip.adoc b/core/camel-core-engine/src/main/docs/eips/onFallback-eip.adoc index 8a282d78490..bc083e47a6d 100644 --- a/core/camel-core-engine/src/main/docs/eips/onFallback-eip.adoc +++ b/core/camel-core-engine/src/main/docs/eips/onFallback-eip.adoc @@ -1,9 +1,9 @@ [[onFallback-eip]] = On Fallback EIP -If you are using *onFallback* then that is intended to be local processing only where you can do a message transformation or call a bean or something as the fallback. If you need to call an external service over the network then you should use *onFallbackViaNetwork* that runs in another independent *HystrixCommand* that uses its own thread pool to not exhaust the first command. -Configuring Hystrix Example -Hystrix has many options as listed in the table above. For example to set a higher timeout to *5* seconds, and also let the circuit breaker wait *10* seconds before attempting a request again when the state was tripped to be open. +If you are using *onFallback* then that is intended to be local processing only where you can do a message transformation or call a bean or something as the fallback. + +If you need to call an external service over the network then you should use *onFallbackViaNetwork* that runs in another independent *HystrixCommand* that uses its own thread pool to not exhaust the first command. == Options @@ -17,10 +17,13 @@ The On Fallback EIP supports 1 options which are listed below: |=== // eip options: END +Hystrix has many options as listed in xref:hystrixConfiguration-eip.adoc[Hystrix Configuration]. +For example to set a higher timeout to *5* seconds, and also let the circuit breaker wait *10* seconds before attempting a request again when the state was tripped to be open. + [source,java] ---- from("direct:start") - .hystrix() + .circuitBreaker() .hystrixConfiguration() .executionTimeoutInMilliseconds(5000) .circuitBreakerSleepWindowInMilliseconds(10000) @@ -38,7 +41,7 @@ And in XML DSL: - + @@ -47,7 +50,7 @@ And in XML DSL: Fallback message - + @@ -66,7 +69,7 @@ You can also configure Hystrix globally and then refer to that configuration: - + diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java similarity index 69% rename from core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixDefinition.java rename to core/camel-core-engine/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java index 4087543e3e3..c16e1b06189 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixDefinition.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/CircuitBreakerDefinition.java @@ -1,13 +1,13 @@ -/* +/** * 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 - * + *

+ * 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. @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -30,39 +29,36 @@ import org.apache.camel.spi.Metadata; -/** - * Hystrix Circuit Breaker EIP - */ @Metadata(label = "eip,routing,circuitbreaker") -@XmlRootElement(name = "hystrix") +@XmlRootElement(name = "circuitBreaker") @XmlAccessorType(XmlAccessType.FIELD) -public class HystrixDefinition extends ProcessorDefinition implements OutputNode { +public class CircuitBreakerDefinition extends ProcessorDefinition implements OutputNode { @XmlElement private HystrixConfigurationDefinition hystrixConfiguration; + @XmlAttribute + private String configurationRef; @XmlElementRef private List> outputs = new ArrayList<>(); @XmlTransient private OnFallbackDefinition onFallback; - @XmlAttribute - private String hystrixConfigurationRef; - public HystrixDefinition() { + public CircuitBreakerDefinition() { } @Override public String toString() { - return "Hystrix[" + getOutputs() + "]"; + return "CircuitBreaker[" + getOutputs() + "]"; } @Override public String getShortName() { - return "hystrix"; + return "circuitBreaker"; } @Override public String getLabel() { - return "hystrix"; + return "circuitBreaker"; } @Override @@ -126,15 +122,16 @@ public void setHystrixConfiguration(HystrixConfigurationDefinition hystrixConfig this.hystrixConfiguration = hystrixConfiguration; } - public String getHystrixConfigurationRef() { - return hystrixConfigurationRef; + public String getConfigurationRef() { + return configurationRef; } /** - * Refers to a Hystrix configuration to use for configuring the Hystrix EIP. + * Refers to a circuit breaker configuration (such as hystrix, resillient4j, or microprofile-fault-tolerance) + * to use for configuring the circuit breaker EIP. */ - public void setHystrixConfigurationRef(String hystrixConfigurationRef) { - this.hystrixConfigurationRef = hystrixConfigurationRef; + public void setConfigurationRef(String configurationRef) { + this.configurationRef = configurationRef; } public OnFallbackDefinition getOnFallback() { @@ -149,26 +146,10 @@ public void setOnFallback(OnFallbackDefinition onFallback) { // ------------------------------------------------------------------------- /** - * Sets the group key to use. The default value is CamelHystrix. - */ - public HystrixDefinition groupKey(String groupKey) { - hystrixConfiguration().groupKey(groupKey); - return this; - } - - /** - * Sets the thread pool key to use. The default value is CamelHystrix. - */ - public HystrixDefinition threadPoolKey(String threadPoolKey) { - hystrixConfiguration().threadPoolKey(threadPoolKey); - return this; - } - - /** - * Configures the Hystrix EIP + * Configures the circuit breaker to use Hystrix. *

* Use end when configuration is complete, to return back to the - * Hystrix EIP. + * Circuit Breaker EIP. */ public HystrixConfigurationDefinition hystrixConfiguration() { hystrixConfiguration = hystrixConfiguration == null ? new HystrixConfigurationDefinition(this) : hystrixConfiguration; @@ -176,46 +157,41 @@ public HystrixConfigurationDefinition hystrixConfiguration() { } /** - * Configures the Hystrix EIP using the given configuration + * Configures the circuit breaker to use Hystrix with the given configuration. */ - public HystrixDefinition hystrixConfiguration(HystrixConfigurationDefinition configuration) { + public CircuitBreakerDefinition hystrixConfiguration(HystrixConfigurationDefinition configuration) { hystrixConfiguration = configuration; return this; } /** - * Refers to a Hystrix configuration to use for configuring the Hystrix EIP. + * Refers to a configuration to use for configuring the circuit breaker. */ - public HystrixDefinition hystrixConfiguration(String ref) { - hystrixConfigurationRef = ref; + public CircuitBreakerDefinition configuration(String ref) { + configurationRef = ref; return this; } /** - * The Hystrix fallback route path to execute that does not go over + * The fallback route path to execute that does not go over * the network. *

* This should be a static or cached result that can immediately be returned * upon failure. If the fallback requires network connection then use * {@link #onFallbackViaNetwork()}. */ - public HystrixDefinition onFallback() { + public CircuitBreakerDefinition onFallback() { onFallback = new OnFallbackDefinition(); onFallback.setParent(this); return this; } /** - * The Hystrix fallback route path to execute that will go over the network. + * The fallback route path to execute that will go over the network. *

- * If the fallback will go over the network it is another possible point of - * failure and so it also needs to be wrapped by a HystrixCommand. It is - * important to execute the fallback command on a separate thread-pool, - * otherwise if the main command were to become latent and fill the - * thread-pool this would prevent the fallback from running if the two - * commands share the same pool. + * If the fallback will go over the network it is another possible point of failure. */ - public HystrixDefinition onFallbackViaNetwork() { + public CircuitBreakerDefinition onFallbackViaNetwork() { onFallback = new OnFallbackDefinition(); onFallback.setFallbackViaNetwork(true); onFallback.setParent(this); diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java index a3ff0589855..75b9f7d0d1d 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/HystrixConfigurationDefinition.java @@ -35,12 +35,12 @@ public class HystrixConfigurationDefinition extends HystrixConfigurationCommon { public static final String DEFAULT_GROUP_KEY = "CamelHystrix"; @XmlTransient - private HystrixDefinition parent; + private CircuitBreakerDefinition parent; public HystrixConfigurationDefinition() { } - public HystrixConfigurationDefinition(HystrixDefinition parent) { + public HystrixConfigurationDefinition(CircuitBreakerDefinition parent) { this.parent = parent; } @@ -375,7 +375,7 @@ public HystrixConfigurationDefinition allowMaximumSizeToDivergeFromCoreSize(Bool /** * End of configuration. */ - public HystrixDefinition end() { + public CircuitBreakerDefinition end() { return parent; } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/ProcessorDefinition.java index 03fa64400a5..d28282f2837 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/model/ProcessorDefinition.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/ProcessorDefinition.java @@ -1188,22 +1188,22 @@ public TryDefinition endDoTry() { } /** - * Ends the current block and returns back to the {@link HystrixDefinition - * hystrix()} DSL. + * Ends the current block and returns back to the {@link CircuitBreakerDefinition + * circuitBreaker()} DSL. * * @return the builder */ - public HystrixDefinition endHystrix() { + public CircuitBreakerDefinition endCircuitBreaker() { ProcessorDefinition def = this; // are we already a try? - if (def instanceof HystrixDefinition) { - return (HystrixDefinition)def; + if (def instanceof CircuitBreakerDefinition) { + return (CircuitBreakerDefinition)def; } // okay end this and get back to the try def = end(); - return (HystrixDefinition)def; + return (CircuitBreakerDefinition)def; } /** @@ -1351,14 +1351,14 @@ public ExpressionClause validate() { } /** - * Creates a Hystrix Circuit Breaker EIP. + * Creates a Circuit Breaker EIP. *

- * This requires having camel-hystrix on the classpath. + * This requires having an implementation on the classpath such as camel-hystrix, or camel-microprofile-fault-tolerance. * * @return the builder */ - public HystrixDefinition hystrix() { - HystrixDefinition answer = new HystrixDefinition(); + public CircuitBreakerDefinition circuitBreaker() { + CircuitBreakerDefinition answer = new CircuitBreakerDefinition(); addOutput(answer); return answer; } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/HystrixReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/CircuitBreakerReifier.java similarity index 77% rename from core/camel-core-engine/src/main/java/org/apache/camel/reifier/HystrixReifier.java rename to core/camel-core-engine/src/main/java/org/apache/camel/reifier/CircuitBreakerReifier.java index 464f0279a27..830b0e7136e 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/HystrixReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/CircuitBreakerReifier.java @@ -17,19 +17,19 @@ package org.apache.camel.reifier; import org.apache.camel.Processor; -import org.apache.camel.model.HystrixDefinition; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.spi.RouteContext; -public class HystrixReifier extends ProcessorReifier { +public class CircuitBreakerReifier extends ProcessorReifier { - public HystrixReifier(ProcessorDefinition definition) { - super(HystrixDefinition.class.cast(definition)); + public CircuitBreakerReifier(ProcessorDefinition definition) { + super(CircuitBreakerDefinition.class.cast(definition)); } @Override public Processor createProcessor(RouteContext routeContext) throws Exception { - throw new IllegalStateException("Cannot find camel-hystrix on the classpath."); + throw new IllegalStateException("Cannot find camel-hystrix or camel-microprofile-fault-tolerance on the classpath."); } } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ProcessorReifier.java index 8fc73825d1c..3c327efa2d5 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ProcessorReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ProcessorReifier.java @@ -31,6 +31,7 @@ import org.apache.camel.model.BeanDefinition; import org.apache.camel.model.CatchDefinition; import org.apache.camel.model.ChoiceDefinition; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.ClaimCheckDefinition; import org.apache.camel.model.ConvertBodyDefinition; import org.apache.camel.model.DelayDefinition; @@ -39,7 +40,6 @@ import org.apache.camel.model.ExpressionNode; import org.apache.camel.model.FilterDefinition; import org.apache.camel.model.FinallyDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.IdempotentConsumerDefinition; import org.apache.camel.model.InOnlyDefinition; import org.apache.camel.model.InOutDefinition; @@ -120,6 +120,7 @@ public abstract class ProcessorReifier> { map.put(BeanDefinition.class, BeanReifier::new); map.put(CatchDefinition.class, CatchReifier::new); map.put(ChoiceDefinition.class, ChoiceReifier::new); + map.put(CircuitBreakerDefinition.class, CircuitBreakerReifier::new); map.put(ClaimCheckDefinition.class, ClaimCheckReifier::new); map.put(ConvertBodyDefinition.class, ConvertBodyReifier::new); map.put(DelayDefinition.class, DelayReifier::new); @@ -127,7 +128,6 @@ public abstract class ProcessorReifier> { map.put(EnrichDefinition.class, EnrichReifier::new); map.put(FilterDefinition.class, FilterReifier::new); map.put(FinallyDefinition.class, FinallyReifier::new); - map.put(HystrixDefinition.class, HystrixReifier::new); map.put(IdempotentConsumerDefinition.class, IdempotentConsumerReifier::new); map.put(InOnlyDefinition.class, SendReifier::new); map.put(InOutDefinition.class, SendReifier::new); @@ -351,16 +351,14 @@ protected Channel wrapChannel(RouteContext routeContext, Processor processor, Pr log.trace("{} is part of OnException so no error handler is applied", definition); // do not use error handler for onExceptions blocks as it will // handle errors itself - } else if (definition instanceof HystrixDefinition || ProcessorDefinitionHelper.isParentOfType(HystrixDefinition.class, definition, true)) { - // do not use error handler for hystrix as it offers circuit - // breaking with fallback for its outputs - // however if inherit error handler is enabled, we need to wrap an - // error handler on the hystrix parent + } else if (definition instanceof CircuitBreakerDefinition || ProcessorDefinitionHelper.isParentOfType(CircuitBreakerDefinition.class, definition, true)) { + // do not use error handler for circuit breaker + // however if inherit error handler is enabled, we need to wrap an error handler on the parent if (inheritErrorHandler != null && inheritErrorHandler && child == null) { - // only wrap the parent (not the children of the hystrix) + // only wrap the parent (not the children of the circuit breaker) wrap = true; } else { - log.trace("{} is part of HystrixCircuitBreaker so no error handler is applied", definition); + log.trace("{} is part of CircuitBreaker so no error handler is applied", definition); } } else if (definition instanceof MulticastDefinition) { // do not use error handler for multicast as it offers fine grained diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java index 02de4952da5..433b18d4aec 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java @@ -41,7 +41,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< // -------------------------------------------------------------- /** - * To configure Hystrix EIP + * To configure Circuit Breaker EIP with Hystrix */ public HystrixConfigurationProperties hystrix() { return hystrixConfigurationProperties; diff --git a/docs/user-manual/modules/ROOT/pages/camel-3-migration-guide.adoc b/docs/user-manual/modules/ROOT/pages/camel-3-migration-guide.adoc index 257bd913057..cb76c1220f8 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-3-migration-guide.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-3-migration-guide.adoc @@ -161,6 +161,14 @@ The `rxjava2` component has been renamed to `rxjava`, and it's corresponding com We have also renamed `camel-jetty9` to `camel-jetty`. The supported scheme is now `jetty`. +=== Hystrix EIP + +The Hystrix EIP has been generalized as circuit breaker to allow to plugin other implementations. + +In the Java DSL you need to migrate from `.hystrix()` to `.circuitBreaker()`. +And in XML DSL `` should be ``. + + === Using endpoint options with consumer. prefix Endpoints with `consumer.` prefix such as `consumer.delay=5000` are no longer supported (deprecated in latest Camel 2.x) and you should just use the option without the `consumer.` prefix, eg `delay=5000`. diff --git a/docs/user-manual/modules/ROOT/pages/hystrix-eip.adoc b/docs/user-manual/modules/ROOT/pages/hystrix-eip.adoc index cb3fe1869db..2cd1eb585bd 100644 --- a/docs/user-manual/modules/ROOT/pages/hystrix-eip.adoc +++ b/docs/user-manual/modules/ROOT/pages/hystrix-eip.adoc @@ -6,6 +6,9 @@ The Hystrix EIP provides integration with Netflix https://github.com/Netflix/Hystrix[Hystrix] to be used as circuit breaker in the Camel routes. Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable. +NOTE: Camel provides the Circuit Breaker EIP in the route model, which allows to plugin different implementations. +Hystrix is one such implementation. + Maven users will need to add the following dependency to their pom.xml to use this EIP: [source] @@ -30,38 +33,7 @@ The Hystrix EIP supports 2 options which are listed below: |=== // eip options: END -== Camel's Error Handler and Hystrix EIP - -By default the Hystrix EIP handles errors by itself. This means if the circuit breaker is open and -the message fails, then Camel's error handler is not reacting also. -However, you can enable Camels error handler with Hystrix by enabling the `inheritErrorHandler` option, as shown: - -[source,java] ----- -// Camel's error handler that will attempt to redeliver the message 3 times -errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0)); - -from("direct:start") - .to("log:start") - // turn on Camel's error handler on hystrix so it can do redeliveries - .hystrix().inheritErrorHandler(true) - .to("mock:a") - .throwException(new IllegalArgumentException("Forced")) - .end() - .to("log:result") - .to("mock:result"); ----- - -This example is from an unit test, where you can see the Hystrix EIP block has been hardcoded -to always fail by throwning an exception. Because the `inheritErrorHandler` has been enabled, -then Camel's error handler will attempt to call the Hystrix EIP block again. - -That means the `mock:a` endpoint will receive the message again, and a total of 1 + 3 = 4 message -(first time + 3 redeliveries). - -If we turn off the `inheritErrorHandler` option (default) then the Hystrix EIP will only be -executed once because it handled the error itself. - +See xref:hystrixConfiguration-eip.adoc[Hystrix Configuration] for all the configuration options on Hystrix EIP. == Samples @@ -69,7 +41,7 @@ Below is an example route showing an Hystrix endpoint that protects against slow [source,java] ---- from("direct:start") - .hystrix() + .circuitBreaker() .to("http://fooservice.com/slow") .onFallback() .transform().constant("Fallback message") @@ -83,21 +55,94 @@ And in XML DSL: - + Fallback message - + ---- +== Configuring Hystrix + +You can fine-tune Hystrix by the many xref:hystrixConfiguration-eip.adoc[Hystrix Configuration] options. +For example to use a 2 second execution timeout, you can do as follows: + +[source,java] +---- +from("direct:start") + .circuitBreaker() + // use 2 second timeout + .hystrixConfiguration().executionTimeoutInMilliseconds(2000).end() + .log("Hystrix processing start: ${threadName}") + .toD("direct:${body}") + .log("Hystrix processing end: ${threadName}") + .end() + .log("After Hystrix ${body}"); +---- + +And in XML: + +[source,xml] +---- + + + + + + + + + + +---- + +== Fallback + See xref:onFallback-eip.adoc[onFallback]. == Other examples You can find an example with the source code: https://github.com/apache/camel/tree/master/examples/camel-example-hystrix[camel-example-hystrix]. + +== Using Hystrix with Spring Boot + +See the xref:hystrix-component.adoc[Hystrix Component]. + +== Camel's Error Handler and Hystrix EIP + +By default the Hystrix EIP handles errors by itself. This means if the circuit breaker is open and +the message fails, then Camel's error handler is not reacting also. +However, you can enable Camels error handler with Hystrix by enabling the `inheritErrorHandler` option, as shown: + +[source,java] +---- +// Camel's error handler that will attempt to redeliver the message 3 times +errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0)); + +from("direct:start") + .to("log:start") + // turn on Camel's error handler on hystrix so it can do redeliveries + .circuitBreaker().inheritErrorHandler(true) + .to("mock:a") + .throwException(new IllegalArgumentException("Forced")) + .end() + .to("log:result") + .to("mock:result"); +---- + +This example is from an unit test, where you can see the Hystrix EIP block has been hardcoded +to always fail by throwing an exception. Because the `inheritErrorHandler` has been enabled, +then Camel's error handler will attempt to call the Hystrix EIP block again. + +That means the `mock:a` endpoint will receive the message again, and a total of 1 + 3 = 4 message +(first time + 3 redeliveries). + +If we turn off the `inheritErrorHandler` option (default) then the Hystrix EIP will only be +executed once because it handled the error itself. + diff --git a/docs/user-manual/modules/ROOT/pages/onFallback-eip.adoc b/docs/user-manual/modules/ROOT/pages/onFallback-eip.adoc index 94b7d21f78e..54264adab77 100644 --- a/docs/user-manual/modules/ROOT/pages/onFallback-eip.adoc +++ b/docs/user-manual/modules/ROOT/pages/onFallback-eip.adoc @@ -2,9 +2,9 @@ = On Fallback EIP :page-source: core/camel-core-engine/src/main/docs/eips/onFallback-eip.adoc -If you are using *onFallback* then that is intended to be local processing only where you can do a message transformation or call a bean or something as the fallback. If you need to call an external service over the network then you should use *onFallbackViaNetwork* that runs in another independent *HystrixCommand* that uses its own thread pool to not exhaust the first command. -Configuring Hystrix Example -Hystrix has many options as listed in the table above. For example to set a higher timeout to *5* seconds, and also let the circuit breaker wait *10* seconds before attempting a request again when the state was tripped to be open. +If you are using *onFallback* then that is intended to be local processing only where you can do a message transformation or call a bean or something as the fallback. + +If you need to call an external service over the network then you should use *onFallbackViaNetwork* that runs in another independent *HystrixCommand* that uses its own thread pool to not exhaust the first command. == Options @@ -18,10 +18,13 @@ The On Fallback EIP supports 1 options which are listed below: |=== // eip options: END +Hystrix has many options as listed in xref:hystrixConfiguration-eip.adoc[Hystrix Configuration]. +For example to set a higher timeout to *5* seconds, and also let the circuit breaker wait *10* seconds before attempting a request again when the state was tripped to be open. + [source,java] ---- from("direct:start") - .hystrix() + .circuitBreaker() .hystrixConfiguration() .executionTimeoutInMilliseconds(5000) .circuitBreakerSleepWindowInMilliseconds(10000) @@ -39,7 +42,7 @@ And in XML DSL: - + @@ -48,7 +51,7 @@ And in XML DSL: Fallback message - + @@ -67,7 +70,7 @@ You can also configure Hystrix globally and then refer to that configuration: - + diff --git a/examples/camel-example-hystrix/client/src/main/java/sample/camel/ClientRoute.java b/examples/camel-example-hystrix/client/src/main/java/sample/camel/ClientRoute.java index 18013b34e73..4f72e301a70 100644 --- a/examples/camel-example-hystrix/client/src/main/java/sample/camel/ClientRoute.java +++ b/examples/camel-example-hystrix/client/src/main/java/sample/camel/ClientRoute.java @@ -28,7 +28,7 @@ public void configure() { from("timer:trigger?period=500").streamCaching() .bean("counterBean") .log(" Client request: ${body}") - .hystrix() + .circuitBreaker() // see application.properties how hystrix is configured .to("http://localhost:9090/service1") //.onFallback() diff --git a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfiguration.java b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfiguration.java index 1d44fc284c5..aa62b272ed1 100644 --- a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfiguration.java +++ b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfiguration.java @@ -21,6 +21,7 @@ import org.springframework.context.annotation.Bean; public class HystrixHierarchicalConfiguration { + @Bean(name = "ref-hystrix") public HystrixConfigurationDefinition hystrixConfiguration() { return new HystrixConfigurationDefinition() @@ -35,8 +36,8 @@ public RouteBuilder routeBuilder() { public void configure() throws Exception { from("direct:start") .routeId("hystrix-route") - .hystrix() - .hystrixConfiguration("ref-hystrix") + .circuitBreaker() + .configuration("ref-hystrix") .hystrixConfiguration() .groupKey("local-conf-group-key") .end() diff --git a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigurationTest.java b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigurationTest.java index b7171e3ddc2..8adf5eade8f 100644 --- a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigurationTest.java +++ b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixHierarchicalConfigurationTest.java @@ -17,8 +17,8 @@ package org.apache.camel.component.hystrix.processor; import org.apache.camel.CamelContext; +import org.apache.camel.model.CircuitBreakerDefinition; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.apache.camel.model.Model; import org.apache.camel.model.RouteDefinition; import org.junit.Assert; @@ -52,7 +52,7 @@ public class HystrixHierarchicalConfigurationTest { @Test public void testConfiguration() throws Exception { RouteDefinition routeDefinition = camelContext.getExtension(Model.class).getRouteDefinition("hystrix-route"); - HystrixDefinition hystrixDefinition = findHystrixDefinition(routeDefinition); + CircuitBreakerDefinition hystrixDefinition = findCircuitBreaker(routeDefinition); Assert.assertNotNull(hystrixDefinition); @@ -68,12 +68,12 @@ public void testConfiguration() throws Exception { // Helper // ********************************************** - private HystrixDefinition findHystrixDefinition(RouteDefinition routeDefinition) throws Exception { + private CircuitBreakerDefinition findCircuitBreaker(RouteDefinition routeDefinition) throws Exception { return routeDefinition.getOutputs().stream() - .filter(HystrixDefinition.class::isInstance) - .map(HystrixDefinition.class::cast) + .filter(CircuitBreakerDefinition.class::isInstance) + .map(CircuitBreakerDefinition.class::cast) .findFirst() - .orElseThrow(() -> new IllegalStateException("Unable to find a HystrixDefinition")); + .orElseThrow(() -> new IllegalStateException("Unable to find a CircuitBreakerDefinition")); } } diff --git a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfiguration.java b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfiguration.java index e61c48fd3fc..ffce8a99403 100644 --- a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfiguration.java +++ b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfiguration.java @@ -21,6 +21,7 @@ import org.springframework.context.annotation.Bean; public class HystrixMultiConfiguration { + @Bean(name = "bean-conf") public HystrixConfigurationDefinition hystrixBeanConfiguration() { return new HystrixConfigurationDefinition() @@ -34,16 +35,16 @@ public RouteBuilder routeBuilder() { public void configure() throws Exception { from("direct:start-1") .routeId("hystrix-route-1") - .hystrix() - .hystrixConfiguration("conf-1") + .circuitBreaker() + .configuration("conf-1") .to("direct:foo") .onFallback() .transform().constant("Fallback message") .end(); from("direct:start-2") .routeId("hystrix-route-2") - .hystrix() - .hystrixConfiguration("conf-2") + .circuitBreaker() + .configuration("conf-2") .to("direct:foo") .onFallback() .transform().constant("Fallback message") diff --git a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfigurationTest.java b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfigurationTest.java index 36dd08fb534..9e736fd923b 100644 --- a/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfigurationTest.java +++ b/platforms/spring-boot/components-starter/camel-hystrix-starter/src/test/java/org/apache/camel/component/hystrix/processor/HystrixMultiConfigurationTest.java @@ -24,7 +24,6 @@ import org.apache.camel.Processor; import org.apache.camel.Route; import org.apache.camel.model.HystrixConfigurationDefinition; -import org.apache.camel.model.HystrixDefinition; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml index 8f12bace3e5..e31b4723585 100644 --- a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml +++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml @@ -26,14 +26,14 @@ - + Fallback message - +