Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll show how to fix the warning, “log4j: WARN No appenders could be found for logger”. We’ll explain what an appender is and how to define it. Furthermore, we will show how to solve the warning in different ways.

2. Appender Definition

Let’s first explain what an appender is. Log4j allows us to put logs into multiple destinations. Each destination where it prints output is called an appender. We have appenders for the console, files, JMS, GUI components, and others.

There’s no default appender defined in log4j. Additionally, a logger can have multiple appenders, in which case the logger prints output into all of them.

3. Warning Message Explained

Now that we know what an appender is, let’s understand the issue at hand. The warning message says that no appender could be found for a logger.

Let’s create a NoAppenderExample class to reproduce the warning:

public class NoAppenderExample {
    private final static Logger logger = Logger.getLogger(NoAppenderExample.class);

    public static void main(String[] args) {
        logger.info("Info log message");
    }
}

We run our class without any log4j configuration. After this, we can see the warning together with more details in the console output:

log4j:WARN No appenders could be found for logger (com.baeldung.log4j.NoAppenderExample).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

4. Solving the Issue With Configuration

Log4j looks by default into the application’s resources for a configuration file, which can be either in XML or Java properties format. Let’s now define the log4j.xml file under the resources directory:

<log4j:configuration debug="false">
    <!--Console appender -->
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
        </layout>
    </appender>

    <root>
        <level value="DEBUG"/>
        <appender-ref ref="stdout"/>
    </root>
</log4j:configuration>

We defined the root logger, which exists on the top of the logger’s hierarchy. All application loggers are children of it and override its configuration. We defined the root logger with one appender, which puts logs into the console.

Let’s run the NoAppenderExample class again and check the console output. As a result, the log contains our statement:

2021-05-23 12:59:10 INFO Info log message

4.1. Appender Additivity

An appender doesn’t have to be defined for each logger. The logging request for a given logger sends logs to the appenders defined for it and all appenders specified for loggers higher in the hierarchy. Let’s show it in an example.

If logger A has defined a console appender and logger B is a child of A, logger B prints its logs to the console, too. A logger inherits appenders from its ancestor only when additivity flags in the intermediate ancestors are set to true. In case the additivity flag is set to false, appenders from loggers higher in the hierarchy are not inherited.

To prove that a logger inherits appenders from ancestors, let’s add a logger for NoAppenderExample in our log4j.xml file:

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
    ...
    <logger name="com.baeldung.log4j.NoAppenderExample" />
    ...
</log4j:configuration>

Let’s run the NoAppenderExample class again. This time, the log statement appears in the console. Though the NoAppenderExample logger has no appender explicitly defined, it inherits the appender from the root logger.

5. Configuration File Not on the Classpath

Let’s now consider the case where we want to define the configuration file outside an application classpath. We have two options:

  • Specify a path to the file with the java command line option: -Dlog4j.configuration=<path to log4j configuration file>
  • Define path in code: PropertyConfigurator.configure(“<path to log4j properties file>”);

In the next section, we’ll see how to achieve this in our Java code.

6. Solving the Issue in Code

Let’s say we don’t want the configuration file. Let’s remove the log4.xml file and modify the main method:

public class NoAppenderExample {
    private final static Logger logger = Logger.getLogger(NoAppenderExample.class);

    public static void main(String[] args) {
        BasicConfigurator.configure();
        logger.info("Info log message");
    }
}

We call the static configure method from the BasicConfigurator class. It adds the ConsoleAppender to the root logger. Let’s look at the source code of the configure method:

public static void configure() {
    Logger root = Logger.getRootLogger();
    root.addAppender(new ConsoleAppender(new PatternLayout("%r [%t] %p %c %x - %m%n")));
}

Because the root logger in log4j always exists, we can programmatically add the console appender to it.

7. Conclusion

That concludes this short tutorial on how to solve the log4j warning about a missing appender. We explained what an appender is and how to solve the warning issue with a configuration file. Then, we explained how appender additivity works. Finally, we showed how to solve the warning in code.

As always, the source code of the example is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.