From ca3a0b19d634948703e442eda732785b5120e0a6 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Tue, 20 Aug 2019 10:45:23 -0500 Subject: [PATCH 1/2] DefaultWebClientBuilder defaults using classpath Previously DefaultWebClientBuilder always defaulted the ClientHttpConnector with ReactorClientHttpConnector. This worked fine if reactor was used. However, it would break if the user was trying to leverage Jetty. This commit defaults to use Reactory Netty HttpClient if it is present. If it is not present it then Jetty's HttpClient is used if present. Closes gh-23491 --- .../client/DefaultWebClientBuilder.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java index c8796e91f7..c3aef0520e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java @@ -25,9 +25,11 @@ import java.util.function.Consumer; import org.springframework.http.HttpHeaders; import org.springframework.http.client.reactive.ClientHttpConnector; +import org.springframework.http.client.reactive.JettyClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -41,6 +43,17 @@ import org.springframework.web.util.UriBuilderFactory; * @since 5.0 */ final class DefaultWebClientBuilder implements WebClient.Builder { + private static final boolean jettyHttpClientPresent; + + private static final boolean reactorNettyHttpClientPresent; + + static { + ClassLoader classLoader = DefaultWebClientBuilder.class.getClassLoader(); + jettyHttpClientPresent = ClassUtils.isPresent( + "org.eclipse.jetty.client.HttpClient", classLoader); + reactorNettyHttpClientPresent = ClassUtils.isPresent( + "reactor.netty.http.client.HttpClient", classLoader); + } @Nullable private String baseUrl; @@ -234,10 +247,20 @@ final class DefaultWebClientBuilder implements WebClient.Builder { return ExchangeFunctions.create(this.connector, this.exchangeStrategies); } else { - return ExchangeFunctions.create(new ReactorClientHttpConnector(), this.exchangeStrategies); + return ExchangeFunctions.create(createDefaultClientHttpConnector(), this.exchangeStrategies); } } + private ClientHttpConnector createDefaultClientHttpConnector() { + if (reactorNettyHttpClientPresent) { + return new ReactorClientHttpConnector(); + } + else if (jettyHttpClientPresent) { + return new JettyClientHttpConnector(); + } + throw new IllegalStateException("No suitable default ClientHttpConnector found"); + } + private UriBuilderFactory initUriBuilderFactory() { if (this.uriBuilderFactory != null) { return this.uriBuilderFactory; From aa220a9a022c5a8443edcfbf38406b87806a2669 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 21 Aug 2019 11:20:37 +0300 Subject: [PATCH 2/2] Polish --- .../client/DefaultWebClientBuilder.java | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java index c3aef0520e..db699ddaae 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java @@ -43,18 +43,18 @@ import org.springframework.web.util.UriBuilderFactory; * @since 5.0 */ final class DefaultWebClientBuilder implements WebClient.Builder { - private static final boolean jettyHttpClientPresent; - private static final boolean reactorNettyHttpClientPresent; + private static final boolean reactorClientPresent; + + private static final boolean jettyClientPresent; static { - ClassLoader classLoader = DefaultWebClientBuilder.class.getClassLoader(); - jettyHttpClientPresent = ClassUtils.isPresent( - "org.eclipse.jetty.client.HttpClient", classLoader); - reactorNettyHttpClientPresent = ClassUtils.isPresent( - "reactor.netty.http.client.HttpClient", classLoader); + ClassLoader loader = DefaultWebClientBuilder.class.getClassLoader(); + reactorClientPresent = ClassUtils.isPresent("reactor.netty.http.client.HttpClient", loader); + jettyClientPresent = ClassUtils.isPresent("org.eclipse.jetty.client.HttpClient", loader); } + @Nullable private String baseUrl; @@ -228,7 +228,9 @@ final class DefaultWebClientBuilder implements WebClient.Builder { @Override public WebClient build() { - ExchangeFunction exchange = initExchangeFunction(); + ExchangeFunction exchange = (this.exchangeFunction == null ? + ExchangeFunctions.create(getOrInitConnector(), this.exchangeStrategies) : + this.exchangeFunction); ExchangeFunction filteredExchange = (this.filters != null ? this.filters.stream() .reduce(ExchangeFilterFunction::andThen) .map(filter -> filter.apply(exchange)) @@ -239,23 +241,14 @@ final class DefaultWebClientBuilder implements WebClient.Builder { this.defaultRequest, new DefaultWebClientBuilder(this)); } - private ExchangeFunction initExchangeFunction() { - if (this.exchangeFunction != null) { - return this.exchangeFunction; + private ClientHttpConnector getOrInitConnector() { + if (this.connector != null) { + return this.connector; } - else if (this.connector != null) { - return ExchangeFunctions.create(this.connector, this.exchangeStrategies); - } - else { - return ExchangeFunctions.create(createDefaultClientHttpConnector(), this.exchangeStrategies); - } - } - - private ClientHttpConnector createDefaultClientHttpConnector() { - if (reactorNettyHttpClientPresent) { + else if (reactorClientPresent) { return new ReactorClientHttpConnector(); } - else if (jettyHttpClientPresent) { + else if (jettyClientPresent) { return new JettyClientHttpConnector(); } throw new IllegalStateException("No suitable default ClientHttpConnector found");