Integrate Spring MVC with Log4j

Integrating Log4j into a Spring MVC application is quite straightforward: include the Log4j library in your project dependencies, then create a log4j.properties file to define Log4j’s appenders and put it on the project classpath. This tutorial walks through that with the Log4j 1.x logging framework.

Note: This post targets Log4j 1.x, which reached end of life in August 2015 and has known vulnerabilities (e.g. CVE-2019-17571, CVE-2021-4104). Treat it as a reference for maintaining legacy projects only. For anything new, prefer SLF4J + Logback (the default in Spring Boot) or Log4j 2.x. Their configuration and API differ entirely from what’s shown here, and the official link below now redirects to Log4j 2.

Add Log4j Library to Your Project

Download the Log4j library from the official website, or via Maven :

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

Create log4j.properties

Create a Log4j properties file (log4j.properties), and put it into the project class path. See the figure below:

The properties below define how Log4j handles each message. In this example, every logged message goes to both the console and a daily rolling text file:

# LOG4J configuration
log4j.rootLogger=INFO, console, file

# Console Logger
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%p] %d %c %x - %m%n

# File Logger
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=${catalina.home}/logs/oes
log4j.appender.file.DatePattern='-'yyyy-MM-dd'.log'
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p] %d %c %x - %m%n

A few keys are worth understanding before you copy this over:

  • log4j.rootLogger=INFO, console, file sets the global level to INFO (so DEBUG messages are dropped) and attaches two appenders named console and file.
  • An appender decides where a message goes. ConsoleAppender prints to stdout, while DailyRollingFileAppender writes to a file and rolls over to a new one every day according to DatePattern.
  • ConversionPattern decides how each line looks: %p is the level, %d the timestamp, %c the logger (class) name, and %m%n the message followed by a line break.

Use Log4j in Spring MVC

Only two lines below are actually about Log4j, obtaining a Logger for the class and writing a message with logger.info(). Everything else is ordinary Spring MVC controller code:

import org.apache.log4j.Logger;

@Controller
@RequestMapping(value = "/accounts")
public class AccountsController {
    // Create one Logger per class, named after the class itself.
    private Logger logger = Logger.getLogger(AccountsController.class);

    @RequestMapping(value = "/login.action", method = RequestMethod.POST)
    public @ResponseBody HashMap<String, Boolean> loginAction(/* ... */) {
        // ... your business logic ...
        logger.info(String.format("User: [Username=%s] tried to log in at %s", username, ipAddress));
        // ...
    }
}

Disable Log4j in Test Environment

During unit tests you usually don’t want Log4j flooding the console with INFO messages; it clutters the test output and slows the build down. The trick is to point the test run at a separate, silent Log4j configuration.

Add a Plugin called maven-surefire-plugin in pom.xml (If you’re using Maven)

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.17</version>
    <configuration>
        <systemPropertyVariables>
            <log4j.configuration>file:${project.build.testOutputDirectory}/log4j-silent.properties</log4j.configuration>
        </systemPropertyVariables>
    </configuration>
</plugin>

Then create log4j-silent.properties as follows

log4j.rootLogger=OFF

Setting the root logger to OFF turns off every appender, so the test output stays clean while your production log4j.properties is left untouched.