Log4j2 自定义插件 - 使用 Maven Assembly Plugin 进行注解处理 [英] Log4j2 custom plugins - annotation processing with Maven Assembly Plugin

查看:51
本文介绍了Log4j2 自定义插件 - 使用 Maven Assembly Plugin 进行注解处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Maven不是很熟悉,我昨天才开始使用它,但我喜欢它.在我的项目中,我使用 Log4j2 库进行日志记录,并且由于高级插件(如附加程序、转换器)的不足我需要使用自定义插件.log4j-apilog4j-core(还有一堆其他库)作为依赖项添加到与我的项目相关的 pom.xml 中.实际上我使用的是 Log4j 2.0 版.

Log4j 使用注解处理来预加载标记为 @Plugin 的类.据我所知,在旧版本的 log4j 中,必须在 pom.xml 中指定额外的插件条目以触发插件处理,或者必须将带有自定义插件的包输入到 配置文件中的packages 属性(https://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax).但自 2.0-rc2 起不支持此功能.

在 v2.0 中,这应该自动完成,只要 log4j-core 可用于构建引擎.在myproject-0.0.1-SNAPSHOT.jar/META-INF/org/apache/logging/log4j/core/config/plugins/中有一个文件Log4j2Plugins.dat包含我的自定义插件的映射 - 没关系.

为了使用 Maven 构建,我还使用 Maven 程序集插件.它的目标 single 绑定到 package 阶段.打包项目后,我自然会在 target 目录中多了一个 jar - myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar.但是,这个 jar 中的 Log4j2Plugins.dat 文件包含原始插件的映射,与 log4j-core 库中的文件相同.这就是问题所在,因为它不包含对我的自定义插件的任何引用.myproject-0.0.1-SNAPSHOT.jar 中的文件似乎被 log4j 库中的原始文件覆盖了,但我不确定是什么情况.

因此,当我运行 myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar 时,log4j 无法从我的项目中找到插件类.我认为 myproject-0.0.1-SNAPSHOT.jar 可以正常运行,但没有依赖项我无法运行它.

配置中的packages属性应该在2.0.1版本中重新开启,但是如果不想等发布,就得使用注解处理方式了.>

你知道如何修复它吗?

<小时>

我尝试使用 log4j 的 2.0-rc1 版本运行它,其中配置元素的 packages 属性可用.结果是:log4j 成功加载了我的自定义插件的类.但是,还有许多其他错误(在此特定版本中出现)使程序更加无法使用.

这是一个很好的观点,它确保我在下一个版本 2.0.1 中启用 packages 属性时,我的插件工作.它应该根据此问题跟踪恢复:https://issues.apache.org/jira/browse/LOG4J2-741

<小时>

添加了我的 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><包装>罐</包装><name>twbot</name><url>http://maven.apache.org</url><属性><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></属性><构建><插件管理><插件><插件><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><配置><source>1.7</source><目标>1.7</目标></配置></插件></plugins></pluginManagement><插件><插件><artifactId>maven-assembly-plugin</artifactId><version>2.4</version><配置><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><存档><清单><mainClass>com.jjurm.twbot.system.Run</mainClass></清单></存档></配置><执行><执行><id>make-assembly</id><!-- 用于继承合并--><phase>包</phase><!-- 绑定到打包阶段--><目标><目标>单</目标></目标><配置><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><存档><清单><mainClass>com.jjurm.twbot.system.Run</mainClass></清单></存档></配置></执行></执行></插件></plugins></build><依赖项><依赖><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><范围>测试</范围></依赖><依赖><groupId>org.mariadb.jdbc</groupId><artifactId>mariadb-java-client</artifactId><version>1.1.7</version></依赖><依赖><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.3</version></依赖><依赖><groupId>commons-configuration</groupId><artifactId>commons-configuration</artifactId><version>1.10</version></依赖><依赖><groupId>net.snaq</groupId><artifactId>dbpool</artifactId><version>6.0</version></依赖><依赖><groupId>org.fusesource.jansi</groupId><artifactId>jansi</artifactId><version>1.11</version></依赖><依赖><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.0</version></依赖><依赖><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.0</version></依赖><依赖><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.7</version></依赖><依赖><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.0</version></依赖><依赖><groupId>commons-jxpath</groupId><artifactId>commons-jxpath</artifactId><version>1.3</version></依赖><依赖><groupId>net.sourceforge.htmlunit</groupId><artifactId>htmlunit</artifactId><version>2.15</version></依赖></依赖项></项目>

解决方案

我认为问题源于将依赖项打包到 jar 中.快速深入代码,看起来插件处理器会为它处理的每组插件覆盖插件 dat 文件.我的猜测是,在打包过程中,您的自定义插件被处理并写入 dat 文件,然后在处理您的 log4j 依赖项以包含在包中时被覆盖.可能有更好的解决方案,但我建议您执行以下操作之一:

  1. 不要将依赖项打包到您的 jar 中.只需打包您的项目,然后在执行时将依赖项包含在您的类路径中.即使您想将所有内容都打包在一个可移植的 jar 中,这样做至少可以让您确认您的插件是否被覆盖,或者是否有其他问题.

  2. 为您的自定义插件创建一个单独的项目,将其与您的主项目分开打包,然后将生成的 jar 作为依赖项包含在内.与选项 1 一样,请确保您不将 log4j jar 包含在此包中.创建自定义插件 jar 后,您可以将其与主 jar 中的其他依赖项一起打包,它应该可以正常工作,因为您的自定义插件 jar 将拥有自己的插件 dat 文件.

祝你好运!

I am not very familiar with Maven, I started using it just yesterday, but I like it. In my project I use Log4j2 library for logging and because of insufficiecy of advanced plugins (like appenders, converters) I need to use custom plugins. log4j-api and log4j-core (also with a bunch of other libraries) are added as dependencies in pom.xml associated with my project. Actually I am using version 2.0 of Log4j.

Log4j uses annotation processing to pre-load classes marked as @Plugin. As far as I know, in older releases of log4j, additional plugin entry had to be specified in pom.xml to trigger plugin processing, or the packages with custom plugins had to be typed into the packages attribute in the configuration file (https://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax). But this is not supported since 2.0-rc2.

In v2.0 this should be done automatically, as long as log4j-core is available to the building engine. There is a file Log4j2Plugins.dat in myproject-0.0.1-SNAPSHOT.jar/META-INF/org/apache/logging/log4j/core/config/plugins/ that contains mappings of my custom plugins - that's OK.

For building with Maven I use also Maven Assembly Plugin. Its goal single is binded to package phase. After packaging the project I naturally have one additional jar in the target directory - myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar. However, Log4j2Plugins.dat file in this jar contains mappings of original plugins, the same file as in the log4j-core library. And that's the problem, since it doesn't hold any references to my custom plugins. It seems that the file from myproject-0.0.1-SNAPSHOT.jar is being overwritten with the original file from the log4j library, but I am not sure what's the case.

So when I run myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar, log4j can't find the plugin classes from my project. I think that myproject-0.0.1-SNAPSHOT.jar would run ok, but I can't run it without the dependencies.

The packages attribute in configuration should be re-enabled in 2.0.1 release, but if I don't want to wait for the release, I have to use the annotation processing method.

Do you have an idea how to fix it?


I tried to run it with release 2.0-rc1 of log4j, where the packages attribute of the configuration element was usable. The result is: log4j successfully loaded the class of my custom plugin. However, there were so many other errors (that arised in this specific release) that make the program even more unusable.

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


Added 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>

解决方案

I think the problem stems from packaging the dependencies into the jar. Doing a quick dive into the code, it looks like the plugin processor overwrites the plugin dat file for each set of plugins it handles. My guess is that during the packaging process, your custom plugins are processed and written to the dat file, and then overwritten when your log4j dependency is processed for inclusion in the package. There may be better solutions, but off the top of my head I would suggest that you do one of the following:

  1. Do not package the dependencies into your jar. Just package your project and then include the dependencies on your classpath when you execute. Even if you want to package everything in a single portable jar, doing this would allow you to at least confirm if your plugins are being overwritten, or if there is something else wrong.

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

Good luck!

这篇关于Log4j2 自定义插件 - 使用 Maven Assembly Plugin 进行注解处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆