spring-boot icon indicating copy to clipboard operation
spring-boot copied to clipboard

Upgrade to SLF4J 2.0 and Logback 1.4

Open wilkinsona opened this issue 6 years ago • 66 comments

With thanks to @rwinch, I've just learned that Boot doesn't work with Logback 1.3 (still in alpha). It fails on launch with the following exception:

java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:273)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:99)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:191)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:170)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:68)
    at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)

StaticLoggerBinder was removed in this commit which appears to be part of a broader effort to provide Jigsaw modules for SLF4J and Logback.

wilkinsona avatar Mar 27 '18 14:03 wilkinsona

Logback 1.3 is still in alpha so I think we should push this back to Spring Boot 2.2

philwebb avatar Sep 11 '18 16:09 philwebb

Apparently the extension module of SLF4J prior to 1.8.0-beta2 contains a security vulnerability (see https://nvd.nist.gov/vuln/detail/CVE-2018-8088#VulnChangeHistorySection). As such, I wouldn't consider this ticket just an enhancement anymore. What do you think?

aprantl avatar Dec 17 '18 09:12 aprantl

@aprantl slf4j-ext and slf4j-api are separate modules and Spring Boot itself does not depend on the module that holds the vulnerability. An application that only depends on slf4j-api is not at risk.

snicoll avatar Dec 17 '18 09:12 snicoll

@snicoll Thanks for the quick reply. What would you recommend if an application based on Spring Boot relies on the extension module in its custom code? I guess the ext-module cannot be updated to 1.8.0-beta2 without dependency-managing the entire SLF4J and logback framework. Which again would not be possible considering the issue above.

aprantl avatar Dec 17 '18 11:12 aprantl

If you're not using EventData then my understanding is that you're not vulnerable even if you have slf4j-ext on the classpath. You should confirm that with the SLF4J team though.

wilkinsona avatar Dec 17 '18 11:12 wilkinsona

It would be great if you can solve this issue. We use dependency-check in our security pipelines and today all of them stopped due to this high severity vulnerability.

Thanks!

jhigueras avatar Dec 17 '18 21:12 jhigueras

@jhigueras as we've already mentioned, this is a false positive in the security check unless you happen to use slf4j-ext directly.

snicoll avatar Dec 18 '18 07:12 snicoll

@jhigueras There’s nothing for us to solve at this time.

If you are only using slf4j-api you are not at risk. If your dependency check is still reporting an issue then it’s there that a possible solution lies as it should not be doing so.

If you are using slf4j-ext then that is out of our control but you still have a few options. You may want to check that you are not using EventData and verify that you are therefore not at risk, explore removing the dependency from your application, or upgrade to an SLF4J 1.8 beta. We cannot do the upgrade at this time as we do not want to force everyone to use a beta version of a dependency.

wilkinsona avatar Dec 18 '18 07:12 wilkinsona

Thanks, we will add the exception to the false-positives list so.

jhigueras avatar Dec 18 '18 07:12 jhigueras

We're making a final push for Java 9+ support and this issue is blocking us. Are there any workarounds until this is fixed?

Baring that, is this feature scheduled?

cowwoc avatar Mar 29 '19 15:03 cowwoc

We cannot schedule this feature as SLF4J 1.8 and Logback 1.3 have not yet been released.

You have a couple options:

  1. Do not use the module path. It provides minimal, if any, benefits to a typical Spring Boot application. You are probably better off avoiding it until the broader ecosystem has caught up.
  2. Try using Log4j2 instead of Logback.

wilkinsona avatar Mar 29 '19 15:03 wilkinsona

Sadly, part of the reason that "the broader ecosystem has [not] caught up" is that frameworks like spring boot have not expended the necessary effort to add support themselves. Everyone is waiting for everyone else to move forward.

I've personally contributed a lot of my time getting the Maven ecosystem up-to-speed and now it finally seems that Java Modules are well supported there. But the rest of the ecosystem needs to do the same.

As an aside, I've been using slf4j 1.8 and logback 1.3 for month now without any problems so I urge you to add support without waiting for a final release. As far as I can tell, the releases are solid.

cowwoc avatar Mar 30 '19 16:03 cowwoc

I suggested above that you consider using Log4j2 but you chose to ignore that constructive suggestion and called into question our efforts instead. We have expended a considerable amount of effort supporting Java 9, 10, 11 and, most recently 12. We have also fixed issues caused by the module path. Unfortunately we can only do so much and cannot justify spending time and introducing complexity to support something that is still in alpha.

If you cannot or do not want to try Log4j2, you also have the option of disabling Boot’s logging system and using Logback 1.3 alphas.

wilkinsona avatar Mar 30 '19 20:03 wilkinsona

Unfortunately we can only do so much and cannot justify spending time and introducing complexity to support something that is still in alpha.

Understood.

If you cannot or do not want to try Log4j2, you also have the option of disabling Boot’s logging system and using Logback 1.3 alphas.

Interesting. Can you please clarify how this would work? If I disable Boot's logging system, where will the logs go? Certainly I can use Logback for my own code but is there a way to direct Boot's logging to use Logback?

Alternatively, I'm thinking I should keep Boot's logging enabled, force it to use JUL and use jul-to-slf4j to redirect to logback. What do you think?

cowwoc avatar Mar 31 '19 00:03 cowwoc

@cowwoc If you set a system property with org.springframework.boot.logging.LoggingSystem=NONE then Spring Boot's deeper logging integration will be disabled. This means you won't be able to do things like set logging levels in application.properties.

Setting that property will not disable the actual logging that spring boot does itself. Those are performed via Apache Commons Logging (usually Spring's own fork) and will ultimately end up being routed to Log4J, SLF4J, or JUL depending on what's on the classpath. You'll need to actually configure your logging system yourself (for example with logback.xml) and define the loggers you want. If you want to replicate the config we provide out the box, take a look at the XML here.

philwebb avatar Apr 04 '19 19:04 philwebb

@philwebb It would work. Is there any harm in forcing JUL support and redirecting that to slf4j? Isn't that better since then application.properties integration would still work?

cowwoc avatar Apr 04 '19 19:04 cowwoc

@cowwoc That's certainly an option, but I'm not sure how well it work as I've never tested that scenario. Specifically, I'm not sure if calling Logger.getLogger(loggerName).setLevel(...) will propagate to the underlying Logback logger.

philwebb avatar Apr 04 '19 19:04 philwebb

I am facing the same problem in my OSS project that I migrated to JPMS entirely. The problem ist that there seems no way to make it work with spring-boot currently. I can not even disable LogbackLoggingSystem and make spring-boot log to jul instead. It seems to be hardwired inside spring-boot that if logback is found on the classpath that StaticLoggerBinder is loaded what has been removed from logback. I can imagine that it is really tricky to support all this messy variants with Junit4 vs. 5, classpath vs. modulepath, etc. Some OSS projects IMHO seem to tend making breaking changes without considering impact vs. benefit (e.g. junit, spring-data, etc.).

hohwille avatar May 10 '20 14:05 hohwille

I can not even disable LogbackLoggingSystem

Disabling or changing the LoggingSystem that Spring Boot uses is possible and documented in the reference guide.

snicoll avatar May 10 '20 14:05 snicoll

Disabling or changing the LoggingSystem that Spring Boot uses is possible and documented in the reference guide.

Thanks for the hint. Indeed it works when I launch my test with

-Dorg.springframework.boot.logging.LoggingSystem=none

and I still get the log output.

However, I need the test to be portable, run by anybody in maven, any IDE, etc. I tried this:

@SpringBootTest(classes = TestApp.class, properties = "org.springframework.boot.logging.LoggingSystem=none", webEnvironment = WebEnvironment.RANDOM_PORT)

But it has to be set as a system property in the boostrapping.

hohwille avatar May 10 '20 15:05 hohwille

If you know that users of your project will never want to use Spring Boot's logging system, you can use an ApplicationListener, registered in spring.factories and with higher precedence than org.springframework.boot.context.logging.LoggingApplicationListener, to set the system property in response to an ApplicationStartingEvent.

wilkinsona avatar May 10 '20 15:05 wilkinsona

As a side note: The SLF4J 1.8 beta seems to work with Logback 1.2.3, if you return StaticLoggerBinder.getSingleton().getLoggerFactory() in your custom SLF4JServiceProvider getLoggerFactory(..) method.

skjolber avatar Jan 29 '21 11:01 skjolber

This has become more important for Spring Boot 3.0 and applications using an SMTP appender. In Logback 1.2, the SMTP appender uses javax.mail classes from Java EE 8. The Logback 1.3 alphas have moved to the jakarta.mail classes that are compatible with Jakarta EE 9.

wilkinsona avatar Jan 24 '22 11:01 wilkinsona

Logback 1.3 has removed InPlayListener which is used by our SpringProfileAction.

wilkinsona avatar Jan 24 '22 12:01 wilkinsona

This has become more important for Spring Boot 3.0

Another example is ch.qos.logback.classic.helpers.MDCInsertingServletFilter. In logback version 1.2.10, included in Spring Boot 3.0.0-M1, that class references javax.servlet.Filter which isn't available.

candrews avatar Jan 26 '22 19:01 candrews

Thanks, @candrews.

Logback moved to jakarta.servlet in 1.3.0-alpha11.

wilkinsona avatar Jan 26 '22 20:01 wilkinsona

@ceki We have an InPlayListener implementation in Spring Boot. If you have the time, could you please advise on how we would implement it on top of Logback 1.3?

wilkinsona avatar Apr 06 '22 15:04 wilkinsona

@wilkinsona Logback 1.3 aims for 1) less confusing configuration code 2) allow for other ways to process configuration. Consequently, the XML processing now creates a model of the configuration which is XML agnostic. Once created, the model is processed to configure logback.

Having said this, logback 1.3 does not currently support conditionals. For example. IfAction/ThenAction/ElseAction no longer exist. SpringProfileAction is rather similar to IfAction/ThenAction.

To cut a long story short, logback 1.3 needs to add support for conditional processing. I have created https://jira.qos.ch/browse/LOGBACK-1625 for this.

ceki avatar Apr 06 '22 17:04 ceki

Thanks, @ceki. I'll keep an eye on that issue. I'd be happy to try to reimplement our SpringProfileAction based on a snapshot when the time comes.

wilkinsona avatar Apr 07 '22 09:04 wilkinsona

Hey, sorry to bother you but 1.3.0-alpha version of logback is getting more and more new feature and we are a bit in trouble right now because of the following issue: https://jira.qos.ch/browse/LOGBACK-1421 We really want this performance improvement in production because it greatly affects our performance right now (confirmed by thread dumps) but just can't do it because we're kinda heavily dependent on spring-logback things and just cannot simply add new property to the JAVA_OPTS and get rid of all the features that spring provides for logging. Otherwise it would be cool for us if logback-team (@ceki) will be able to copy some important features implementation (related to security / performance) to 1.2.X branch as well till the moment it'll be possible to simply update spring boot version. Thanks.

ruslangm avatar Apr 18 '22 16:04 ruslangm