diff --git a/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java b/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java index f955acc53857..dcf9d44e5923 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java +++ b/spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java @@ -122,6 +122,8 @@ abstract static class DefaultBuilder { @Nullable Consumer> configurer; + @Nullable Consumer>> convertersListConfigurer; + @Nullable HttpMessageConverter kotlinJsonConverter; @Nullable HttpMessageConverter jsonConverter; @@ -226,6 +228,10 @@ void addMessageConverterConfigurer(Consumer> configurer) this.configurer = (this.configurer != null) ? configurer.andThen(this.configurer) : configurer; } + void addMessageConvertersListConfigurer(Consumer>> configurer) { + this.convertersListConfigurer = (this.convertersListConfigurer != null) ? convertersListConfigurer.andThen(this.convertersListConfigurer) : configurer; + } + List> getBaseConverters() { List> converters = new ArrayList<>(); if (this.byteArrayConverter != null) { @@ -442,6 +448,12 @@ public ClientBuilder configureMessageConverters(Consumer return this; } + @Override + public ClientBuilder configureMessageConvertersList(Consumer>> configurer) { + addMessageConvertersListConfigurer(configurer); + return this; + } + @Override public HttpMessageConverters build() { if (this.registerDefaults) { @@ -466,6 +478,10 @@ public HttpMessageConverters build() { if (this.configurer != null) { allConverters.forEach(this.configurer); } + if (this.convertersListConfigurer != null) { + this.convertersListConfigurer.accept(allConverters); + } + return new DefaultHttpMessageConverters(allConverters); } } @@ -539,6 +555,12 @@ public ServerBuilder configureMessageConverters(Consumer return this; } + @Override + public ServerBuilder configureMessageConvertersList(Consumer>> configurer) { + addMessageConvertersListConfigurer(configurer); + return this; + } + @Override public HttpMessageConverters build() { if (this.registerDefaults) { @@ -567,6 +589,10 @@ public HttpMessageConverters build() { if (this.configurer != null) { allConverters.forEach(this.configurer); } + if (this.convertersListConfigurer != null) { + this.convertersListConfigurer.accept(allConverters); + } + return new DefaultHttpMessageConverters(allConverters); } } diff --git a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java index 61bc33ab9bc4..68a6a859cbfc 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java +++ b/spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java @@ -16,6 +16,7 @@ package org.springframework.http.converter; +import java.util.List; import java.util.function.Consumer; /** @@ -172,6 +173,12 @@ interface Builder> { */ T configureMessageConverters(Consumer> configurer); + /** + * Add a consumer for configuring the message converters list just before it's returned. + * @param configurer the configurer to use + */ + T configureMessageConvertersList(Consumer>> configurer); + /** * Build and return the {@link HttpMessageConverters} instance configured by this builder. */ diff --git a/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java b/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java index f939e9b227ac..8e15bbe703a3 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java @@ -17,9 +17,11 @@ package org.springframework.http.converter; import java.io.IOException; +import java.util.Comparator; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import org.assertj.core.util.Lists; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -211,6 +213,31 @@ void shouldConfigureConverter() { assertThat(customConverter.processed).isTrue(); } + @Test + void shouldConfigureConverterOrder() { + var customConverter = new CustomHttpMessageConverter(); + var converted = HttpMessageConverters.forClient() + .addCustomConverter(customConverter) + .configureMessageConvertersList(converter -> { + converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? 1 : -1)); + }).build(); + + var messageConvertersBack = Lists.newArrayList(converted); + assertThat(messageConvertersBack.size()).isGreaterThan(1); + assertThat(messageConvertersBack.get(messageConvertersBack.size() - 1).getClass()).isEqualTo(CustomHttpMessageConverter.class); + + var convertedFront = HttpMessageConverters.forClient() + .addCustomConverter(customConverter) + .configureMessageConvertersList(converter -> { + converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? -1 : 1)); + }).build(); + + var messageConvertersFront = Lists.newArrayList(convertedFront); + assertThat(messageConvertersFront.get(0).getClass()).isEqualTo(CustomHttpMessageConverter.class); + assertThat(messageConvertersFront.size()).isGreaterThan(1); + + } + } @@ -319,6 +346,31 @@ void shouldConfigureConverter() { assertThat(customConverter.processed).isTrue(); } + + @Test + void shouldConfigureConverterOrder() { + var customConverter = new CustomHttpMessageConverter(); + var converted = HttpMessageConverters.forServer() + .addCustomConverter(customConverter) + .configureMessageConvertersList(converter -> { + converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? 1 : -1)); + }).build(); + + var messageConvertersBack = Lists.newArrayList(converted); + assertThat(messageConvertersBack.size()).isGreaterThan(1); + assertThat(messageConvertersBack.get(messageConvertersBack.size() - 1).getClass()).isEqualTo(CustomHttpMessageConverter.class); + + var convertedFront = HttpMessageConverters.forServer() + .addCustomConverter(customConverter) + .configureMessageConvertersList(converter -> { + converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? -1 : 1)); + }).build(); + + var messageConvertersFront = Lists.newArrayList(convertedFront); + assertThat(messageConvertersFront.size()).isGreaterThan(1); + assertThat(messageConvertersFront.get(0).getClass()).isEqualTo(CustomHttpMessageConverter.class); + + } } @SuppressWarnings("unchecked")