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
index 8102428e9a..8b11ac99c3 100644
--- a/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
+++ b/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
@@ -1,8 +1,10 @@
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.context.ApplicationContext;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class AppConfig {
@@ -10,4 +12,9 @@ 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/main/java/com/baeldung/hystrix/HystrixAspect.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java
index 2ea0163ab1..c2e4af8edb 100644
--- a/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java
+++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java
@@ -1,7 +1,81 @@
package com.baeldung.hystrix;
-/**
- * Created by sbalachandran on 8/5/2016.
- */
+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
index 9377d83495..e7c0694a7b 100644
--- a/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java
+++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java
@@ -1,7 +1,11 @@
package com.baeldung.hystrix;
-/**
- * Created by sbalachandran on 8/5/2016.
- */
-public class HystrixCircuitBreaker {
+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/SpringExistingClient.java b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java
index b08f61a777..fab8e611d4 100644
--- a/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java
+++ b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java
@@ -1,7 +1,17 @@
package com.baeldung.hystrix;
-/**
- * Created by sbalachandran on 8/5/2016.
- */
+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
index e69de29bb2..abde975550 100644
--- a/hystrix/src/main/resources/application.properties
+++ 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..9f067a0764 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,87 @@ 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(5_000)).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(9_000)).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));
+ assertThat(this.invokeRemoteService(500), 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;
+ }
+
}