Java and Spring development

SLF4J logging with Log4J and JCL

with 6 comments

More and more frameworks logs with the SLF4J framework. Many applications must relate to several different logging frameworks. This tutorial shows how one logger framework can handle log messages from other logging frameworks with SLF4J as the central part.

The demo application used in this tutorial logs with Log4J and have dependencies to Spring and Hibernate. Here’s the different loggers and where they are used:

  • JCL Spring
  • SLF4J Hibernate 3.3+
  • Log4J Demo application

Log4J integrates well with JCL, but can’t handle log messages from SLF4J. This forces the use of SLF4J to connect the different loggers together.

SLF4J

A description of SLF4J from their homepage:

The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time.

In addition to the extra flexibility, the API also contains a nice feature with support for arguments.

logger.debug("The date is: {}", date);

The old way with Log4J:

if (logger.isDebugEnabled()) {
	logger.debug("The date is: " + date);
}

Both examples prints:

 DEBUG [demo.Slf4jDemo] - <The date is: Sun Jun 06 11:34:11 CEST 2010>

The difference is that SLF4J doesn’t merge the dynamic and static data into a new string in the debug method, but sends the dynamic part(s) as argument(s). If the logger is configured to only log messages with info level or higher, the debug message above gets discarded without any string processing and without the need for an extra if sentence for performance reasons.

For information about SLF4J and its alternatives on a high level, Bruce Snyder has written a good post here.

Two scenarios that will support central log handling

The first option is to bind the SLF4J logger against Log4J. It works nice and enables management of JCL and SLF4J log messages from the Log4J configuration. In my case with the log4j.properties file.

The other alternative which is also recommended in the SLF4J’s manual is to log messages to the SLF4J framework and bind SLF4J to the new logback framework like this:

With the second solution, SLF4J’s binder framework will receive all the log messages.

SLF4J and and binding against a backend logger

You can only bind against one backend logging framework. With no binding framework on the classpath, the silent logger (NOP) will be used by default.

The frameworks supported by SLF4J:

  • Logback-classic
  • Log4J
  • java.util.logging (JUL)
  • Simple
  • NOP
  • Jakarta Commons Logging (JCL)

The preferred backend logging framework with SLF4J is Logback.

Logback

Logbac is written by the same people who have written SLF4J. It natively implements the SLF4J API.

Their description of the framework:

The logback-classic module can be assimilated to a significantly improved version of log4j

A nice feature with Logback is that you can see which jar file that contains a class in the stacktrace. And if the jar file contains an Implemented-Version property in the /META-INF/MANIFEST.MF file, then you can see the version number to the right for the jar file name.

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'unkownBeanId'
        is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition
        (DefaultListableBeanFactory.java:510)
        ~[org.springframework.beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]

You can find more reasons to upgrade from Log4J to Logback on their site here.

Logging with the SLF4J API

A simple example:

import java.util.Date;

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

public class Slf4jDemo {

	private final Logger logger = LoggerFactory.getLogger(Slf4jDemo.class);

	public void demo() {
		Date date = new Date();

		logger.debug("The date is: {}", date);
	}

	public static void main(String[] args) {
		new Slf4jDemo().demo();
	}
}

A basic logback.xml configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="stdout">
    <encoder>
      %-5p [%c] - <%m>%n
    </encoder>
  </appender>
  <logger name="demo" level="DEBUG"/>
  <root level="WARN">
    <appender-ref ref="stdout"/>
  </root>
</configuration>

Handle JCL log messages with SLF4J

With SLF4J’s JCL bridge implementation, you can program against the JCL API without adding the JCL jar file, since the bridge implementation contains the necessary classes to route the log messages to the SLF4J’s backend implementation.

An example that logs with the JCL API like the Spring framework does:

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ApacheCommonsLoggerDemo {

	private final static Log logger = LogFactory.getLog(ApacheCommonsLoggerDemo.class);

	public void demo() {
		Date date = new Date();

		logger.debug("The date is: " + date);
	}

	public static void main(String[] args) {
		new ApacheCommonsLoggerDemo().demo();
	}
}

Log4J messages and SLF4J

Many applications logs with Log4J. These log messages can also be handled by SLF4J’s backend logger with adding the log4j-over-slf4j library to your build path. This library works similar to the JCL bridge implementation described above. The important class is the org.apache.log4j.Logger and is instantiated like this:

private final Logger logger = Logger.getLogger(Log4jDemo.class);

Summary

SLF4J is the new common logging API for new open-source projects. With its facade pattern implementation, it’s a very flexible framework that let you easily integrate different logging frameworks used by the application’s dependencies. It’s also modular by nature with a loose coupling between the SLF4J API and the backend logger framework.

In addition to the modularity, I like the enhanced stacktrace that’s printed with the configuration illustrated in the second scenario without changing a single line of code!

If you in the future wants to standardize logging with SLF4J, then you can use this migrator that’s bundled with the SLF4J distribution and migrate your log4j.properties file to a logback.xml file with this online translator.

Written by Espen

June 6, 2010 at 21:02

Posted in Logging

Tagged with , , , , ,

6 Responses

Subscribe to comments with RSS.

  1. This is really a very remarkable article on JAVA.
    It has provided very important information which is very useful for all who are planning to learn JAVA.

    Thanks allot for such a remarkable effort.

    IBM Mainframe Training

    July 23, 2010 at 09:04

  2. Nice features described.
    But the most difficult mix is java.util.logging with the others. Do you know of a solution ?
    JBOss does some nice tricks, but it s not packaged. The idea could be reused but it requires some programming …

    Gauthier

    March 7, 2011 at 10:09

    • You have to bind all 3rd party loggers including JUL to SLF4J. Then you configure SLF4J to use the backend logger you prefer.

      An overview of the different binders can be found on the SLF4J manual page.

      Espen

      March 7, 2011 at 12:02

  3. […] shows the various binding among different loggers and it pointed me in the right direction, thanks Espen!:) Like this:LikeBe the first to like this post. This entry was posted in Uncategorized. Bookmark […]

  4. Thanks Espen, its a great article. I piggybacked on your article for my Spring-Hibernate implementation here : http://anirbanchowdhury.wordpress.com/2012/05/16/logging-spring-hibernate-sl4j-log4j-jcl/

    Anirban Chowdhury

    May 17, 2012 at 07:36

  5. […] Spring provides instructions to use SLF4J with Log4J and there is a great explanation for the bindings at SLF4J logging with Log4J and JCL […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: