Setting Up SLF4J with Logback, Log4j2 and JUL

A logging facade is an abstraction API that application code logs against, while a separate logging framework does the actual logging. SLF4J (Simple Logging Facade for Java) is the facade for logging frameworks such as Java Util Logging (JUL), Logback and Log4j2. We use the SLF4J API in …

Java Logging

A logging facade is an abstraction API that application code logs against, while a separate logging framework does the actual logging. SLF4J (Simple Logging Facade for Java) is the facade for logging frameworks such as Java Util Logging (JUL), Logback and Log4j2. We use the SLF4J API in the application code and later plug in the logging framework we want as the implementation.

Because the application code uses only the SLF4J API, we can migrate from one logging framework to another by replacing the dependencies and the configuration files. The application code stays unchanged.

In this tutorial, we set up SLF4J with Logback, Log4j2 and Java Util Logging.

1. SLF4J Dependency and API

The only mandatory dependency for the SLF4J API is slf4j-api. The other dependencies are specific to the logging framework, so each framework needs its own dependencies.

  • If SLF4J finds no binding on the classpath, it falls back to a no-operation implementation, so the application logs nothing at runtime.
  • Since version 2.0.0, SLF4J requires Java 8 and provides a backward-compatible fluent logging API. The fluent API works with all existing logging frameworks.
  • In a Spring Boot application, the starter spring-boot-starter-logging configures SLF4J with Logback.
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>${slf4j-api-version}</version>
</dependency>

To log messages in a class, we create a Logger with LoggerFactory. Both classes are in the package org.slf4j.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//Create Logger
Logger logger = LoggerFactory.getLogger(Main.class);

//Log messages
logger.info("Info Message Logged !!!");

2. Configuring Logback with SLF4J

Logback needs the dependency logback-classic. It transitively includes slf4j-api and logback-core, so logback-classic alone is enough to set up Logback with SLF4J.

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback-classic-version}</version>
</dependency>

Logback configures a console appender with the DEBUG log level by default. For custom logback configuration, we create the file logback.xml and place it on the classpath.

<configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

3. Configuring Log4j2 with SLF4J

Log4j2 needs three dependencies to work with SLF4J.

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>${log4j2-version}</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${log4j2-version}</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>${log4j2-version}</version>
</dependency>

Log4j2 reads its loggers and appenders from one of the files log4j2.properties, log4j2.xml or log4j2.json, so we provide one of them.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n</Property>
    </Properties>
 
    <Appenders>
        <Console name="console" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
    </Appenders>
 
    <Loggers>
        <Root level="info">
            <AppenderRef ref="console"/>
        </Root>
    </Loggers>
</Configuration>

4. Configuring Java Util Logging with SLF4J

To use JUL as the logging implementation, we add the dependency slf4j-jdk14.

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>${jul-version}</version>
</dependency>

By default, JUL loads logging.properties from $JAVA_HOME/jre/lib/ in Java 8 and before. In Java 9 and above, the file logging.properties is in $JAVA_HOME/conf.

The following file is a sample JUL configuration.

# Logging handlers
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level
.level = ALL

# File Logging
# default file output is in user's home directory
java.util.logging.FileHandler.pattern = %h/myApp.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = INFO

# Console Logging
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

5. Conclusion

Using the SLF4J API is the recommended way to implement logging in Java applications. It keeps the application code independent of the logging framework.

SLF4J also supports the fluent API and readable log messages through parameter substitution instead of string concatenation. Parameter substitution also improves the logging performance of the application.

Happy Learning !!

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.