diff --git a/hystrix/pom.xml b/hystrix/pom.xml
index 0ec5fa0411..381adfbcd5 100644
--- a/hystrix/pom.xml
+++ b/hystrix/pom.xml
@@ -6,9 +6,15 @@
com.baeldung
hystrix
1.0
-
hystrix
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.0.RELEASE
+
+
+
@@ -32,12 +38,35 @@
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
com.netflix.hystrix
hystrix-core
${hystrix-core.version}
+
+ com.netflix.hystrix
+ hystrix-metrics-event-stream
+ 1.3.16
+
+
+
+
+
com.netflix.rxjava
rxjava-core
@@ -62,6 +91,10 @@
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java b/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
new file mode 100644
index 0000000000..8b11ac99c3
--- /dev/null
+++ b/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
@@ -0,0 +1,20 @@
+package com.baeldung.hystrix;
+
+import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class AppConfig {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AppConfig.class, args);
+ }
+
+ @Bean
+ public ServletRegistrationBean adminServletRegistrationBean() {
+ return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
+ }
+}
diff --git a/hystrix/src/test/java/com/baeldung/hystrix/CommandHelloWorld.java b/hystrix/src/main/java/com/baeldung/hystrix/CommandHelloWorld.java
similarity index 100%
rename from hystrix/src/test/java/com/baeldung/hystrix/CommandHelloWorld.java
rename to hystrix/src/main/java/com/baeldung/hystrix/CommandHelloWorld.java
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java
new file mode 100644
index 0000000000..c2e4af8edb
--- /dev/null
+++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java
@@ -0,0 +1,81 @@
+package com.baeldung.hystrix;
+
+import com.netflix.hystrix.*;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Component
+@Aspect
+public class HystrixAspect {
+
+ private HystrixCommand.Setter config;
+ private HystrixCommandProperties.Setter commandProperties;
+ private HystrixThreadPoolProperties.Setter threadPoolProperties;
+
+ @Around("@annotation(com.baeldung.hystrix.HystrixCircuitBreaker)")
+ public Object circuitBreakerAround(final ProceedingJoinPoint aJoinPoint) {
+ return new RemoteServiceCommand(config, aJoinPoint).execute();
+ }
+
+ @PostConstruct
+ private void setup() {
+ this.config = HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey));
+ this.config = config.andCommandKey(HystrixCommandKey.Factory.asKey(key));
+
+ this.commandProperties = HystrixCommandProperties.Setter();
+ this.commandProperties.withExecutionTimeoutInMilliseconds(executionTimeout);
+ this.commandProperties.withCircuitBreakerSleepWindowInMilliseconds(sleepWindow);
+
+ this.threadPoolProperties= HystrixThreadPoolProperties.Setter();
+ this.threadPoolProperties.withMaxQueueSize(maxThreadCount).withCoreSize(coreThreadCount).withMaxQueueSize(queueCount);
+
+ this.config.andCommandPropertiesDefaults(commandProperties);
+ this.config.andThreadPoolPropertiesDefaults(threadPoolProperties);
+ }
+
+ private static class RemoteServiceCommand extends HystrixCommand {
+
+ private final ProceedingJoinPoint joinPoint;
+
+ RemoteServiceCommand(final Setter config, final ProceedingJoinPoint joinPoint) {
+ super(config);
+ this.joinPoint = joinPoint;
+ }
+
+ @Override
+ protected String run() throws Exception {
+ try {
+ return (String) joinPoint.proceed();
+ } catch (final Throwable th) {
+ throw new Exception(th);
+ }
+
+ }
+ }
+
+ @Value("${remoteservice.command.execution.timeout}")
+ private int executionTimeout;
+
+ @Value("${remoteservice.command.sleepwindow}")
+ private int sleepWindow;
+
+ @Value("${remoteservice.command.threadpool.maxsize}")
+ private int maxThreadCount;
+
+ @Value("${remoteservice.command.threadpool.coresize}")
+ private int coreThreadCount;
+
+ @Value("${remoteservice.command.task.queue.size}")
+ private int queueCount;
+
+ @Value("${remoteservice.command.group.key}")
+ private String groupKey;
+
+ @Value("${remoteservice.command.key}")
+ private String key;
+}
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java
new file mode 100644
index 0000000000..e7c0694a7b
--- /dev/null
+++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java
@@ -0,0 +1,11 @@
+package com.baeldung.hystrix;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface HystrixCircuitBreaker {
+}
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java
new file mode 100644
index 0000000000..a8ca0adef2
--- /dev/null
+++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java
@@ -0,0 +1,17 @@
+package com.baeldung.hystrix;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HystrixController {
+
+ @Autowired
+ private SpringExistingClient client;
+
+ @RequestMapping("/")
+ public String index() throws InterruptedException{
+ return client.invokeRemoteService();
+ }
+}
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceSimulator.java b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceSimulator.java
deleted file mode 100644
index 3efd579d84..0000000000
--- a/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceSimulator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.baeldung.hystrix;
-
-
-public class RemoteServiceSimulator {
-
- public String checkSomething(final long timeout) throws InterruptedException {
-
- System.out.print(String.format("Waiting %sms. ", timeout));
-
- // to simulate a real world delay in processing.
- Thread.sleep(timeout);
-
- return "Done waiting.";
- }
-}
diff --git a/hystrix/src/test/java/com/baeldung/hystrix/RemoteServiceTestCommand.java b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestCommand.java
similarity index 100%
rename from hystrix/src/test/java/com/baeldung/hystrix/RemoteServiceTestCommand.java
rename to hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestCommand.java
diff --git a/hystrix/src/test/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java
similarity index 86%
rename from hystrix/src/test/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java
rename to hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java
index 54c626a67a..d302166ea8 100644
--- a/hystrix/src/test/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java
+++ b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java
@@ -1,7 +1,7 @@
package com.baeldung.hystrix;
-class RemoteServiceTestSimulator {
+public class RemoteServiceTestSimulator {
private long wait;
diff --git a/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java
new file mode 100644
index 0000000000..fab8e611d4
--- /dev/null
+++ b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java
@@ -0,0 +1,17 @@
+package com.baeldung.hystrix;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component("springClient")
+public class SpringExistingClient {
+
+ @Value("${remoteservice.timeout}")
+ private int remoteServiceDelay;
+
+ @HystrixCircuitBreaker
+ public String invokeRemoteService() throws InterruptedException{
+ return new RemoteServiceTestSimulator(remoteServiceDelay).execute();
+ }
+
+}
diff --git a/hystrix/src/main/resources/application.properties b/hystrix/src/main/resources/application.properties
new file mode 100644
index 0000000000..abde975550
--- /dev/null
+++ b/hystrix/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+remoteservice.command.group.key=RemoteServiceGroup
+remoteservice.command.key=RemoteServiceKey
+remoteservice.command.execution.timeout=10000
+remoteservice.command.threadpool.coresize=5
+remoteservice.command.threadpool.maxsize=10
+remoteservice.command.task.queue.size=5
+remoteservice.command.sleepwindow=5000
+remoteservice.timeout=5000
\ No newline at end of file
diff --git a/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java b/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java
index 773c76536f..c9ddd98367 100644
--- a/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java
+++ b/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java
@@ -9,13 +9,15 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import java.util.concurrent.ExecutionException;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class HystrixTimeoutTest {
- private static HystrixCommand.Setter config;
- private static HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
+ private HystrixCommand.Setter config;
+ private HystrixCommandProperties.Setter commandProperties ;
@Rule
@@ -23,6 +25,7 @@ public class HystrixTimeoutTest {
@Before
public void setup() {
+ commandProperties = HystrixCommandProperties.Setter();
config = HystrixCommand
.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroup1"));
@@ -34,29 +37,86 @@ public class HystrixTimeoutTest {
}
@Test
- public void givenTimeoutEqualTo100_andDefaultSettings_thenReturnSuccess() throws InterruptedException {
+ public void givenServiceTimeoutEqualTo100_andDefaultSettings_thenReturnSuccess() throws InterruptedException {
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(100)).execute(), equalTo("Success"));
}
@Test
- public void givenTimeoutEqualTo10000_andDefaultSettings_thenExpectHystrixRuntimeException() throws InterruptedException {
+ public void givenServiceTimeoutEqualTo10000_andDefaultSettings_thenExpectHRE() throws InterruptedException {
exception.expect(HystrixRuntimeException.class);
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(10_000)).execute();
}
@Test
- public void givenTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess() throws InterruptedException {
+ public void givenServiceTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess()
+ throws InterruptedException {
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
config.andCommandPropertiesDefaults(commandProperties);
- assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(5_000)).execute(), equalTo("Success"));
+ assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
+ equalTo("Success"));
}
@Test
- public void givenTimeoutEqualTo15000_andExecutionTimeoutEqualTo10000_thenExpectHystrixRuntimeException() throws InterruptedException {
+ public void givenServiceTimeoutEqualTo15000_andExecutionTimeoutEqualTo5000_thenExpectHRE()
+ throws InterruptedException {
exception.expect(HystrixRuntimeException.class);
- commandProperties.withExecutionTimeoutInMilliseconds(10_000);
+ commandProperties.withExecutionTimeoutInMilliseconds(5_000);
config.andCommandPropertiesDefaults(commandProperties);
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(15_000)).execute();
}
+ @Test
+ public void givenServiceTimeoutEqual_andExecutionTimeout_andThreadPool_thenReturnSuccess()
+ throws InterruptedException {
+ commandProperties.withExecutionTimeoutInMilliseconds(10_000);
+ config.andCommandPropertiesDefaults(commandProperties);
+ config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
+ .withMaxQueueSize(10)
+ .withCoreSize(3)
+ .withQueueSizeRejectionThreshold(10));
+ assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
+ equalTo("Success"));
+ }
+
+ @Test
+ public void givenCircuitBreakerSetup_thenReturnSuccess() throws InterruptedException {
+
+ commandProperties.withExecutionTimeoutInMilliseconds(1000);
+
+ commandProperties.withCircuitBreakerSleepWindowInMilliseconds(4000);
+ commandProperties.withExecutionIsolationStrategy(
+ HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
+ commandProperties.withCircuitBreakerEnabled(true);
+ commandProperties.withCircuitBreakerRequestVolumeThreshold(1);
+
+ config.andCommandPropertiesDefaults(commandProperties);
+
+ config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
+ .withMaxQueueSize(1)
+ .withCoreSize(1)
+ .withQueueSizeRejectionThreshold(1));
+
+ assertThat(this.invokeRemoteService(10000), equalTo(null));
+ assertThat(this.invokeRemoteService(10000), equalTo(null));
+ Thread.sleep(5000);
+
+ assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
+ equalTo("Success"));
+ assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
+ equalTo("Success"));
+ assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
+ equalTo("Success"));
+ }
+
+ public String invokeRemoteService(long timeout) throws InterruptedException{
+ String response = null;
+ try{
+ response = new RemoteServiceTestCommand(config,
+ new RemoteServiceTestSimulator(timeout)).execute();
+ }catch(HystrixRuntimeException ex){
+ System.out.println("ex = " + ex);
+ }
+ return response;
+ }
+
}