SLF4J

Slf4j Spring Boot Example

In this example, we are going to learn how to use SLF4J in Spring projects with an example of Spring Boot application.

1. Introduction

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.

SLF4J facilitates your code to make logging calls without binding to a specific logging implementation. This comes real handy for libraries where it is not desired to hard bind the API to a particular logging framework as the program where it may be used might be using another logging implementation.

To get started with SLF4J, read this tutorial.

SLF4J has now become a logging abstraction of choice and probably fast ruling out Commons logging due to it’s advantages (read here for a head-on comparison).

Spring (what started as a Java enterprise application framework) has evolved into an ecosystem now with framework for enterprise applications, transaction management, web services, security, mobile development etc. Let’s see in this example what Spring has to offer when it comes to logging framework support.

2. Technologies Used

For this example, we use the following tools on a Windows 10 platform:

  • Eclipse IDE
  • Apache Maven
  • JDK 1.8
  • Slf4j 1.7.22
  • Spring Boot 1.5.3

3. Slf4j Spring Boot Example

3.1 Create a Maven Project

We will create a bare minimum Maven project. Once you have the Maven installed and running on your machine, issue the following command from the command line.

1
mvn archetype:generate -DgroupId=com.javacodegeeks -DartifactId=slf4-spring-boot -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

In this example, Maven will manage dependencies for us and we don’t need to download any jars explicitly.

3.2 Add Maven Dependencies

Add the required dependencies for just Spring Boot. Your pom.xml should look like this.

pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.javacodegeeks</groupId>
    <artifactId>slf4-spring-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>slf4-spring-boot</name>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>1.5.3.RELEASE</version>
        </dependency>
    </dependencies>
</project>

With just the single dependency, spring boot will download the logging dependency (spring-boot-starter-logging)  as well among other core dependencies. If you open pom.xml and go to the “Dependency Hierarchy” tab, it looks like this:

Dependency Hierarchy
Figure 1: Dependency Hierarchy

Note the jar files spring-boot-starter-logging brings along in the figure above.  jcl-over-slf4j, jul-to-slf4j and log4j-over-slf4j are the bridging modules which redirect calls made to log4j, JCL and java.util.logging APIs to behave as if they were made to the SLF4J API instead. logback-classic along with logback-core enables logback as the default logging implementation for Spring Boot.  This may have to do with the fact that logback is the native implementation of SLF4J; using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.

3.3 Logback Configuration

Create logback.xml and put the basic configuration settings. If we don’t create this file, even then logback will configure itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.

logback.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<configuration>
 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <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.4 Test Class

Slf4jSpringBootApplication.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.javacodegeeks;
 
import java.lang.invoke.MethodHandles;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
import com.javacodegeeks.service.HelloWorldService;
 
@SpringBootApplication
public class Slf4jSpringBootApplication implements CommandLineRunner {
 
    // SLF4J's logging instance for this class
    // We could have used LoggerFactory.getLogger(Slf4jSpringBootApplication.class) as well
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
     
    // This is what SLF4J uses to bind to a specific logging implementation
    final StaticLoggerBinder binder = StaticLoggerBinder.getSingleton();
     
    @Autowired
    private HelloWorldService helloWorldService;
 
    public void run(String... args) {
        System.out.println(binder.getLoggerFactory());
        System.out.println(binder.getLoggerFactoryClassStr());
         
        LOGGER.debug(this.helloWorldService.getHelloMessage());
        if (args.length > 0 && args[0].equals("exitcode")) {
            LOGGER.error("Exit Code encountered", new ExitException());
        }
    }
 
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Slf4jSpringBootApplication.class, args);
    }
}

Since the logging level is set to debug, it’s going to output a lot of Spring messages. Our logging specific calls is shown below.

Output Snippet

01
02
03
04
05
06
07
08
09
10
11
12
13
14
ch.qos.logback.classic.LoggerContext[default]
ch.qos.logback.classic.util.ContextSelectorStaticBinder
19:48:58.844 [main] INFO  c.j.service.HelloWorldService - Name registered World
19:48:58.846 [main] DEBUG c.j.Slf4jSpringBootApplication - Hello World
19:48:58.848 [main] ERROR c.j.Slf4jSpringBootApplication - Exit Code encountered
java.lang.Exception: null
    at com.javacodegeeks.Slf4jSpringBootApplication.run(Slf4jSpringBootApplication.java:34)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151)
    at com.javacodegeeks.Slf4jSpringBootApplication.main(Slf4jSpringBootApplication.java:39)

3.5 Configuring With Log4J

You can use spring-boot-starter-log4j2 in place of spring-boot-starter-logging so that log4j2 becomes the default dependency for your Spring Boot app. In this case our pom.xml will look like this.

pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.javacodegeeks</groupId>
    <artifactId>slf4-spring-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>slf4-spring-boot</name>
    <url>http://maven.apache.org</url>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>1.5.3.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>1.5.3.RELEASE</version>
        </dependency>
    </dependencies>
</project>

Create log4j.properties for the logging configuration.

log4j.properties

1
2
3
4
5
6
7
8
# Root logger option
log4j.rootLogger=INFO, stdout
 
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n

Let’s re-run Slf4jSpringBootApplication.java to see the output.

Output Snippet

01
02
03
04
05
06
07
08
09
10
11
12
13
14
org.apache.logging.slf4j.Log4jLoggerFactory@38b27cdc
org.apache.logging.slf4j.Log4jLoggerFactory
2017-04-29 20:28:02.924  INFO 14356 --- [           main] c.j.s.HelloWorldService                  : Name registered World
2017-04-29 20:28:02.925 ERROR 14356 --- [           main] c.j.Slf4jSpringBootApplication           : Exit Code encountered
 
java.lang.Exception: null
    at com.javacodegeeks.Slf4jSpringBootApplication.run(Slf4jSpringBootApplication.java:34) [classes/:?]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    at com.javacodegeeks.Slf4jSpringBootApplication.main(Slf4jSpringBootApplication.java:39) [classes/:?]

Note in the above output, the SLF4J binding has switched to log4j2.

4. Summary

Spring Boot provides out of the box support for SLF4J and Logback is the default logging implementation for Spring Boot.

Default logging implementation can be changed by excluding corresponding bridging modules (jcl-over-slf4j, jult-to-slf4j and log4j-over-slf4j) as well as logback-classic and then add required logging library with the corresponding slf4j bridge.

5. References

  1. https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#overview-logging-slf4j
  2. https://projects.spring.io/spring-boot/
  3. https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
  4. https://www.slf4j.org/legacy.html

6. Download the Eclipse Project

You can download the full source codes of this example here: slf4j-log4j-spring-boot & slf4j-spring-boot

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Mayank Gupta

Senior JEE developer with experience in large scale IT projects, especially in the telecommunications and financial services sectors. Mayank has been designing and building J2EE applications since 2007. Fascinated by all forms of software development; keen to explore upcoming areas of technology like AI, machine learning, blockchain development and AR. Lover of gadgets, apps, technology and gaming.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button