diff --git a/ratpack/pom.xml b/ratpack/pom.xml index 7a75ec50b7..3f953b3ed0 100644 --- a/ratpack/pom.xml +++ b/ratpack/pom.xml @@ -40,16 +40,38 @@ ratpack-hikari ${ratpack.version} + + io.ratpack + ratpack-hystrix + ${ratpack.version} + + + io.ratpack + ratpack-rx + ${ratpack.version} + io.ratpack ratpack-test ${ratpack.version} + test com.h2database h2 1.4.193 + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + org.apache.httpcomponents + httpcore + 4.4.6 + diff --git a/ratpack/src/main/java/com/baeldung/hystrix/HystrixAsyncHttpCommand.java b/ratpack/src/main/java/com/baeldung/hystrix/HystrixAsyncHttpCommand.java new file mode 100644 index 0000000000..a1a19150c3 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/hystrix/HystrixAsyncHttpCommand.java @@ -0,0 +1,54 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandProperties; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicHeader; +import org.apache.http.util.EntityUtils; + +import java.net.URI; +import java.util.Collections; + +/** + * @author aiet + */ +public class HystrixAsyncHttpCommand extends HystrixCommand { + + private URI uri; + private RequestConfig requestConfig; + + HystrixAsyncHttpCommand(URI uri, int timeoutMillis) { + super(Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("hystrix-ratpack-async")) + .andCommandPropertiesDefaults(HystrixCommandProperties + .Setter() + .withExecutionTimeoutInMilliseconds(timeoutMillis))); + requestConfig = RequestConfig + .custom() + .setSocketTimeout(timeoutMillis) + .setConnectTimeout(timeoutMillis) + .setConnectionRequestTimeout(timeoutMillis) + .build(); + this.uri = uri; + } + + @Override + protected String run() throws Exception { + return EntityUtils.toString(HttpClientBuilder + .create() + .setDefaultRequestConfig(requestConfig) + .setDefaultHeaders(Collections.singleton(new BasicHeader("User-Agent", "Baeldung Blocking HttpClient"))) + .build() + .execute(new HttpGet(uri)) + .getEntity()); + } + + @Override + protected String getFallback() { + return "eugenp's async fallback profile"; + } + +} diff --git a/ratpack/src/main/java/com/baeldung/hystrix/HystrixReactiveHttpCommand.java b/ratpack/src/main/java/com/baeldung/hystrix/HystrixReactiveHttpCommand.java new file mode 100644 index 0000000000..f9f85c705b --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/hystrix/HystrixReactiveHttpCommand.java @@ -0,0 +1,44 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandProperties; +import com.netflix.hystrix.HystrixObservableCommand; +import ratpack.http.client.HttpClient; +import ratpack.rx.RxRatpack; +import rx.Observable; + +import java.net.URI; + +/** + * @author aiet + */ +public class HystrixReactiveHttpCommand extends HystrixObservableCommand { + + private HttpClient httpClient; + private URI uri; + + HystrixReactiveHttpCommand(HttpClient httpClient, URI uri, int timeoutMillis) { + super(Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("hystrix-ratpack-reactive")) + .andCommandPropertiesDefaults(HystrixCommandProperties + .Setter() + .withExecutionTimeoutInMilliseconds(timeoutMillis))); + this.httpClient = httpClient; + this.uri = uri; + } + + @Override + protected Observable construct() { + return RxRatpack.observe(httpClient + .get(uri, requestSpec -> requestSpec.headers(mutableHeaders -> mutableHeaders.add("User-Agent", "Baeldung HttpClient"))) + .map(receivedResponse -> receivedResponse + .getBody() + .getText())); + } + + @Override + protected Observable resumeWithFallback() { + return Observable.just("eugenp's reactive fallback profile"); + } + +} diff --git a/ratpack/src/main/java/com/baeldung/hystrix/HystrixSyncHttpCommand.java b/ratpack/src/main/java/com/baeldung/hystrix/HystrixSyncHttpCommand.java new file mode 100644 index 0000000000..7c848331ca --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/hystrix/HystrixSyncHttpCommand.java @@ -0,0 +1,55 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandProperties; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicHeader; +import org.apache.http.util.EntityUtils; + +import java.net.URI; +import java.util.Collections; + +/** + * @author aiet + */ +public class HystrixSyncHttpCommand extends HystrixCommand { + + private URI uri; + private RequestConfig requestConfig; + + HystrixSyncHttpCommand(URI uri, int timeoutMillis) { + super(Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("hystrix-ratpack-sync")) + .andCommandPropertiesDefaults(HystrixCommandProperties + .Setter() + .withExecutionTimeoutInMilliseconds(timeoutMillis))); + requestConfig = RequestConfig + .custom() + .setSocketTimeout(timeoutMillis) + .setConnectTimeout(timeoutMillis) + .setConnectionRequestTimeout(timeoutMillis) + .build(); + this.uri = uri; + } + + @Override + protected String run() throws Exception { + HttpGet request = new HttpGet(uri); + return EntityUtils.toString(HttpClientBuilder + .create() + .setDefaultRequestConfig(requestConfig) + .setDefaultHeaders(Collections.singleton(new BasicHeader("User-Agent", "Baeldung Blocking HttpClient"))) + .build() + .execute(request) + .getEntity()); + } + + @Override + protected String getFallback() { + return "eugenp's sync fallback profile"; + } + +} diff --git a/ratpack/src/main/java/com/baeldung/hystrix/RatpackHystrixApp.java b/ratpack/src/main/java/com/baeldung/hystrix/RatpackHystrixApp.java new file mode 100644 index 0000000000..1e4724bd96 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/hystrix/RatpackHystrixApp.java @@ -0,0 +1,30 @@ +package com.baeldung.hystrix; + +import ratpack.guice.Guice; +import ratpack.http.client.HttpClient; +import ratpack.hystrix.HystrixMetricsEventStreamHandler; +import ratpack.hystrix.HystrixModule; +import ratpack.server.RatpackServer; + +import java.net.URI; + +public class RatpackHystrixApp { + + public static void main(String[] args) throws Exception { + final int timeout = Integer.valueOf(System.getProperty("ratpack.hystrix.timeout")); + final URI eugenGithubProfileUri = new URI("https://api.github.com/users/eugenp"); + + RatpackServer.start(server -> server + .registry(Guice.registry(bindingsSpec -> bindingsSpec.module(new HystrixModule().sse()))) + .handlers(chain -> chain + .get("rx", ctx -> new HystrixReactiveHttpCommand(ctx.get(HttpClient.class), eugenGithubProfileUri, timeout) + .toObservable() + .subscribe(ctx::render)) + .get("async", ctx -> ctx.render(new HystrixAsyncHttpCommand(eugenGithubProfileUri, timeout) + .queue() + .get())) + .get("sync", ctx -> ctx.render(new HystrixSyncHttpCommand(eugenGithubProfileUri, timeout).execute())) + .get("hystrix", new HystrixMetricsEventStreamHandler()))); + + } +} diff --git a/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppFallbackLiveTest.java b/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppFallbackLiveTest.java new file mode 100644 index 0000000000..25287a5cbd --- /dev/null +++ b/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppFallbackLiveTest.java @@ -0,0 +1,50 @@ +package com.baeldung.hystrix; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import ratpack.test.MainClassApplicationUnderTest; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +/** + * @author aiet + */ +public class RatpackHystrixAppFallbackLiveTest { + + static MainClassApplicationUnderTest appUnderTest; + + @BeforeClass + public static void setup() { + System.setProperty("ratpack.hystrix.timeout", "10"); + appUnderTest = new MainClassApplicationUnderTest(RatpackHystrixApp.class); + } + + @Test + public void whenFetchReactive_thenGotFallbackProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("rx"), containsString("reactive fallback profile")); + } + + @Test + public void whenFetchAsync_thenGotFallbackProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("async"), containsString("async fallback profile")); + } + + @Test + public void whenFetchSync_thenGotFallbackProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("sync"), containsString("sync fallback profile")); + } + + @AfterClass + public static void clean() { + appUnderTest.close(); + } + +} diff --git a/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppLiveTest.java b/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppLiveTest.java new file mode 100644 index 0000000000..843ef68e13 --- /dev/null +++ b/ratpack/src/test/java/com/baeldung/hystrix/RatpackHystrixAppLiveTest.java @@ -0,0 +1,50 @@ +package com.baeldung.hystrix; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import ratpack.test.MainClassApplicationUnderTest; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +/** + * @author aiet + */ +public class RatpackHystrixAppLiveTest { + + static MainClassApplicationUnderTest appUnderTest; + + @BeforeClass + public static void setup() { + System.setProperty("ratpack.hystrix.timeout", "5000"); + appUnderTest = new MainClassApplicationUnderTest(RatpackHystrixApp.class); + } + + @Test + public void whenFetchReactive_thenGotEugenProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("rx"), containsString("www.baeldung.com")); + } + + @Test + public void whenFetchAsync_thenGotEugenProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("async"), containsString("www.baeldung.com")); + } + + @Test + public void whenFetchSync_thenGotEugenProfile() { + assertThat(appUnderTest + .getHttpClient() + .getText("sync"), containsString("www.baeldung.com")); + } + + @AfterClass + public static void clean() { + appUnderTest.close(); + } + +}