-
Notifications
You must be signed in to change notification settings - Fork 41.9k
Jackson2HttpMessageConvertersConfiguration uses ConditionOn Jackson3 XMLMapper class #49015
Description
Short description:
With SpringBoot 4, Jackson2HttpMessageConvertersConfiguration contains a nested Configuration class (MappingJackson2XmlHttpMessageConverterConfiguration) to provide Jackson2XmlMessageConvertersCustomizer as soon as xml-dataformat is present. The condition
@ConditionalOnClass(tools.jackson.dataformat.xml.XmlMapper.class)
uses (accidentely) the Jackson3 XmlMapper class, which can lead to NoClassDefFoundErrors
Details
Many of our applications still require Jackson2ObjectMapperBuilder for the programmatic deserialization/serialization of objects. While we switched to Jackson3 by default when we upgraded to Spring Boot 4, we still provide a Jackson2ObjectMapperBuilder bean in the spring context for compatibility reasons. (We do not set spring.http.converters.preferred-json-mapper: jackson2).
This triggers the Jackson2HttpMessageConvertersConfiguration and leads to NoClassDefFoundErrors as soon as Jackson3 xml-dataformat is present.
Sample Code to reproduce the exception
pom.xml
<!-- Jackson 3 Deps -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jackson</artifactId>
</dependency>
<dependency>
<groupId>tools.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- for Jackson2ObjectMapperBuilder -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
DemoApplication.class
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// SB35 compatibility bean
@Bean
@Scope("prototype")
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(){
return new Jackson2ObjectMapperBuilder();
}
}
Exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.http.converter.autoconfigure.Jackson2HttpMessageConvertersConfiguration$Jackson2XmlMessageConvertersCustomizer]: Factory method 'mappingJackson2XmlHttpMessageConverter' threw exception with message: com/fasterxml/jackson/dataformat/xml/XmlMapper
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:183) ~[spring-beans-7.0.3.jar:7.0.3]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:72) ~[spring-beans-7.0.3.jar:7.0.3]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:152) ~[spring-beans-7.0.3.jar:7.0.3]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-7.0.3.jar:7.0.3]
... 65 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/dataformat/xml/XmlMapper
at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2ObjectMapperBuilder.java:684) ~[spring-web-7.0.3.jar:7.0.3]
at org.springframework.boot.http.converter.autoconfigure.Jackson2HttpMessageConvertersConfiguration$MappingJackson2XmlHttpMessageConverterConfiguration.mappingJackson2XmlHttpMessageConverter(Jackson2HttpMessageConvertersConfiguration.java:73) ~[spring-boot-http-converter-4.0.2.jar:4.0.2]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:155) ~[spring-beans-7.0.3.jar:7.0.3]
... 68 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.dataformat.xml.XmlMapper
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490) ~[na:na]
... 73 common frames omitted