How to log with Lombok using @slf4j annotation in Java, Spring and Spring Boot Applications

Introduction

In this tutorial I will show you how to configure Lombok for logging using @slf4j annotation in Java, Spring and Spring Boot applications. The example shown here will work for Java, Spring and Spring Boot applications. This annotation will reduce the code you write for creating logger variable. Lombok will provide log variable when you use @slf4j annotation on class level. You can use this log variable to create log statements.

I am going to use log4j2 with slf4j API for Java, Spring and Spring Boot applications. You can even use spring-boot-starter-log4j2 API instead of log4j2 with slf4j for Spring Boot application. This starter dependency will resolve the similar kind of libraries as log4j2 with slf4j.

Prerequisites

At least Java 8, lombok API, log4j2 with slf4j API, Spring, Spring Boot

Make sure you have configured Lombok for your IDE from the Lombok Installation section.

Create Build Configuration

If you are creating gradle based project in Eclipse then you can use the following dependencies in build.gradle script:

repositories {
    mavenCentral()
    maven {
    	url "http://projectlombok.org/mavenrepo"
    }    
}

dependencies {
	implementation('org.projectlombok:lombok:1.18.10')
	implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.13.0'
}

If you are using maven based project then you can use below dependencies in pom.xml file:

<repositories>
    <repository>
      <id>projectlombok.org</id>
      <url>http://projectlombok.org/mavenrepo</url>
    </repository>
</repositories>

<dependencies>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.10</version>
	</dependency>
	
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-slf4j-impl</artifactId>
		<version>2.13.0</version>
	</dependency>
</dependencies>

The above build configuration for gradle or maven based project will work for Java, Spring and Spring boot applications.

But you need to exclude logback API from Spring Boot starter otherwise it will conflict and logback will override log4j2.

For gradle build:

configurations {
    all*.exclude module : 'spring-boot-starter-logging'
}

For maven build:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

For Spring Boot applications you can also use only log4j starter API that will resolve the similar libraries. Make sure to exclude the logback API even when you are using log4j starter API. Don’t forget to include the lombok API.

For gradle build:

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-log4j2'
}

For maven build:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
</dependencies>

Create log4j2.xml

Log4j is a logging library for Java based applications and purpose of inserting log statements into code is a low-tech method for debugging it. But make sure you follow the best practices while putting log statements.

Learn Logging using logback in Spring Boot application.

Now we will create log4j2.xml file under the classpath directory src/main/resources.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">

	<Properties>
		<Property name="LOG_LOC">logs</Property>
		<Property name="MAX">5</Property>
		<Property name="LOG_PATTERN">%d{yyyy.MM.dd HH:mm:ss.SSS} [%p] %c: %m%n
		</Property>
	</Properties>

	<Appenders>
		<RollingFile name="FILE" fileName="${LOG_LOC}/main.log"
			filePattern="${LOG_LOC}/main.%i.log">
			<PatternLayout>
				<Pattern>${LOG_PATTERN}</Pattern>
			</PatternLayout>

			<Policies>
				<OnStartupTriggeringPolicy />
			</Policies>

			<DefaultRolloverStrategy max="${MAX}" />
		</RollingFile>

		<Console name="STDOUT" target="SYSTEM_OUT" follow="true">
			<PatternLayout pattern="${LOG_PATTERN}" />
		</Console>
	</Appenders>

	<Loggers>
		<Logger name="com.roytuts" level="debug" />

		<Logger name="org.springframework.web" level="info"
			additivity="false" />

		<Logger name="file" level="debug" additivity="false">
			<appender-ref ref="FILE" />
		</Logger>

		<Root level="warn">
			<AppenderRef ref="FILE" />
			<AppenderRef ref="STDOUT" />
		</Root>
	</Loggers>

</Configuration>

As we are using log4j2 API, so the configuration file name is log4j2.xml or log4j2.properties. If you are using log4j API version 1, then your file name should be log4j.xml or log4j.properties.

Keeping the log4j2 XML or properties file in classpath will be picked up by the application automatically.

The status in the log4j2 configuration is used internally by log4j2 components. This is useful for troubleshooting the configuration issues. Here I have turned this off. You can set debug, warn etc. for the status.

Then we set some properties with key/value pairs.

Next we define two appenders – RollingFile and Console.

In RollingFile appender we set the file name and file name pattern. We have maximum backup file 5 apart from main.log file. The file name pattern will create main.1.log … main.5.log and another main.log file will be the current log file.

We have specified the pattern of the log statements.

Next we have specified policy to start a new log file whenever the application starts up. During start up the file name pattern comes into picture and maximum 5 files will be created apart from main log file.

The console appender prints the log statements into console.

Next we define some loggers with level of logging.

The root level of logging is info for file as well as console logging.

Avoid duplicate logging by adding aditivity=”false”.

Example of Logging

The below class shows how to create log statements which will be printed in the console as well as into the file.

package com.roytuts.lombok.slf4j.java.spring.springboot;

import org.apache.logging.log4j.ThreadContext;
import org.slf4j.MDC;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LombokSlf4jApp {

	public static void main(String[] args) {
		printLog();
	}

	private static void printLog() {
		log.debug("Debug Message");
		log.warn("Warn Message");
		log.error("Error Message");
		log.info("Info Message");
		log.trace("Trace Message");

		MDC.put("module", "MDC");
		log.debug("Debug Message");
		log.warn("Warn Message");
		log.error("Error Message");
		log.info("Info Message");
		log.trace("Trace Message");

		MDC.remove("MDC");

		ThreadContext.put("module", "Module1");
		log.debug("Module1 Debug Message");
		log.warn("Module1 Warn Message");
		log.error("Module1 Error Message");
		log.info("Module1 Info Message");

		ThreadContext.put("module", "Module2");
		log.debug("Module2 Debug Message");
		log.warn("Module2 Warn Message");
		log.error("Module2 Error Message");
		log.info("Module2 Info Message");

		ThreadContext.remove("module");
	}

}

Notice in the above class, we have just put @slf4j annotation on the class level and log variable is available for creating log statements.

Source Code

Download

Thanks for reading.

2 thoughts on “How to log with Lombok using @slf4j annotation in Java, Spring and Spring Boot Applications

  1. I don’t understand why you are even using SLF4J in this example. Just change @SLF4J to @Log4j2 and change the one MDC reference to ThreadContext – which you are already using.

    1. If you have used @SLF4J in your old project and now you want to move SLF4J to Log4j2 that time this strategy help you.

Leave a Reply

Your email address will not be published. Required fields are marked *