Configure custom converters ahead in HttpMessageConverters

This commit aligns `HttpMessageConverters` with the WebFlux codecs
configuration by adding custom converters first, before the
auto-detected and well-known ones.

This is a general approach in Spring Framework, where custom
implementations are more likely to handle specific uses cases and should
be involved before considering the more general implementations.

Fixes gh-35177
This commit is contained in:
Brian Clozel
2025-07-10 16:56:06 +02:00
parent 440bf94cee
commit 0a705f467d
3 changed files with 73 additions and 17 deletions
@@ -150,7 +150,21 @@ class DefaultHttpMessageConvertersTests {
void registerCustomMessageConverter() {
var converters = HttpMessageConverters.create()
.additionalMessageConverter(new CustomHttpMessageConverter()).build();
assertThat(converters.forClient()).hasExactlyElementsOfTypes(AllEncompassingFormHttpMessageConverter.class, CustomHttpMessageConverter.class);
assertThat(converters.forClient()).hasExactlyElementsOfTypes(CustomHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class);
}
@Test
void registerCustomMessageConverterAheadOfDefaults() {
var converters = HttpMessageConverters.withDefaults()
.additionalMessageConverter(new CustomHttpMessageConverter()).build();
assertThat(converters.forClient()).hasExactlyElementsOfTypes(
CustomHttpMessageConverter.class, ByteArrayHttpMessageConverter.class,
StringHttpMessageConverter.class, ResourceHttpMessageConverter.class,
AllEncompassingFormHttpMessageConverter.class,
JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class,
JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class,
JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class,
AtomFeedHttpMessageConverter.class, RssChannelHttpMessageConverter.class);
}
@Test
@@ -224,7 +238,22 @@ class DefaultHttpMessageConvertersTests {
void registerCustomMessageConverter() {
var converters = HttpMessageConverters.create()
.additionalMessageConverter(new CustomHttpMessageConverter()).build();
assertThat(converters.forServer()).hasExactlyElementsOfTypes(AllEncompassingFormHttpMessageConverter.class, CustomHttpMessageConverter.class);
assertThat(converters.forServer()).hasExactlyElementsOfTypes(CustomHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class);
}
@Test
void registerCustomMessageConverterAheadOfDefaults() {
var converters = HttpMessageConverters.withDefaults()
.additionalMessageConverter(new CustomHttpMessageConverter()).build();
assertThat(converters.forServer()).hasExactlyElementsOfTypes(
CustomHttpMessageConverter.class,
ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class,
ResourceHttpMessageConverter.class, ResourceRegionHttpMessageConverter.class,
AllEncompassingFormHttpMessageConverter.class,
JacksonJsonHttpMessageConverter.class, JacksonSmileHttpMessageConverter.class,
JacksonCborHttpMessageConverter.class, JacksonYamlHttpMessageConverter.class,
JacksonXmlHttpMessageConverter.class, KotlinSerializationProtobufHttpMessageConverter.class,
AtomFeedHttpMessageConverter.class, RssChannelHttpMessageConverter.class);
}
@Test