diff --git a/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java index ed1eebf5b8..8776508c59 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java @@ -65,6 +65,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer { protected AbstractCodecConfigurer(AbstractDefaultCodecs defaultCodecs) { Assert.notNull(defaultCodecs, "'defaultCodecs' is required."); this.defaultCodecs = defaultCodecs; + this.defaultCodecs.setCustomCodecs(this.customCodecs); } @@ -112,7 +113,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer { } - abstract static class AbstractDefaultCodecs implements DefaultCodecs { + abstract protected static class AbstractDefaultCodecs implements DefaultCodecs { private boolean registerDefaults = true; @@ -120,6 +121,8 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer { private Jackson2JsonEncoder jackson2Encoder; + private DefaultCustomCodecs customCodecs; + public void setRegisterDefaults(boolean registerDefaults) { this.registerDefaults = registerDefaults; @@ -129,6 +132,17 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer { return this.registerDefaults; } + /** + * Access to custom codecs for sub-classes, e.g. for multipart writers. + */ + public void setCustomCodecs(DefaultCustomCodecs customCodecs) { + this.customCodecs = customCodecs; + } + + public DefaultCustomCodecs getCustomCodecs() { + return this.customCodecs; + } + @Override public void jackson2Decoder(Jackson2JsonDecoder decoder) { this.jackson2Decoder = decoder; @@ -227,7 +241,7 @@ abstract class AbstractCodecConfigurer implements CodecConfigurer { } - private static class DefaultCustomCodecs implements CustomCodecs { + protected static class DefaultCustomCodecs implements CustomCodecs { private final List> typedReaders = new ArrayList<>(); private final List> typedWriters = new ArrayList<>(); diff --git a/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java index 7863f6e4da..28ad129744 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/DefaultClientCodecConfigurer.java @@ -100,9 +100,19 @@ class DefaultClientCodecConfigurer extends AbstractCodecConfigurer implements Cl } private MultipartHttpMessageWriter getMultipartHttpMessageWriter() { - return this.multipartCodecs != null ? - new MultipartHttpMessageWriter(this.multipartCodecs.getWriters()) : - new MultipartHttpMessageWriter(); + List> partWriters; + if (this.multipartCodecs != null) { + partWriters = this.multipartCodecs.getWriters(); + } + else { + partWriters = new ArrayList<>(); + partWriters.addAll(super.getTypedWriters()); + partWriters.addAll(getCustomCodecs().getTypedWriters()); + partWriters.addAll(super.getObjectWriters()); + partWriters.addAll(getCustomCodecs().getObjectWriters()); + partWriters.addAll(super.getCatchAllWriters()); + } + return new MultipartHttpMessageWriter(partWriters); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MultipartIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MultipartIntegrationTests.java index b72cfdc3bd..f3dae0600d 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MultipartIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/MultipartIntegrationTests.java @@ -30,14 +30,11 @@ import reactor.test.StepVerifier; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.codec.CharSequenceEncoder; import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.codec.ResourceHttpMessageWriter; -import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.multipart.FilePart; import org.springframework.http.codec.multipart.FormFieldPart; import org.springframework.http.codec.multipart.MultipartHttpMessageReader; @@ -55,7 +52,6 @@ import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.config.EnableWebFlux; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.ExchangeStrategies; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; @@ -70,16 +66,7 @@ public class MultipartIntegrationTests extends AbstractHttpHandlerIntegrationTes @Before public void setup() throws Exception { super.setup(); - - ExchangeStrategies strategies = ExchangeStrategies.builder().defaultCodecs(configurer -> - configurer.multipartCodecs() - .encoder(CharSequenceEncoder.allMimeTypes()) - .writer(new ResourceHttpMessageWriter()) - .encoder(new Jackson2JsonEncoder())).build(); - - this.webClient = WebClient.builder().baseUrl("http://localhost:" + this.port) - .exchangeStrategies(strategies) - .build(); + this.webClient = WebClient.create("http://localhost:" + this.port); }