58

I have log4j2 in my project when I run main method in intellij Idea ,it correct to print log.

when i use maven-shade-plugin package project to jar file, and run jar as standalone application it shows error:

java -cp package.jar com.xxx.TestMain

the console output

ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.

pom.xml config . log4j2.version = 2.10.0, spring boot version is 1.5.9.RELEASE

<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>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>
                        </transformers>
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <sourceDirectory>src/main/java</sourceDirectory>
</build>

log4j2.xml config

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" monitorInterval="30" shutdownHook="disable">
    <properties>
        <property name="LOG_HOME">/data1/logs</property>
        <property name="JOB_NAME">noname</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%logger{36}][%file:%line] %msg%n%throwable"/>
        </Console>

        <RollingRandomAccessFile name="DetailFile"
                                 fileName="${sys:LOG_HOME}/${sys:JOB_NAME}/detail.log" bufferedIO="false"
                                 filePattern="${sys:LOG_HOME}/${sys:JOB_NAME}/detail.%d{yyyy-MM-dd}-%i.log">

            <PatternLayout
                    pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%file:%line] %msg%n%throwable"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="500 MB"/>
            </Policies>
        </RollingRandomAccessFile>
        <RollingRandomAccessFile name="error"
                                 fileName="${sys:LOG_HOME}/${sys:JOB_NAME}/error.log" bufferedIO="true"
                                 filePattern="${sys:LOG_HOME}/${sys:JOB_NAME}/error.%d{yyyy-MM-dd}.log">

            <PatternLayout
                    pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%logger{36}:%line] %msg%n%throwable"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="DetailFile"/>
            <AppenderRef level="error" ref="error"/>
        </Root>
    </Loggers>
</Configuration>
CoderMeng
  • 739
  • 1
  • 6
  • 8

9 Answers9

93

If a dependency contains log4j2 plugin, a Log4j2Plugins.dat cache file is included in the jar. When the Maven shade plugin is used to merge multiple jars with a Log4j2Plugins.dat file, only one will survive. Without the plugin definitions, errors are shown on startup. Log4j2 issue

One solution for this is excluding Log4j2Plugins.dat cache file from shaded jar so that Log4j scans for plugins on startup. For this, add a filter in maven-shade-plugin configuration in your pom:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.1.0</version>
  <configuration>
    <createDependencyReducedPom>false</createDependencyReducedPom>
    <filters>
      <filter>
        <artifact>*:*</artifact>
        <excludes>
          <exclude>**/Log4j2Plugins.dat</exclude>
        </excludes>
      </filter>
    </filters>
  </configuration>
  <!-- ... -->
</plugin>

Another solution is to merge the cache files using a transformation plugin which is log4j version specific.

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Shashank Kapoor
  • 1,101
  • 8
  • 9
  • 6
    Adding this configuration to the maven-shade-plugin entry in pom.xml solved this issue for me – Bertware Nov 14 '18 at 14:27
  • For Gradle look at the comment below – MaX Sep 17 '21 at 14:14
  • how to fix this in scala? – Suchita Aug 19 '22 at 11:02
  • Hello, none of the above mentioned solutions solved the issue for me. The only thing that helped was to not minimize the UBER jar – experiment unit 1998X Feb 10 '23 at 02:34
  • Adding the `Log4j2PluginCacheFileTransformer` fixed the problem for me. Note that the plugin has just recently been donated to the Apache Software Foundation, so the most recent is the [Log4j Plugin Cache Transformer](https://github.com/apache/logging-log4j-transform/tree/main/log4j-transform-maven-shade-plugin-extensions) on the Apache GitHub site. That page has example code. – Garret Wilson Jun 05 '23 at 21:16
23

If you are using Gradle and ShadowJar 4+:

shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
}

Gradle Kotlin DSL:

shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer::class.java)
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Chris Xue
  • 2,317
  • 1
  • 25
  • 21
14

Unfortunately, I can't reply to Shashank Kapoor answer, as he correctly pointed out excluding the Log4j2Plugins.dat file solves the issue. This did the trick for me while using gradle:

shadowJar {
    exclude "**/Log4j2Plugins.dat"
}
philuX
  • 191
  • 1
  • 3
  • Though this prevents the errors about the format, now the application wont start: Exception in thread "main" java.util.ServiceConfigurationError: java.nio.file.spi.FileSystemProvider: Provider org.apache.sshd.sftp.client.fs.SftpFileSystemProvider not found – Charlie May 18 '22 at 18:17
  • Not sure if it's related to the original problem but I was able to get past the SftpFileSystemProvider error by excluding its manifest from the shadowJar: exclude("META-INF/services/java.nio.file.spi.FileSystemProvider") – Charlie May 18 '22 at 19:31
6

I’ve seen this error before when people had multiple versions of Log4j2 on the classpath.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • 1
    I checked maven package log, it's only have Log4j2 version. – CoderMeng Dec 31 '17 at 02:06
  • 1
    Please make sure by printing the value of system property `java.classpath` from your application. It could be a transient dependency or some other configuration. – Remko Popma Dec 31 '17 at 03:38
3

For those of us who are removing the older Logj42 from our classpaths to remediate the Log4Shell (CVE-2021-44228) vulnerability, you may find you have this issue when using your uber jars after you upgrade.

If you are building your uber jars from Maven or Gradle, use one of the plugins respectively:

if you are building them by some other means, see this answer: https://stackoverflow.com/a/70497498/1174024. But basically you have to properly handle Log4j2 plugin cache files as this class does:

https://github.com/edwgiz/maven-shaded-log4j-transformer/blob/master/src/main/java/io/github/edwgiz/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformer.java

to properly handle the Log4j2Plugins.dat file when building the new uber jar.

Nicholas DiPiazza
  • 10,029
  • 11
  • 83
  • 152
1

On our project, such a problem arose after the creation of the TestAppender class.

@Plugin(name = "TestAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class TestAppender extends AbstractAppender {
...

Its settings overwrote the logger settings in the Log4j2Plugins.dat file.

Then we moved it to a separate module and began to attach it to the project in a similar way (please, pay attention to scope):

<dependency>
  <groupId>info.project</groupId>
  <artifactId>test</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
Leonis
  • 294
  • 3
  • 10
0

This link works for me. There's a problem while shading log4j

<filter>
    <artifact>log4j:log4j</artifact>
    <includes>
        <include>org/apache/log4j/spi/LoggingEvent.class</include>
    </includes>
</filter>
<filter>
    <artifact>org.apache.logging.log4j:log4j-*</artifact>
    <includes>
        <include>**</include>
    </includes>
</filter>
anhldbk
  • 4,559
  • 5
  • 29
  • 37
0
@PowerMockIgnore( {"org.springframework.util.Log4jConfigurer","javax.script.*","javax.management.*", "org.w3c.dom.*", "org.apache.log4j.*","org.apache.logging.*","org.apache.commons.logging.*", "org.xml.sax.*",   "javax.xml.*"})

added this snippet to the test class. No error log anymore.

0

You can exclude all the Log4j2Plugins.dat files except the right one, the one contained in log4j-core:

<filter>
    <artifact>SOME-ARTIFACT</artifact>
    <excludes>
        <exclude>**/Log4j2Plugins.dat</exclude>
    </excludes>
</filter>
<filter>
    <artifact>SOME-ARTIFACT</artifact>
    <excludes>
        <exclude>**/Log4j2Plugins.dat</exclude>
    </excludes>
</filter>
...

See answer here, with a sample project: https://stackoverflow.com/a/76003471/1121497

Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100