From b9e190e313cd49c895f92626a37e170b42d827e8 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 16 Feb 2026 18:48:26 +0100 Subject: [PATCH] Fix HttpMessageConverters configurers support This commit fixes the `configureMessageConverters` and `configureMessageConvertersList` behavior. `configureMessageConverters` was not executing consumers in their order of registration (but in the reverse order). `configureMessageConvertersList` was not executing multiple consumers and was instead executing the first consumer multiple times. This commit fixes both issues. Fixes gh-36332 --- .../DefaultHttpMessageConverters.java | 4 +- .../DefaultHttpMessageConvertersTests.java | 40 ++++++++++++++----- 2 files changed, 31 insertions(+), 13 deletions(-) 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 0bd936c977c..0c50bb36955 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 @@ -225,12 +225,12 @@ class DefaultHttpMessageConverters implements HttpMessageConverters { } void addMessageConverterConfigurer(Consumer> configurer) { - this.configurer = (this.configurer != null) ? configurer.andThen(this.configurer) : configurer; + this.configurer = (this.configurer != null) ? this.configurer.andThen(configurer) : configurer; } void addMessageConvertersListConfigurer(Consumer>> configurer) { this.convertersListConfigurer = (this.convertersListConfigurer != null) ? - this.convertersListConfigurer.andThen(this.convertersListConfigurer) : configurer; + this.convertersListConfigurer.andThen(configurer) : configurer; } List> getBaseConverters() { 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 a9196ce44c5..dcef8369b35 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 @@ -210,22 +210,31 @@ class DefaultHttpMessageConvertersTests { .addCustomConverter(customConverter) .configureMessageConverters(converter -> { if (converter instanceof CustomHttpMessageConverter custom) { - custom.processed = true; + assertThat(custom.processCount).isZero(); + custom.processCount++; + } + }) + .configureMessageConverters(converter -> { + if (converter instanceof CustomHttpMessageConverter custom) { + assertThat(custom.processCount).isEqualTo(1); + custom.processCount++; } }).build(); - assertThat(customConverter.processed).isTrue(); + assertThat(customConverter.processCount).isEqualTo(2); } @Test void shouldAppendCustomConverterToList() { - var customConverter = new CustomHttpMessageConverter(); + var firstCustom = new CustomHttpMessageConverter(); + var secondCustom = new CustomHttpMessageConverter(); var messageConverters = HttpMessageConverters.forClient() .registerDefaults() - .configureMessageConvertersList(converters -> converters.add(customConverter)) + .configureMessageConvertersList(converters -> converters.add(firstCustom)) + .configureMessageConvertersList(converters -> converters.add(secondCustom)) .build(); - assertThat(messageConverters).last().isInstanceOf(CustomHttpMessageConverter.class); + assertThat(messageConverters).containsSequence(firstCustom, secondCustom); } } @@ -336,22 +345,31 @@ class DefaultHttpMessageConvertersTests { .addCustomConverter(customConverter) .configureMessageConverters(converter -> { if (converter instanceof CustomHttpMessageConverter custom) { - custom.processed = true; + assertThat(custom.processCount).isZero(); + custom.processCount++; + } + }) + .configureMessageConverters(converter -> { + if (converter instanceof CustomHttpMessageConverter custom) { + assertThat(custom.processCount).isEqualTo(1); + custom.processCount++; } }).build(); - assertThat(customConverter.processed).isTrue(); + assertThat(customConverter.processCount).isEqualTo(2); } @Test void shouldAppendCustomConverterToList() { - var customConverter = new CustomHttpMessageConverter(); + var firstCustom = new CustomHttpMessageConverter(); + var secondCustom = new CustomHttpMessageConverter(); var messageConverters = HttpMessageConverters.forServer() .registerDefaults() - .configureMessageConvertersList(converters -> converters.add(customConverter)) + .configureMessageConvertersList(converters -> converters.add(firstCustom)) + .configureMessageConvertersList(converters -> converters.add(secondCustom)) .build(); - assertThat(messageConverters).last().isInstanceOf(CustomHttpMessageConverter.class); + assertThat(messageConverters).containsSequence(firstCustom, secondCustom); } } @@ -365,7 +383,7 @@ class DefaultHttpMessageConvertersTests { static class CustomHttpMessageConverter extends AbstractHttpMessageConverter { - boolean processed = false; + int processCount; @Override protected boolean supports(Class clazz) {