camunda-community-hub / spring-zeebe

DEPRECATED. Easily use the Zeebe Java Client in your Spring or Spring Boot projects
Apache License 2.0
205 stars 119 forks source link

Resilience4j dependency pulls in a transitive slf4j which is too old #499

Closed berndruecker closed 1 month ago

berndruecker commented 11 months ago

Running a plain worker (like https://github.com/camunda/camunda-platform-tutorials/tree/main/orchestrate-microservices/worker-java) on spring-zeebe 8.2.x or 8.3.0 will result in the following exception:

[WARNING]
java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.helpers.NOPLoggerFactory loaded from file:/C:/Users/ruecker/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.helpers.NOPLoggerFactory
    at org.springframework.util.Assert.instanceCheckFailed (Assert.java:713)
    at org.springframework.util.Assert.isInstanceOf (Assert.java:632)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext (LogbackLoggingSystem.java:389)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize (LogbackLoggingSystem.java:123)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent (LoggingApplicationListener.java:238)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent (LoggingApplicationListener.java:220)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener (SimpleApplicationEventMulticaster.java:174)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener (SimpleApplicationEventMulticaster.java:167)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent (SimpleApplicationEventMulticaster.java:145)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent (SimpleApplicationEventMulticaster.java:133)
    at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent (EventPublishingRunListener.java:136)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting (EventPublishingRunListener.java:75)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0 (SpringApplicationRunListeners.java:54)
    at java.lang.Iterable.forEach (Iterable.java:75)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners (SpringApplicationRunListeners.java:118)
    at org.springframework.boot.SpringApplicationRunListeners.starting (SpringApplicationRunListeners.java:54)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:307)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1309)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1298)
    at io.camunda.getstarted.tutorial.Worker.main (Worker.java:16)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:279)
    at java.lang.Thread.run (Thread.java:833)

This is because in this plain worker, no Maven BOM is used to set versions, an thus resilience4j brings in a slf4j in an too old version (1.7.3 instead of 2.0.x):

[INFO]    \- io.github.resilience4j:resilience4j-retry:jar:2.1.0:compile
[INFO]       +- io.github.resilience4j:resilience4j-core:jar:2.1.0:compile
[INFO]       \- org.slf4j:slf4j-api:jar:1.7.30:compile

When manually overwriting this version to 2.0.9 or use a Spring BOM in the worker, the problem goes away:

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>
        <dependency>
            <groupId>io.camunda</groupId>
            <artifactId>spring-zeebe-starter</artifactId>
            <version>8.3.0</version>
        </dependency>
    </dependencies>

But I think we should actually let users don't experience this obstacle themselves and thus solve it within Spring Zeebe itself.

berndruecker commented 11 months ago

Which is interesting, because I thought this should solve those kind of problems already: https://github.com/camunda-community-hub/spring-zeebe/blob/main/pom.xml#L60 🤔

berndruecker commented 11 months ago

Labeled it as bug as we either have to fix it or update the get started tutorial - as it does not run out of the box right now

berndruecker commented 11 months ago

I think we should add a dependency to that slf4j-api within the spring-boot-starter project, this way the version is pulled from the dependencyManagement and written to the resulting pom. I will create a PR for it.

I also thought about looking into the Maven Flatten Plugin (https://stackoverflow.com/questions/75510285/dependencymanagement-unfortunately-not-transitive, https://blog.frankel.ch/maven-flatten-plugin/) but restrained from touching too much for now :-)

jonathanlukas commented 11 months ago

There is a way to enforce dependency convergence by using the maven enforcer plugin. This will help cleaning up issues like this.

1nb0und commented 11 months ago

Nice catch, I wasn't encountering this before due to the fact I always include the Spring BOM. I think your approach of adding an explicit dependency looks fine.

I prefer to have that fixed now so prospects will not encounter that issue.

@jonathanlukas Thats interesting will take look at that approach when I get some capacity.

jonathanlukas commented 11 months ago

I would prefer excluding the dependency instead of managing it in our artefact.

1nb0und commented 11 months ago

Added slf4j dependency to enforce correct version on transitive depen…

Could you provide an example on how we can exclude the dependency? From a first thought, we could do that, but then the customer will then be responsible (which I think is an extra work and might be a showstopper for first-time users) for putting the right version in their implementation either by hardcoding a version number, or relying on another dependency that will supersede the old sl4j in our resilience4j

berndruecker commented 11 months ago

You can't exclude slf4j-api as it is used by resilience4j - we just have to make sure the version compatible with the current Spring Boot setup is used.