JUL to SLF4J Bridge Example
Java developers often work with different logging frameworks across projects. The standard Java logging (JUL) comes bundled with the JDK but lacks flexibility. Let us delve into understanding how to use the Java JUL to SLF4J bridge for logging management.
1. What is JUL? What is SLF4J?
- java.util.logging (JUL):
- JUL is the built-in logging framework available since Java 1.4.
- It provides a basic set of logging capabilities including log levels, handlers (console, file, socket), and formatters.
- However, it lacks modern logging features such as:
- SLF4J (Simple Logging Facade for Java):
- SLF4J is not a logging implementation itself, but a facade or abstraction that allows the underlying logging implementation to be plugged in at deployment time.
- It standardizes logging across different libraries and modules, decoupling application code from a specific logging implementation.
- SLF4J supports:
- Parameterized logging with placeholders
{} - Mapped Diagnostic Context (MDC) for contextual information like user ID, request ID, etc.
- Integration with various backends like Logback, Log4j2, and even JUL (via bridging)
- Parameterized logging with placeholders
If you’re using a library that logs using JUL but your application uses SLF4J + Logback, the JUL-to-SLF4J bridge can unify all logs under the same logging configuration.
2. Code Implementation
Integrating java.util.logging (JUL) with SLF4J allows applications and third-party libraries that use different logging approaches to output logs through a unified backend (such as Logback). This not only streamlines log management but also enables advanced features like centralized logging configuration, MDC tracking, and cleaner log formatting. Below are the required steps and code snippets to bridge JUL to SLF4J.
2.1 Adding JAR Dependencies
To enable the bridging mechanism, you need to include specific dependencies in your project pom.xml. These dependencies consist of:
- SLF4J API – Provides the unified logging facade that your application and other libraries will log through.
- SLF4J Implementation – The actual backend where logs are routed. Common choices include
logback-classic,log4j-slf4j-impl, or others. - JUL to SLF4J Bridge – A bridge module that intercepts JUL logs and redirects them through SLF4J.
<dependencies>
<!-- SLF4J API -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<!-- SLF4J Implementation (e.g., Logback) -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
<!-- JUL to SLF4J Bridge -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
Note: Be sure to exclude any existing conflicting JUL or Logback bindings that may be brought in transitively by other libraries. Also, ensure that only one SLF4J binding is present in your classpath to avoid runtime errors.
2.2 Code
2.2.1 Logging using JUL (without bridge)
This example demonstrates basic logging using the built-in java.util.logging (JUL) framework. By default, JUL writes to the console using the ConsoleHandler and applies a simple text formatter.
import java.util.logging.Logger;
public class JulExample {
private static final Logger logger = Logger.getLogger(JulExample.class.getName());
public static void main(String[] args) {
logger.info("This is an info log from JUL");
logger.warning("This is a warning from JUL");
}
}
When run, the output appears in the default JUL format, typically showing the timestamp, logger name, log level, and message:
Apr 24, 2025 10:00:00 AM JulExample main INFO: This is an info log from JUL Apr 24, 2025 10:00:00 AM JulExample main WARNING: This is a warning from JUL
JUL does not support advanced formatting, MDC, or redirection to modern logging systems by default. Its output format is also harder to customize compared to Logback or Log4j.
2.2.2 Redirecting JUL to SLF3
To redirect JUL logs into SLF4J (and ultimately Logback or another backend), the JUL-to-SLF4J bridge must be installed programmatically at application startup. This disables all existing JUL handlers and redirects logs via SLF4J:
import java.util.logging.Logger;
import java.util.logging.LogManager;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class JulToSlf4jBridgeExample {
private static final Logger julLogger = Logger.getLogger(JulToSlf4jBridgeExample.class.getName());
public static void main(String[] args) {
// Remove existing handlers attached to JUL root logger
LogManager.getLogManager().reset();
// Install the SLF4J bridge
SLF4JBridgeHandler.install();
// Log using JUL (will be redirected to SLF4J -> Logback)
julLogger.info("This JUL log will now go to SLF4J (Logback)");
}
}
After the bridge is installed, JUL logs are sent to the SLF4J API, where they are processed by your configured SLF4J binding (e.g., Logback). This ensures that all application and library logs, regardless of their original framework, follow a unified format and configuration.
2.2.2.1 Logback Configuration (Optional)
To fully benefit from redirecting java.util.logging output through SLF4J, you should configure a logging backend such as Logback. The configuration file, typically named logback.xml, is placed in the src/main/resources directory so it can be found on the classpath at runtime.
Below is a simple Logback configuration that outputs logs to the console using a custom pattern format. You can customize the pattern to include thread name, MDC values, log level, and source class:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] %-5level [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
This configuration outputs logs in the format:
%d{HH:mm:ss.SSS}: Timestamp in hours, minutes, seconds, and milliseconds%-5level: Log level, left-aligned (e.g., INFO, DEBUG)[%thread]: The name of the thread writing the log%logger{36}: Logger name, truncated to 36 characters if needed%msg: The actual log message
When running a JUL logger after the SLF4J bridge has been installed, and with this Logback configuration in place, the output will appear like:
[10:05:00.123] INFO [main] JulToSlf4jBridgeExample - This JUL log will now go to SLF4J (Logback)
This confirms that:
- The JUL logging calls are now redirected to SLF4J.
- The output is handled by the SLF4J backend—in this case, Logback.
- All formatting, filtering, and routing decisions are delegated to Logback, regardless of the original logging API used.
This setup is especially useful in large enterprise applications or libraries where multiple logging frameworks might coexist. By centralizing log output through SLF4J, you ensure consistency and flexibility in log management.
3. Conclusion
Bridging JUL to SLF4J is an effective way to standardize logging across your Java application. It becomes especially useful when dealing with third-party libraries that use JUL. With a few lines of code and the right dependencies, you can gain centralized control over log formatting, levels, and destinations using powerful SLF4J backends like Logback. In modern Java applications, consistency is key — and the JUL to SLF4J bridge helps bring that consistency to your logging strategy.

