logfellow / logstash-logback-encoder

Logback JSON encoder and appenders
Apache License 2.0
2.43k stars 407 forks source link

With Spring 3.2.2 I seem to need to add a runtime dependency on Jaxb? #1005

Closed frankjkelly closed 1 month ago

frankjkelly commented 7 months ago

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:

  1. Upgraded from 7.3 to 7.4 and switched to Spring Boot 3.2.2

Expected behavior A clear and concise description of what you expected to happen.

Additional context Add any other context about the problem here.

 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
jowi-ppi commented 7 months ago

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.

frankjkelly commented 7 months ago

Thanks @jowi-ppi - is there any way around it?

philsttr commented 7 months ago

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:

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.