From 4a6a556af04fe8d1e2686c07fea7e289e42acb05 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 15 Jul 2016 16:26:21 +0200 Subject: [PATCH] Added tests and fix docs for AsyncRestTemplate fixes #334 --- .../main/asciidoc/spring-cloud-sleuth.adoc | 7 +- ...eAsyncClientHttpRequestFactoryWrapper.java | 4 +- ...ceWebAsyncClientAutoConfigurationTest.java | 92 +++++++++++++++++++ .../WebClientDiscoveryExceptionTests.java | 12 +-- 4 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTest.java diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc index 537a0ad78..9a7c38813 100644 --- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc +++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc @@ -456,7 +456,12 @@ If you create a `RestTemplate` instance with a `new` keyword then the instrument Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the `ClientHttpRequestFactory` and the `AsyncClientHttpRequestFactory` by registering your beans. Remember to use tracing compatible implementations (e.g. don't forget to -wrap `ThreadPoolTaskScheduler` in a `TraceAsyncListenableTaskExecutor`). +wrap `ThreadPoolTaskScheduler` in a `TraceAsyncListenableTaskExecutor`). Example of custom request factories: + +[source,java] +---- +include::../../../../spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTest.java[tags=async_template_factories,indent=0] +---- To block the `AsyncRestTemplate` features set `spring.sleuth.web.async.client.enabled` to `false`. To disable creation of the default `TraceAsyncClientHttpRequestFactoryWrapper` set `spring.sleuth.web.async.client.factory.enabled` diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceAsyncClientHttpRequestFactoryWrapper.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceAsyncClientHttpRequestFactoryWrapper.java index 96be114cc..49e26f6c4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceAsyncClientHttpRequestFactoryWrapper.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceAsyncClientHttpRequestFactoryWrapper.java @@ -43,8 +43,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttpRequestInterceptor implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory { - private final AsyncClientHttpRequestFactory asyncDelegate; - private final ClientHttpRequestFactory syncDelegate; + final AsyncClientHttpRequestFactory asyncDelegate; + final ClientHttpRequestFactory syncDelegate; /** * According to the JavaDocs all Spring {@link AsyncClientHttpRequestFactory} implement diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTest.java new file mode 100644 index 000000000..0cdfb5a9e --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed 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 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth.instrument.web.client; + +import java.io.IOException; +import java.net.URI; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.AsyncClientHttpRequest; +import org.springframework.http.client.AsyncClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.client.AsyncRestTemplate; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author Marcin Grzejszczak + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = { + TraceWebAsyncClientAutoConfigurationTest.TestConfiguration.class }, webEnvironment = RANDOM_PORT) +public class TraceWebAsyncClientAutoConfigurationTest { + + @Autowired AsyncRestTemplate asyncRestTemplate; + @Autowired MySyncClientHttpRequestFactory mySyncClientHttpRequestFactory; + @Autowired MyAsyncClientHttpRequestFactory myAsyncClientHttpRequestFactory; + + @Test + public void should_inject_to_async_rest_template_custom_client_http_request_factory() { + then(this.asyncRestTemplate.getAsyncRequestFactory()).isInstanceOf(TraceAsyncClientHttpRequestFactoryWrapper.class); + TraceAsyncClientHttpRequestFactoryWrapper wrapper = (TraceAsyncClientHttpRequestFactoryWrapper) this.asyncRestTemplate.getAsyncRequestFactory(); + then(wrapper.syncDelegate).isSameAs(this.mySyncClientHttpRequestFactory); + then(wrapper.asyncDelegate).isSameAs(this.myAsyncClientHttpRequestFactory); + then(this.asyncRestTemplate).isInstanceOf(TraceAsyncRestTemplate.class); + } + + // tag::async_template_factories[] + @EnableAutoConfiguration + @Configuration + public static class TestConfiguration { + + @Bean + ClientHttpRequestFactory mySyncClientFactory() { + return new MySyncClientHttpRequestFactory(); + } + + @Bean + AsyncClientHttpRequestFactory myAsyncClientFactory() { + return new MyAsyncClientHttpRequestFactory(); + } + } + // end::async_template_factories[] + + private static class MySyncClientHttpRequestFactory implements ClientHttpRequestFactory { + @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) + throws IOException { + return null; + } + } + private static class MyAsyncClientHttpRequestFactory implements AsyncClientHttpRequestFactory { + @Override + public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) + throws IOException { + return null; + } + } + +} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientDiscoveryExceptionTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientDiscoveryExceptionTests.java index 73ff1f476..4f215f627 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientDiscoveryExceptionTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientDiscoveryExceptionTests.java @@ -26,8 +26,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.feign.EnableFeignClients; @@ -44,6 +43,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -51,12 +51,12 @@ import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.BDDAssertions.then; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = { - WebClientDiscoveryExceptionTests.TestConfiguration.class }) -@WebIntegrationTest(value = { - "spring.application.name=exceptionservice" }, randomPort = true) +@SpringBootTest(classes = { + WebClientDiscoveryExceptionTests.TestConfiguration.class }, webEnvironment = RANDOM_PORT) +@TestPropertySource(properties = "spring.application.name=exceptionservice") @DirtiesContext public class WebClientDiscoveryExceptionTests {