Resolving Java Logging Framework Conflicts in SpringBoot and Dubbo Projects
This article explains why multiple Java logging frameworks often clash in SpringBoot and Dubbo applications, identifies common causes such as transitive dependencies and duplicate versions, and provides step‑by‑step Maven configurations and adaptation techniques to unify logging with SLF4J and Logback.
Introduction
Many developers encounter situations where logs are not printed, Logback is configured but Log4j errors appear, SLF4J reports multiple bindings, Dubbo logs are missing, MyBatis/Hibernate SQL logs are absent, Tomcat generates duplicate log files, or SpringBoot creates multiple log files.
Log Framework Conflicts
These problems are usually caused by the coexistence of multiple logging frameworks or misconfiguration. Common reasons include:
Manually adding several logging jars (e.g., Log4j, Log4j2, Logback, JCL, etc.).
Transitive dependencies that bring in unwanted logging libraries (e.g., Dubbo depends on zkclient, which depends on Log4j).
Multiple versions of the same logging framework coexisting.
Java Logging Frameworks
Java logging consists of two layers: abstraction (facade) and implementation. The main abstractions are SLF4J (Simple Logging Facade for Java) and JCL (Apache Commons Logging); JBoss‑logging is used by JBoss‑related projects. Implementations include Log4j (old, now Log4j2), Log4j2, Logback, and java.util.logging (jul).
SpringBoot + Dubbo Conflict Example
Consider a clean SpringBoot project that only depends on spring-boot-starter . Adding Dubbo with Zookeeper as the registry introduces transitive Log4j dependencies, leading to SLF4J multiple‑binding warnings and Log4j "no appenders" warnings.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.9</version>
</dependency>
</dependencies>Running the application produces errors such as:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/.../logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/.../slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
log4j:WARN No appenders could be found for logger (org.apache.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.The root cause is that Dubbo brings in Log4j (1) while SpringBoot defaults to SLF4J + Logback. To resolve the conflict:
Exclude Log4j from Dubbo dependencies.
Add log4j-over-slf4j to redirect Log4j API calls to SLF4J/Logback.
Remove the slf4j-log4j12 implementation so that only Logback remains as the SLF4J binding.
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.9</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>After these changes the application starts without logging errors, and all frameworks log through the unified Logback implementation.
Log Adaptation Overview
The article also provides a comprehensive diagram showing how each logging framework can be adapted to another using "over" packages (e.g., log4j-over-slf4j , jcl-over-slf4j , log4j-slf4j-impl ) or built‑in bridge implementations. By following the arrows in the diagram you can introduce the appropriate dependency to convert one logging API to the desired implementation.
Conclusion
Key principles for solving logging conflicts:
Unify the project to a single logging implementation.
Remove unnecessary logging dependencies.
If a library must remain, replace its original jar with an "over" variant that forwards calls to the chosen implementation.
For frameworks that cannot be bridged, use provider‑specific configuration (e.g., set org.jboss.logging.provider for JBoss‑logging).
Once the logging stack is unified, all logs flow through the single chosen framework, eliminating missing logs, duplicate files, and configuration headaches.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.