From fd34f80bf1549bf383ebf6897fac97bdf6ed0367 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 26 Jun 2025 22:31:31 -0700 Subject: [PATCH] Restore HttpMessageConverters ordering Temporarily add reordering logic to `HttpMessageConverters` to restore the Spring Boot 3.5 order. See gh-46221 --- .../http/HttpMessageConverters.java | 32 +++++++++++++++++-- .../http/HttpMessageConvertersTests.java | 12 +++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConverters.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConverters.java index 774306dfa75..1a24ccbe9d6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConverters.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConverters.java @@ -26,8 +26,11 @@ import java.util.List; import java.util.Map; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; import org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter; +import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.util.ClassUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; @@ -184,13 +187,14 @@ public class HttpMessageConverters implements Iterable> List> converters = new ArrayList<>(); if (ClassUtils.isPresent("org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport", null)) { - converters.addAll(new WebMvcConfigurationSupport() { + List> webMvcConverters = new WebMvcConfigurationSupport() { public List> defaultMessageConverters() { return super.getMessageConverters(); } - }.defaultMessageConverters()); + }.defaultMessageConverters(); + converters.addAll(reorderAllEncompassingFormHttpMessageConverterBeforeJackson(webMvcConverters)); } else { converters.addAll(new RestTemplate().getMessageConverters()); @@ -199,6 +203,30 @@ public class HttpMessageConverters implements Iterable> return converters; } + @SuppressWarnings("removal") + private List> reorderAllEncompassingFormHttpMessageConverterBeforeJackson( + List> converters) { + List> reordered = new ArrayList<>(); + for (int i = 0; i < converters.size(); i++) { + HttpMessageConverter converter = converters.get(i); + if (converter == null) { + continue; + } + if (converter instanceof MappingJackson2XmlHttpMessageConverter + || converter instanceof MappingJackson2HttpMessageConverter + || converter instanceof MappingJackson2CborHttpMessageConverter) { + for (int j = i; j < converters.size(); j++) { + if (converters.get(j) instanceof AllEncompassingFormHttpMessageConverter) { + reordered.add(converters.get(j)); + converters.set(j, null); + } + } + } + reordered.add(converter); + } + return reordered; + } + @SuppressWarnings("removal") private void reorderXmlConvertersToEnd(List> converters) { List> xml = new ArrayList<>(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersTests.java index e70674676f1..1e475098368 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersTests.java @@ -56,9 +56,9 @@ class HttpMessageConvertersTests { } assertThat(converterClasses).containsExactly(ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, - ResourceRegionHttpMessageConverter.class, MappingJackson2HttpMessageConverter.class, - MappingJackson2CborHttpMessageConverter.class, MappingJackson2YamlHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class, MappingJackson2XmlHttpMessageConverter.class); + ResourceRegionHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class, + MappingJackson2HttpMessageConverter.class, MappingJackson2CborHttpMessageConverter.class, + MappingJackson2YamlHttpMessageConverter.class, MappingJackson2XmlHttpMessageConverter.class); } @Test @@ -126,9 +126,9 @@ class HttpMessageConvertersTests { } assertThat(converterClasses).containsExactly(ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class, ResourceHttpMessageConverter.class, - ResourceRegionHttpMessageConverter.class, MappingJackson2HttpMessageConverter.class, - MappingJackson2CborHttpMessageConverter.class, MappingJackson2YamlHttpMessageConverter.class, - AllEncompassingFormHttpMessageConverter.class); + ResourceRegionHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class, + MappingJackson2HttpMessageConverter.class, MappingJackson2CborHttpMessageConverter.class, + MappingJackson2YamlHttpMessageConverter.class); } @Test