Friday, February 3, 2017

How to fix Log4j2 problem with maven shade plugin

The maven shade plugin is used for packaging of the project classes and dependencies in a single jar (so called uber-jar).
Having one fat jar is very convenient for execution: it is enough to specify in the class path the uber-jar name instead of the long list of dependency jars.

Example of basic shade plugin configuration


The pom fragment below shows the basic shade plugin configuration for creating an execution jar:
 <build>  
      <finalName>myCli</finalName>  
      <plugins>  
      <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-shade-plugin</artifactId>  
                <version>3.0.0</version>  
                <executions>  
                     <execution>  
                          <phase>package</phase>  
                          <goals>  
                               <goal>shade</goal>  
                          </goals>  
                          <configuration>  
                               <transformers>  
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
                                 <mainClass>com.something.MyCliApp</mainClass>  
                                    </transformer>  
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.PluginXmlResourceTransformer"/>  
                               </transformers>  
                          </configuration>  
                     </execution>  
                </executions>  
           </plugin>  
      </plugins>  
 </build>  
The property finalName specifies the name of the uber-jar artifact instead of the default name. The property mainClass specifies the class, which main method is to be called.

If the uber jar is located in the subdirectory bin, it should be run like this:
 java -cp bin/myCli.jar com.something.MyCliApp
Read more about shade plugin on the documentation page.

Log4j2 and shade plugin problem


There is the known problem (at least on time of writing this post) with including log4j2 dependencies into the uber jar: log4j2 fails to start when running the jar.

To overcome the problem log4j2 should be excluded from shade dependencies and provided explicitly in the class path:
1. Add the following to the shade plugin configuration:
 <artifactSet>  
      <excludes>  
           <exclude>org.apache.logging.log4j:log4j-api</exclude>  
           <exclude>org.apache.logging.log4j:log4j-core</exclude>  
      </excludes>  
 </artifactSet>  
The full configuration now looks like this:
 <build>  
      <finalName>myCli</finalName>  
      <plugins>  
      <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-shade-plugin</artifactId>  
                <version>3.0.0</version>  
                <executions>  
                     <execution>  
                          <phase>package</phase>  
                          <goals>  
                               <goal>shade</goal>  
                          </goals>  
                          <configuration>  
                               <artifactSet>  
                                    <excludes>  
                                       <exclude>org.apache.logging.log4j:log4j-api</exclude>  
                                       <exclude>org.apache.logging.log4j:log4j-core</exclude>  
                                    </excludes>  
                               </artifactSet>  
                               <transformers>  
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
                                 <mainClass>com.something.MyCliApp</mainClass>  
                                    </transformer>  
                                    <transformer implementation="org.apache.maven.plugins.shade.resource.PluginXmlResourceTransformer"/>  
                               </transformers>  
                          </configuration>  
                     </execution>  
                </executions>  
           </plugin>  
      </plugins>  
 </build>  
2. Decide on you deployment directory structure. The good convention is to create folders bin and lib under the deployment root. The bin folder is for executable, the lib folder - for dependencies.
Copy into the lib log4j2 artifacts of appropriate versionsfrom your local maven repository.
For example:

3. The class path in the run command should include executable jar and log4j2 jars.
Running on Windows is like this:
 java -cp lib\log4j-core-2.3.jar;lib\log4j-api-2.3.jar;bin\myCli.jar com.something.MyCliApp
On Linux jars delimiter in the class path ":" instead of ';'. Running on Linux is like this:
 java -cp ./lib/log4j-core-2.3.jar;./lib/log4j-api-2.3.jar;./bin/myCli.jar com.something.MyCliApp
Note:
There are several posts, which mention the maven-shade-plugin.log4j2-cachefile-transformer plugin. This plugin is not the official maven plugin. It was developed by some smart guy, but there is no guarantee, that it will work. At least in my case it doesn't - I am using different java and dependencies versions.
If you want to try, the plugin may be found on this link.

2 comments :

cheap reliable essay writing service said...

Oh man! I can not figure out, no matter how hard I try, these programming solutions can be so tough at times. Thanks mate for this, it is actually very healpful.

Ala Schneider said...

I am really glad this was helpful

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top