Fix appender not found / class_not_found error for Log4j2 / SpringBoot

In a springboot2 project, we use log4j2. And to do some customized job, we implemented 2 log4j2 appenders.

However, from time to time when the app starts up, the following errors on console:

2019-07-25 17:23:52,312 main ERROR Error processing element LogServiceAppender ([Appenders: null]): CLASS_NOT_FOUND
2019-07-25 17:23:52,348 main ERROR Appenders contains an invalid element or attribute "OpenTracingAppender"
2019-07-25 17:23:52,352 main ERROR Unable to locate appender "logAppender" for logger config "root"
2019-07-25 17:23:52,352 main ERROR Unable to locate appender "tracingAppender" for logger config "root"

And sometime not.

After a few hours of debugging and searching online, I finally got the reason.

From log4j2 document ( https://logging.apache.org/log4j/2.x/manual/plugins.html), it is said that log4j2 can get the customized plugins from the following source:

  1. Serialized plugin listing files on the classpath. These files are generated automatically during the build (more details below).
  2. (OSGi only) Serialized plugin listing files in each active OSGi bundle. A BundleListener is added on activation to continue checking new bundles after log4j-core has started.
  3. A comma-separated list of packages specified by the log4j.plugin.packages system property.
  4. Packages passed to the static PluginManager.addPackages method (before Log4j configuration occurs).
  5. The packages declared in your log4j2 configuration file.

However, I have tested that, for a SpringBoot Fat Jar, (3)/(5) does not work either.

For (2) my project has nothing related to OSGi. For (5) I do not want to hard code the loading part.

So only (1) is left.

By debugging log4j2.0 source, I found that when the app starts up, Log4j2 initialization code will load a configuration file from <jar>\META-INF\org\apache\logging\log4j\core\config\plugins\Log4j2Plugins.dat

This is the configuration file described in (1). If the content is not correct, or this file is missing, errors will be got.

The content of this dat file is the class name, etc of my customized log4j2 appenders.

If this file exists and its content is correct, no problem.

And I do more testing.

I found that Intelij IDEA does some funny jobs. When I press CTRL+F9 to build, sometimes it will generate the correct Log4j2Plugins.dat and sometimes it does not. For example, I have 2 appenders. I change the source for one appender. Then in .dat file, only one appender appears.

So finally the question is, how do we create this file properly ?

2 ways, I found.

First: Add the following maven plugin to your pom.xml:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<id>log4j-plugin-processor</id>
<goals>
<goal>compile</goal>
</goals>
<phase>process-classes</phase>
<configuration>
<proc>only</proc>
<annotationProcessors>
<annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</execution>
</executions>
</plugin>

And each time your run maven, the correct .dat file will be generated.

Second: If you do not want to use maven, you can just copy & paste one copy of the correct \META-INF\org\apache\logging\log4j\core\config\plugins\Log4j2Plugins.dat under src\main\resources folder. So each time you build the project, IDEA or other builders will copy it to the target directory. But if your appenders are changed (classname and anything for @Plugin) you need to re-generate the .dat file and copy it under resources.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store