From 26a2d3875f89cce1f2ba08bc58d4646ec7d83667 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 12 Dec 2019 20:56:03 +0000 Subject: [PATCH] Expose ClientCodecConfigurer in WebClient.Builder Using Consumer instead of Consumer eliminates one level of nesting that is also unnecessary since codecs are the only strategy at present. Backport of dd9b6287b4c3b507f963c655144ed06dd8f5ff21 Closes gh-24201 --- .../server/DefaultWebTestClientBuilder.java | 8 ++++++ .../web/reactive/server/WebTestClient.java | 24 ++++++++++++----- .../client/DefaultWebClientBuilder.java | 11 ++++++++ .../reactive/function/client/WebClient.java | 27 +++++++++++++------ src/docs/asciidoc/web/webflux.adoc | 14 ++++------ 5 files changed, 60 insertions(+), 24 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClientBuilder.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClientBuilder.java index 82006d37b255..69279499fe73 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClientBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClientBuilder.java @@ -23,6 +23,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.MultiValueMap; @@ -136,12 +137,19 @@ public WebTestClient.Builder filters(Consumer> filt return this; } + @Override + public WebTestClient.Builder codecs(Consumer configurer) { + this.webClientBuilder.codecs(configurer); + return this; + } + @Override public WebTestClient.Builder exchangeStrategies(ExchangeStrategies strategies) { this.webClientBuilder.exchangeStrategies(strategies); return this; } + @SuppressWarnings("deprecation") @Override public WebTestClient.Builder exchangeStrategies(Consumer configurer) { this.webClientBuilder.exchangeStrategies(configurer); diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index e8b109cbc014..691d7aa68467 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -36,6 +36,7 @@ import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; @@ -435,14 +436,22 @@ interface Builder { */ Builder filters(Consumer> filtersConsumer); + /** + * Configure the codecs for the {@code WebClient} in the + * {@link #exchangeStrategies(ExchangeStrategies) underlying} + * {@code ExchangeStrategies}. + * @param configurer the configurer to apply + * @since 5.1.13 + */ + Builder codecs(Consumer configurer); + /** * Configure the {@link ExchangeStrategies} to use. - *

Note that in a scenario where the builder is configured by - * multiple parties, it is preferable to use - * {@link #exchangeStrategies(Consumer)} in order to customize the same - * {@code ExchangeStrategies}. This method here sets the strategies that - * everyone else then can customize. - *

By default this is {@link ExchangeStrategies#withDefaults()}. + *

For most cases, prefer using {@link #codecs(Consumer)} which allows + * customizing the codecs in the {@code ExchangeStrategies} rather than + * replace them. That ensures multiple parties can contribute to codecs + * configuration. + *

By default this is set to {@link ExchangeStrategies#withDefaults()}. * @param strategies the strategies to use */ Builder exchangeStrategies(ExchangeStrategies strategies); @@ -452,8 +461,9 @@ interface Builder { * {@link #exchangeStrategies(ExchangeStrategies)}. This method is * designed for use in scenarios where multiple parties wish to update * the {@code ExchangeStrategies}. - * @since 5.1.12 + * @deprecated as of 5.1.13 in favor of {@link #codecs(Consumer)} */ + @Deprecated Builder exchangeStrategies(Consumer configurer); /** 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 44c3164b701b..c255c439d326 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 @@ -27,6 +27,7 @@ import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.JettyClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -206,12 +207,22 @@ public WebClient.Builder clientConnector(ClientHttpConnector connector) { return this; } + @Override + public WebClient.Builder codecs(Consumer configurer) { + if (this.strategiesConfigurers == null) { + this.strategiesConfigurers = new ArrayList<>(4); + } + this.strategiesConfigurers.add(builder -> builder.codecs(configurer)); + return this; + } + @Override public WebClient.Builder exchangeStrategies(ExchangeStrategies strategies) { this.strategies = strategies; return this; } + @SuppressWarnings("deprecation") @Override public WebClient.Builder exchangeStrategies(Consumer configurer) { if (this.strategiesConfigurers == null) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java index f60a822597cc..eda41805c757 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java @@ -37,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; @@ -288,14 +289,22 @@ interface Builder { */ Builder clientConnector(ClientHttpConnector connector); + /** + * Configure the codecs for the {@code WebClient} in the + * {@link #exchangeStrategies(ExchangeStrategies) underlying} + * {@code ExchangeStrategies}. + * @param configurer the configurer to apply + * @since 5.1.13 + */ + Builder codecs(Consumer configurer); + /** * Configure the {@link ExchangeStrategies} to use. - *

Note that in a scenario where the builder is configured by - * multiple parties, it is preferable to use - * {@link #exchangeStrategies(Consumer)} in order to customize the same - * {@code ExchangeStrategies}. This method here sets the strategies that - * everyone else then can customize. - *

By default this is {@link ExchangeStrategies#withDefaults()}. + *

For most cases, prefer using {@link #codecs(Consumer)} which allows + * customizing the codecs in the {@code ExchangeStrategies} rather than + * replace them. That ensures multiple parties can contribute to codecs + * configuration. + *

By default this is set to {@link ExchangeStrategies#withDefaults()}. * @param strategies the strategies to use */ Builder exchangeStrategies(ExchangeStrategies strategies); @@ -305,15 +314,17 @@ interface Builder { * {@link #exchangeStrategies(ExchangeStrategies)}. This method is * designed for use in scenarios where multiple parties wish to update * the {@code ExchangeStrategies}. - * @since 5.1.12 + * @deprecated as of 5.1.13 in favor of {@link #codecs(Consumer)} */ + @Deprecated Builder exchangeStrategies(Consumer configurer); /** * Provide an {@link ExchangeFunction} pre-configured with * {@link ClientHttpConnector} and {@link ExchangeStrategies}. *

This is an alternative to, and effectively overrides - * {@link #clientConnector}, and {@link #exchangeStrategies}. + * {@link #clientConnector}, and + * {@link #exchangeStrategies(ExchangeStrategies)}. * @param exchangeFunction the exchange function to use */ Builder exchangeFunction(ExchangeFunction exchangeFunction); diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index 3b0e41a055b1..3d047c642b72 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -908,20 +908,16 @@ The following example shows how to do so for client-side requests: [source,java,indent=0] [subs="verbatim,quotes"] ---- - Consumer consumer = configurer -> { - CustomDecoder customDecoder = new CustomDecoder(); - configurer.customCodecs().decoder(customDecoder); - configurer.customCodecs().withDefaultCodecConfig(config -> - customDecoder.maxInMemorySize(config.maxInMemorySize()) - ); - } - WebClient webClient = WebClient.builder() - .exchangeStrategies(strategies -> strategies.codecs(consumer)) + .codecs(configurer -> { + CustomDecoder decoder = new CustomDecoder(); + configurer.customCodecs().registerWithDefaultConfig(decoder); + }) .build(); ---- ==== + [[webflux-dispatcher-handler]] == `DispatcherHandler` [.small]#<>#