diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java index 5410786e4385..383ebd6c0e37 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -306,7 +306,7 @@ private Field findPropertyNamingStrategyField(String fieldName) { } private void configureModules(Jackson2ObjectMapperBuilder builder) { - builder.modulesToInstall(this.modules.toArray(new Module[0])); + builder.modulesToInstall((modules) -> modules.addAll(this.modules)); } private void configureLocale(Jackson2ObjectMapperBuilder builder) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java index 29dde38a9714..06a937bc7bad 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java @@ -73,6 +73,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import static org.assertj.core.api.Assertions.assertThat; @@ -324,6 +326,16 @@ void moduleBeansAndWellKnownModulesAreRegisteredWithTheObjectMapperBuilder() { }); } + @Test + void customModulesRegisteredByBuilderCustomizerWithHighestPrecedenceShouldBeRetained() { + this.contextRunner.withUserConfiguration(ModuleConfig.class, CustomModuleBuilderCustomizerConfig.class) + .run((context) -> { + ObjectMapper objectMapper = context.getBean(Jackson2ObjectMapperBuilder.class).build(); + assertThat(context.getBean(CustomModule.class).getOwners()).contains(objectMapper); + assertThat(objectMapper.getRegisteredModuleIds()).contains("customizer-module"); + }); + } + @Test void defaultSerializationInclusion() { this.contextRunner.run((context) -> { @@ -592,6 +604,17 @@ Jackson2ObjectMapperBuilderCustomizer customDateFormat() { } + @Configuration(proxyBeanMethods = false) + static class CustomModuleBuilderCustomizerConfig { + + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + Jackson2ObjectMapperBuilderCustomizer customModuleCustomizer() { + return (builder) -> builder.modulesToInstall(new SimpleModule("customizer-module")); + } + + } + @Configuration(proxyBeanMethods = false) static class ObjectMapperBuilderConsumerConfig {