With Spring 3.2.2 I seem to need to add a runtime dependency on Jaxb?
Describe the bug I have to add
runtimeOnly('javax.xml.bind:jaxb-api:2.3.1') {
because("Needed for logstash logback encoder for some reason")
}
to avoid
java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlElement
at com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector.<init>(JaxbAnnotationIntrospector.java:137)
at com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector.<init>(JaxbAnnotationIntrospector.java:124)
at com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule.setupModule(JaxbAnnotationModule.java:98)
at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:879)
at com.fasterxml.jackson.databind.ObjectMapper.registerModules(ObjectMapper.java:1081)
at com.fasterxml.jackson.databind.ObjectMapper.findAndRegisterModules(ObjectMapper.java:1165)
at net.logstash.logback.composite.AbstractCompositeJsonFormatter.createJsonFactory(AbstractCompositeJsonFormatter.java:247)
at net.logstash.logback.composite.AbstractCompositeJsonFormatter.start(AbstractCompositeJsonFormatter.java:117)
at net.logstash.logback.encoder.CompositeJsonEncoder.start(CompositeJsonEncoder.java:129)
at ch.qos.logback.core.model.processor.ImplicitModelHandler.postHandleComplex(ImplicitModelHandler.java:208)
at ch.qos.logback.core.model.processor.ImplicitModelHandler.postHandle(ImplicitModelHandler.java:186)
at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:257)
at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
at ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:90)
at ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:106)
at ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:208)
at org.springframework.boot.logging.logback.SpringBootJoranConfigurator.processModel(SpringBootJoranConfigurator.java:122)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:170)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:287)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:249)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:467)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:244)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:81)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:61)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:189)
To Reproduce Steps to reproduce the behavior:
- Upgraded from
7.3to7.4and switched to Spring Boot3.2.2
Expected behavior A clear and concise description of what you expected to happen.
- I expected not to have to adjust my gradle dependencies
Additional context Add any other context about the problem here.
- logstash-logback-encoder version
- logback version
- jackson version
- java version
java --version
openjdk 17.0.9 2023-10-17
OpenJDK Runtime Environment Homebrew (build 17.0.9+0)
OpenJDK 64-Bit Server VM Homebrew (build 17.0.9+0, mixed mode, sharing)
From my lockfile
ch.qos.logback:logback-classic:1.4.14=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
ch.qos.logback:logback-core:1.4.14=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.3=intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.3=intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.15.3=intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.15.3=intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.15.3=intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.15.3=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.logstash.logback:logstash-logback-encoder:7.4=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
software.amazon.awssdk:third-party-jackson-core:2.22.7=intTestCompileClasspath,intTestImplementation,intTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
The reason is in the Pom.xml
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>${jackson.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
This includes jackson-module-jaxb-annotations-${jackson.version}.jar, which is then automatically discovered by jackson.
Thanks @jowi-ppi - is there any way around it?
That is not exactly correct. The jackson-bom is used in logstash-logback-encoder's dependencyManagement section. Not its dependencies section. Therefore logstash-logback-encoder does not depend on, or require, jackson-module-jaxb-annotations.
This can be confirmed by viewing the runtime dependency tree for logstash-logback-encoder (including optional dependencies).
❯ mvn dependency:tree -Dscope=runtime
[INFO] Scanning for projects...
[INFO]
[INFO] -----------< net.logstash.logback:logstash-logback-encoder >------------
[INFO] Building Logstash Logback Encoder 7.4
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:3.6.0:tree (default-cli) @ logstash-logback-encoder ---
[INFO] net.logstash.logback:logstash-logback-encoder:jar:7.4
[INFO] +- ch.qos.logback:logback-classic:jar:1.3.7:compile
[INFO] | \- org.slf4j:slf4j-api:jar:2.0.4:compile
[INFO] +- ch.qos.logback:logback-access:jar:1.3.7:compile
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.15.2:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.15.2:compile
[INFO] | \- com.fasterxml.jackson.core:jackson-core:jar:2.15.2:compile
[INFO] +- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:jar:2.15.2:compile
[INFO] +- com.fasterxml.jackson.dataformat:jackson-dataformat-smile:jar:2.15.2:compile
[INFO] +- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.15.2:compile
[INFO] | \- org.yaml:snakeyaml:jar:2.0:compile
[INFO] +- com.fasterxml.uuid:java-uuid-generator:jar:4.2.0:compile
[INFO] \- com.lmax:disruptor:jar:3.4.4:compile
By default, logstash-logback-encoder will tell jackson to dynamically discover all available jackson modules on the classpath by calling objectMapper.findAndRegisterModules(), as seen in your stacktrace. In your case, the jackson-module-jaxb-annotations is on your runtime classpath, and jackson is trying to register it, and failing due to one of its required dependencies being missing. Something else in your application (not logstash-logback-encoder) is putting jackson-module-jaxb-annotations on your classpath.
There are a couple solves for this:
- If you do not need the
jackson-module-jaxb-annotationsmodule, then you can find whatever is putting that on your runtime classpath and exclude it. - If you do need
jackson-module-jaxb-annotations, then you'll need to ensure its dependencies are on your runtime classpath.
Alternatively, you can tell logstash-logback-encoder to not configure jackson to find and register modules dynamically (as mentioned here), but then you'll need to register any modules that you do need explicitly.