Log4j2 custom plugins - annotation processing using the Maven Assembly plugin

I am not very familiar with Maven, I started using it only yesterday, but I like it. In my project, I use the Log4j2 library for logging and due to insufficient support for additional plug-ins (for example, converters, converters) I need to use custom plugins . log4j-api and log4j-core (also with several other libraries) are added as dependencies in pom.xml related to my project. I am actually using version 2.0 of Log4j.

Log4j uses annotation processing for preload classes marked as @Plugin . As far as I know, in older versions of log4j in pom.xml you need to specify an additional entry in the plugin in order to initiate the plugin processing, or packages with custom plugins should have been entered into the packages attribute in the configuration file ( https://logging.apache.org /log4j/2.x/manual/configuration.html#ConfigurationSyntax ). But this is not supported with 2.0-rc2.

In version 2.0, this should be done automatically while log4j-core is available to the building engine. There is a Log4j2Plugins.dat file in myproject-0.0.1-SNAPSHOT.jar / META-INF / org / apache / logging / log4j / core / config / plugins / that contains the mappings of my custom plugins - this is normal.

To build with Maven, I also use the Maven Assembly Plugin . Its single target is tied to the package phase. After packing the project, I naturally have one more jar in the target directory - myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar. However, the Log4j2Plugins.dat file in this bank contains the source plug-in mappings, the same file as the log4j-core library. And this problem, because it does not contain links to my custom plugins. It seems that the file from myproject-0.0.1-SNAPSHOT.jar is overwritten by the original file from the log4j library, but I'm not sure what this is.

So when I run myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar, log4j cannot find the plugin classes from my project. I think myproject-0.0.1-SNAPSHOT.jar will work fine, but I cannot run it without dependencies.

The packages attribute in the configuration must be re-enabled in version 2.0.1, but if I do not want to wait for the release, I must use the annotation processing method.

Do you have an idea how to fix it?


I tried to launch it with the release of 2.0-rc1 log4j, where the packages attribute of the configuration item could be used. Result: log4j successfully loaded the class of my custom plugin. However, there were so many other errors (which arose in this particular version) that made the program even more unusable.

This is one good point that ensures that if the packages attribute is included in the next version 2.0.1, my plugin will work. It should be restored according to this problem tracking: https://issues.apache.org/jira/browse/LOG4J2-741


Added by my pom.xml

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jjurm</groupId> <artifactId>twbot</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>twbot</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.4</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.jjurm.twbot.system.Run</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.jjurm.twbot.system.Run</mainClass> </manifest> </archive> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mariadb.jdbc</groupId> <artifactId>mariadb-java-client</artifactId> <version>1.1.7</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>net.snaq</groupId> <artifactId>dbpool</artifactId> <version>6.0</version> </dependency> <dependency> <groupId>org.fusesource.jansi</groupId> <artifactId>jansi</artifactId> <version>1.11</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>commons-jxpath</groupId> <artifactId>commons-jxpath</artifactId> <version>1.3</version> </dependency> <dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.15</version> </dependency> </dependencies> </project> 
+6
source share
2 answers

I think the problem is with dependency packaging in a jar. Performing a quick dive into the code, it seems that the plug-in processor overwrites the plug-in data file for each set of plug-ins. I assume that during the packaging process, your custom plugins are processed and written to the data file, and then overwritten when your log4j dependency is processed to be included in the package. There may be better solutions, but from my head I suggest you do one of the following:

  • Do not pack dependencies in your jar. Just pack your project, and then include the dependencies on your classpath at runtime. Even if you want to pack everything in one portable jar, this will allow you to at least confirm whether your plugins are being rewritten or something else is wrong.

  • Create a separate project for your custom plug-ins, place it separately from the main project, and then include the resulting jar as a dependency. As with option 1, make sure that you do not include log4j jars in this package. Once you have created your custom plugin jar, you can pack it along with other dependencies in your main bank, and it should work fine, since your custom plugin banner will have its own plugin dll file.

Good luck

+5
source

Another solution is mentioned in Log4j 2 issue 673 . Use the maven shade plugin with a special transformer instead of the maven build plugin .

 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <configuration> <transformers> <transformer implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer" /> </transformers> </configuration> <dependencies> <dependency> <groupId>com.github.edwgiz</groupId> <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId> <version>2.6.1</version> </dependency> </dependencies> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> 

If I understand him correctly, the transformer creates the Log4j2Plugins.dat file by correctly merging Log4j2Plugins.dat from all the dependencies and the main bank, i.e. All plugins will be included.

+4
source

Source: https://habr.com/ru/post/973186/


All Articles