Browse Source

Configure HttpMessageConverters as a list

This commit adds a new `configureMessageConvertersList` method on the
builder to add/remove/move converters in the resulting list before they
are individually post-processed.

This allows to re-introduce a behavior that was missing with the new
contract: the ability to append a converter at the end of the list.

See gh-36083

Signed-off-by: hayden.rear <hayden.rear@gmail.com>
pull/36110/head
hayden.rear 1 month ago committed by Brian Clozel
parent
commit
c7413cbdfc
  1. 26
      spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java
  2. 7
      spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java
  3. 44
      spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java

26
spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java

@ -122,6 +122,8 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -122,6 +122,8 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
@Nullable Consumer<HttpMessageConverter<?>> configurer;
@Nullable Consumer<List<HttpMessageConverter<?>>> convertersListConfigurer;
@Nullable HttpMessageConverter<?> kotlinJsonConverter;
@Nullable HttpMessageConverter<?> jsonConverter;
@ -226,6 +228,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -226,6 +228,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
this.configurer = (this.configurer != null) ? configurer.andThen(this.configurer) : configurer;
}
void addMessageConvertersListConfigurer(Consumer<List<HttpMessageConverter<?>>> configurer) {
this.convertersListConfigurer = (this.convertersListConfigurer != null) ? this.convertersListConfigurer.andThen(this.convertersListConfigurer) : configurer;
}
List<HttpMessageConverter<?>> getBaseConverters() {
List<HttpMessageConverter<?>> converters = new ArrayList<>();
if (this.byteArrayConverter != null) {
@ -442,6 +448,12 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -442,6 +448,12 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
return this;
}
@Override
public ClientBuilder configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer) {
addMessageConvertersListConfigurer(configurer);
return this;
}
@Override
public HttpMessageConverters build() {
if (this.registerDefaults) {
@ -466,6 +478,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -466,6 +478,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
if (this.configurer != null) {
allConverters.forEach(this.configurer);
}
if (this.convertersListConfigurer != null) {
this.convertersListConfigurer.accept(allConverters);
}
return new DefaultHttpMessageConverters(allConverters);
}
}
@ -539,6 +555,12 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -539,6 +555,12 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
return this;
}
@Override
public ServerBuilder configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer) {
addMessageConvertersListConfigurer(configurer);
return this;
}
@Override
public HttpMessageConverters build() {
if (this.registerDefaults) {
@ -567,6 +589,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { @@ -567,6 +589,10 @@ class DefaultHttpMessageConverters implements HttpMessageConverters {
if (this.configurer != null) {
allConverters.forEach(this.configurer);
}
if (this.convertersListConfigurer != null) {
this.convertersListConfigurer.accept(allConverters);
}
return new DefaultHttpMessageConverters(allConverters);
}
}

7
spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.http.converter;
import java.util.List;
import java.util.function.Consumer;
/**
@ -172,6 +173,12 @@ public interface HttpMessageConverters extends Iterable<HttpMessageConverter<?>> @@ -172,6 +173,12 @@ public interface HttpMessageConverters extends Iterable<HttpMessageConverter<?>>
*/
T configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer);
/**
* Add a consumer for configuring the message converters list just before it's returned.
* @param configurer the configurer to use
*/
T configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer);
/**
* Build and return the {@link HttpMessageConverters} instance configured by this builder.
*/

44
spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java

@ -17,9 +17,11 @@ @@ -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,27 @@ class DefaultHttpMessageConvertersTests { @@ -211,6 +213,27 @@ class DefaultHttpMessageConvertersTests {
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 +342,27 @@ class DefaultHttpMessageConvertersTests { @@ -319,6 +342,27 @@ class DefaultHttpMessageConvertersTests {
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")

Loading…
Cancel
Save