diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java index 76ecc4cd830d..f0749715398d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java @@ -52,37 +52,60 @@ * * @author Moritz Halbritter * @author Stefan Bratanov + * @author Wick Dynex */ class ZipkinConfigurations { @Configuration(proxyBeanMethods = false) - @Import({ UrlConnectionSenderConfiguration.class, WebClientSenderConfiguration.class, - RestTemplateSenderConfiguration.class, HttpClientSenderConfiguration.class }) + @Import({ HttpClientSenderConfiguration.class, WebClientSenderConfiguration.class, + RestTemplateSenderConfiguration.class, UrlConnectionSenderConfiguration.class }) static class SenderConfiguration { } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(URLConnectionSender.class) + @ConditionalOnClass(HttpClient.class) @EnableConfigurationProperties(ZipkinProperties.class) - static class UrlConnectionSenderConfiguration { + static class HttpClientSenderConfiguration { @Bean @ConditionalOnMissingBean(BytesMessageSender.class) - URLConnectionSender urlConnectionSender(ZipkinProperties properties, Encoding encoding, + ZipkinHttpClientSender httpClientSender(ZipkinProperties properties, Encoding encoding, + ObjectProvider customizers, ObjectProvider connectionDetailsProvider, ObjectProvider endpointSupplierFactoryProvider) { ZipkinConnectionDetails connectionDetails = connectionDetailsProvider .getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties)); HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider .getIfAvailable(HttpEndpointSuppliers::constantFactory); - URLConnectionSender.Builder builder = URLConnectionSender.newBuilder(); - builder.connectTimeout((int) properties.getConnectTimeout().toMillis()); - builder.readTimeout((int) properties.getReadTimeout().toMillis()); - builder.endpointSupplierFactory(endpointSupplierFactory); - builder.endpoint(connectionDetails.getSpanEndpoint()); - builder.encoding(encoding); - return builder.build(); + Builder httpClientBuilder = HttpClient.newBuilder().connectTimeout(properties.getConnectTimeout()); + customizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder)); + return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(), + httpClientBuilder.build(), properties.getReadTimeout()); + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(WebClient.class) + @EnableConfigurationProperties(ZipkinProperties.class) + static class WebClientSenderConfiguration { + + @Bean + @ConditionalOnMissingBean(BytesMessageSender.class) + @SuppressWarnings({ "deprecation", "removal" }) + ZipkinWebClientSender webClientSender(ZipkinProperties properties, Encoding encoding, + ObjectProvider customizers, + ObjectProvider connectionDetailsProvider, + ObjectProvider endpointSupplierFactoryProvider) { + ZipkinConnectionDetails connectionDetails = connectionDetailsProvider + .getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties)); + HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider + .getIfAvailable(HttpEndpointSuppliers::constantFactory); + WebClient.Builder builder = WebClient.builder(); + customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); + return new ZipkinWebClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(), + builder.build(), properties.getConnectTimeout().plus(properties.getReadTimeout())); } } @@ -126,48 +149,26 @@ private RestTemplateBuilder applyCustomizers(RestTemplateBuilder restTemplateBui } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(WebClient.class) - @EnableConfigurationProperties(ZipkinProperties.class) - static class WebClientSenderConfiguration { - - @Bean - @ConditionalOnMissingBean(BytesMessageSender.class) - @SuppressWarnings({ "deprecation", "removal" }) - ZipkinWebClientSender webClientSender(ZipkinProperties properties, Encoding encoding, - ObjectProvider customizers, - ObjectProvider connectionDetailsProvider, - ObjectProvider endpointSupplierFactoryProvider) { - ZipkinConnectionDetails connectionDetails = connectionDetailsProvider - .getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties)); - HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider - .getIfAvailable(HttpEndpointSuppliers::constantFactory); - WebClient.Builder builder = WebClient.builder(); - customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); - return new ZipkinWebClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(), - builder.build(), properties.getConnectTimeout().plus(properties.getReadTimeout())); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(HttpClient.class) + @ConditionalOnClass(URLConnectionSender.class) @EnableConfigurationProperties(ZipkinProperties.class) - static class HttpClientSenderConfiguration { + static class UrlConnectionSenderConfiguration { @Bean @ConditionalOnMissingBean(BytesMessageSender.class) - ZipkinHttpClientSender httpClientSender(ZipkinProperties properties, Encoding encoding, - ObjectProvider customizers, + URLConnectionSender urlConnectionSender(ZipkinProperties properties, Encoding encoding, ObjectProvider connectionDetailsProvider, ObjectProvider endpointSupplierFactoryProvider) { ZipkinConnectionDetails connectionDetails = connectionDetailsProvider .getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties)); HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider .getIfAvailable(HttpEndpointSuppliers::constantFactory); - Builder httpClientBuilder = HttpClient.newBuilder().connectTimeout(properties.getConnectTimeout()); - customizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder)); - return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(), - httpClientBuilder.build(), properties.getReadTimeout()); + URLConnectionSender.Builder builder = URLConnectionSender.newBuilder(); + builder.connectTimeout((int) properties.getConnectTimeout().toMillis()); + builder.readTimeout((int) properties.getReadTimeout().toMillis()); + builder.endpointSupplierFactory(endpointSupplierFactory); + builder.endpoint(connectionDetails.getSpanEndpoint()); + builder.encoding(encoding); + return builder.build(); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsSenderConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsSenderConfigurationTests.java index 7988fd310837..f32519dd4f00 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsSenderConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsSenderConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.tracing.zipkin; import java.io.IOException; +import java.net.http.HttpClient; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.TimeUnit; @@ -31,6 +32,7 @@ import zipkin2.reporter.urlconnection.URLConnectionSender; import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.SenderConfiguration; +import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.UrlConnectionSenderConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -39,6 +41,7 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; import static org.assertj.core.api.Assertions.assertThat; @@ -49,6 +52,7 @@ * Tests for {@link SenderConfiguration}. * * @author Moritz Halbritter + * @author Wick Dynex */ @SuppressWarnings({ "deprecation", "removal" }) class ZipkinConfigurationsSenderConfigurationTests { @@ -63,34 +67,33 @@ class ZipkinConfigurationsSenderConfigurationTests { .withConfiguration(AutoConfigurations.of(DefaultEncodingConfiguration.class, SenderConfiguration.class)); @Test - void shouldSupplyBeans() { + void shouldSupplyDefaultHttpClientSenderBeans() { this.contextRunner.run((context) -> { assertThat(context).hasSingleBean(BytesMessageSender.class); - assertThat(context).hasSingleBean(URLConnectionSender.class); + assertThat(context).hasSingleBean(ZipkinHttpClientSender.class); assertThat(context).doesNotHaveBean(ZipkinRestTemplateSender.class); + assertThat(context).doesNotHaveBean(ZipkinWebClientSenderTests.class); + assertThat(context).doesNotHaveBean(URLConnectionSender.class); }); } @Test - void shouldUseHttpClientIfUrlSenderIsNotAvailable() { - this.contextRunner.withUserConfiguration(HttpClientConfiguration.class) - .withClassLoader(new FilteredClassLoader("zipkin2.reporter.urlconnection", "org.springframework.web.client", - "org.springframework.web.reactive.function.client")) + void shouldUseUrlSenderIfHttpSenderIsNotAvailable() { + this.contextRunner.withUserConfiguration(UrlConnectionSenderConfiguration.class) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class, RestTemplate.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); - assertThat(context).hasSingleBean(ZipkinHttpClientSender.class); - then(context.getBean(ZipkinHttpClientBuilderCustomizer.class)).should() - .customize(ArgumentMatchers.any()); + assertThat(context).hasSingleBean(URLConnectionSender.class); }); } @Test - void shouldPreferWebClientSenderIfWebApplicationIsReactiveAndUrlSenderIsNotAvailable() { + void shouldPreferWebClientSenderIfWebApplicationIsReactiveAndHttpClientSenderIsNotAvailable() { this.reactiveContextRunner.withUserConfiguration(RestTemplateConfiguration.class, WebClientConfiguration.class) - .withClassLoader(new FilteredClassLoader("zipkin2.reporter.urlconnection")) + .withClassLoader(new FilteredClassLoader(HttpClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinWebClientSender.class); then(context.getBean(ZipkinWebClientBuilderCustomizer.class)).should() @@ -99,55 +102,55 @@ void shouldPreferWebClientSenderIfWebApplicationIsReactiveAndUrlSenderIsNotAvail } @Test - void shouldPreferWebClientSenderIfWebApplicationIsServletAndUrlSenderIsNotAvailable() { + void shouldPreferWebClientSenderIfWebApplicationIsServletAndHttpClientSenderIsNotAvailable() { this.servletContextRunner.withUserConfiguration(RestTemplateConfiguration.class, WebClientConfiguration.class) - .withClassLoader(new FilteredClassLoader("zipkin2.reporter.urlconnection")) + .withClassLoader(new FilteredClassLoader(HttpClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinWebClientSender.class); }); } @Test - void shouldPreferWebClientInNonWebApplicationAndUrlConnectionSenderIsNotAvailable() { + void shouldPreferWebClientInNonWebApplicationAndHttpClientSenderIsNotAvailable() { this.contextRunner.withUserConfiguration(RestTemplateConfiguration.class, WebClientConfiguration.class) - .withClassLoader(new FilteredClassLoader("zipkin2.reporter.urlconnection")) + .withClassLoader(new FilteredClassLoader(HttpClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinWebClientSender.class); }); } @Test - void willUseRestTemplateInNonWebApplicationIfUrlConnectionSenderAndWebClientAreNotAvailable() { + void willUseRestTemplateInNonWebApplicationIfSenderAndWebClientAreNotAvailable() { this.contextRunner.withUserConfiguration(RestTemplateConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class, WebClient.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(HttpClient.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinRestTemplateSender.class); }); } @Test - void willUseRestTemplateInServletWebApplicationIfUrlConnectionSenderAndWebClientNotAvailable() { + void willUseRestTemplateInServletWebApplicationIfHttpClientSenderAndWebClientNotAvailable() { this.servletContextRunner.withUserConfiguration(RestTemplateConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class, WebClient.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinRestTemplateSender.class); }); } @Test - void willUseRestTemplateInReactiveWebApplicationIfUrlConnectionSenderAndWebClientAreNotAvailable() { + void willUseRestTemplateInReactiveWebApplicationIfHttpClientSenderAndWebClientAreNotAvailable() { this.reactiveContextRunner.withUserConfiguration(RestTemplateConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class, WebClient.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class)) .run((context) -> { - assertThat(context).doesNotHaveBean(URLConnectionSender.class); + assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); assertThat(context).hasSingleBean(ZipkinRestTemplateSender.class); }); @@ -158,7 +161,7 @@ void shouldNotUseWebClientSenderIfNoBuilderIsAvailable() { this.reactiveContextRunner.run((context) -> { assertThat(context).doesNotHaveBean(ZipkinWebClientSender.class); assertThat(context).hasSingleBean(BytesMessageSender.class); - assertThat(context).hasSingleBean(URLConnectionSender.class); + assertThat(context).hasSingleBean(ZipkinHttpClientSender.class); }); } @@ -177,7 +180,7 @@ void shouldApplyZipkinRestTemplateBuilderCustomizers() throws IOException { this.reactiveContextRunner .withPropertyValues("management.zipkin.tracing.endpoint=" + mockWebServer.url("/")) .withUserConfiguration(RestTemplateConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class, WebClient.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class)) .run((context) -> { assertThat(context).hasSingleBean(ZipkinRestTemplateSender.class); ZipkinRestTemplateSender sender = context.getBean(ZipkinRestTemplateSender.class); @@ -192,6 +195,7 @@ void shouldApplyZipkinRestTemplateBuilderCustomizers() throws IOException { @Test void shouldUseCustomHttpEndpointSupplierFactory() { this.contextRunner.withUserConfiguration(CustomHttpEndpointSupplierFactoryConfiguration.class) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class, RestTemplate.class)) .run((context) -> assertThat(context.getBean(URLConnectionSender.class)) .extracting("delegate.endpointSupplier") .isInstanceOf(CustomHttpEndpointSupplier.class)); @@ -200,7 +204,7 @@ void shouldUseCustomHttpEndpointSupplierFactory() { @Test void shouldUseCustomHttpEndpointSupplierFactoryWhenReactive() { this.reactiveContextRunner.withUserConfiguration(WebClientConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class)) .withUserConfiguration(CustomHttpEndpointSupplierFactoryConfiguration.class) .run((context) -> assertThat(context.getBean(ZipkinWebClientSender.class)).extracting("endpointSupplier") .isInstanceOf(CustomHttpEndpointSupplier.class)); @@ -209,7 +213,7 @@ void shouldUseCustomHttpEndpointSupplierFactoryWhenReactive() { @Test void shouldUseCustomHttpEndpointSupplierFactoryWhenRestTemplate() { this.contextRunner.withUserConfiguration(RestTemplateConfiguration.class) - .withClassLoader(new FilteredClassLoader(URLConnectionSender.class, WebClient.class)) + .withClassLoader(new FilteredClassLoader(HttpClient.class, WebClient.class)) .withUserConfiguration(CustomHttpEndpointSupplierFactoryConfiguration.class) .run((context) -> assertThat(context.getBean(ZipkinRestTemplateSender.class)).extracting("endpointSupplier") .isInstanceOf(CustomHttpEndpointSupplier.class));