others-how to solve Failed to load class org.slf4j.impl.StaticLoggerBinder problem ?

Problem

When we run a java application, sometimes, we get this error or warning message:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
14:58:59: Task execution finished 'Hello1.main()'.

The core error is :

Failed to load class "org.slf4j.impl.StaticLoggerBinder".

Why do this error happen?

Environment

  • jdk 8
  • gradle 6.x

Our build.gradle is as follows:

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

dependencies {
    implementation 'io.codearte.jfairy:jfairy:0.5.9'
}

Reason

There are no log implementation libraries in your classpath, so slf4j can not use the specific logger to print logs, it can only use the default no-operation(NOP) logger.

And according to stackoverflow.com, the reason is:

Failed to load class org.slf4j.impl.StaticLoggerBinder

This warning message is reported when the org.slf4j.impl.StaticLoggerBinder class could not be loaded into memory. This happens when no appropriate SLF4J binding could be found on the class path. Placing one (and only one) of slf4j-nop.jar slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar or logback-classic.jar on the class path should solve the problem.

Note that slf4j-api versions 2.0.x and later use the ServiceLoader mechanism. Backends such as logback 1.3 and later which target slf4j-api 2.x, do not ship with org.slf4j.impl.StaticLoggerBinder. If you place a logging backend which targets slf4j-api 2.0.x, you need slf4j-api-2.x.jar on the classpath. See also relevant faq entry.

SINCE 1.6.0 As of SLF4J version 1.6, in the absence of a binding, SLF4J will default to a no-operation (NOP) logger implementation.

If you are responsible for packaging an application and do not care about logging, then placing slf4j-nop.jar on the class path of your application will get rid of this warning message. Note that embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J’s purpose.

What is slf4j?

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time.

It’s a facade for loggers , it’s not a logger by itself. So , we should tell it who is the logger implementation, e.g. the log4j or logback.

Slf4j’s artitecture is as follows:

image-20210130135918019

So the key solution to this problem is tell slf4j who is the logger.

Solution

We can add the logger to slf4j as follows:

Change your build.gradle:

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

dependencies {
    implementation 'io.codearte.jfairy:jfairy:0.5.9'
    implementation 'org.slf4j:slf4j-simple:1.7.30'
}

The most important line is:

implementation 'org.slf4j:slf4j-simple:1.7.30'

The slf4j-simple is simple implementation of Logger that sends all enabled log messages, for all defined loggers, to the console (System.err). The following system properties are supported to configure the behavior of this logger:

Run the app again, the error messages disappear.

It works!