【问题标题】:Custom plugin not getting detected in EAR with log4j2 API使用 log4j2 API 在 EAR 中未检测到自定义插件
【发布时间】:2016-01-17 19:46:35
【问题描述】:

我正在将 EAR 应用程序从 log4j 迁移到 log4j2。我在不同的 EAR jar 中扩展了附加程序、过滤器、布局的类,现在,我已将它们转换为插件。这意味着我在不止一个罐子里有自定义插件(假设 3 个罐子)。

我没有在log4j2.xml 中使用packages 属性,而是使用指向EAR 的META-INF 中的log4j2.xml 位置的Dlog4j.configurationFile JVM 参数来初始化日志系统。

在所有三个 jar 项目中添加以下插件均无效。

<plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <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>

图案布局: 在下面的模式布局中,e 是自定义模式,其中编写了自定义模式转换器插件来转换此字符串。

<Pattern>%d %-5p [%c{1}] [EventId: %e] [%t] %m%n</Pattern>

上述模式布局的自定义转换器插件(在 jar1 中):

jar1 在org.apache.. 文件夹中的META-INF 下有Log4J2Plugins.dat 文件。

@Plugin(name = "EventPatternConverter", category = "Converter")
@ConverterKeys({"e"})

public class EventPatternConverter extends LogEventPatternConverter {

protected EventPatternConverter(String name, String style) {
    super(name, style);
}

public static EventPatternConverter newInstance(String[] options) {
  return new EventPatternConverter("e", "e");
}

@Override
public void format(LogEvent event, StringBuilder toAppendTo) {      
    String eventId= "";
    // Append empty string (OR) value        
    toAppendTo.append(eventId);
  }
}

但是,我收到以下错误

ERROR Unrecognized format specifier [e]

甚至,没有一个自定义插件被识别,因为我得到了invalid element,其余的自定义插件都在 jar2、jar3 中可用,并且它们都有 Log4J2Plugins.dat 文件。

ERROR File contains an invalid element or attribute "TestFilter"

我在 EAR 中使用 log4j-api-2.4.jarlog4j-core-2.4.jarlog4j-jcl-2.4.jarlog4j-web-2.4.1.jarcommons-logging-1.1.1.jar 罐子。

我已经定义了一个自定义模式转换器插件,并希望这个转换器能够应用于所有模式布局,包括使用&lt;patternlayout&gt; 定义的默认模式布局。是这样吗?

如果是,如果有人遇到此问题,请提供帮助,如果我在定义自定义插件时出错,请指导我,因为它们都没有从 EAR 中的 jar 中检测到。

【问题讨论】:

    标签: java logging log4j log4j2 apache-commons-logging


    【解决方案1】:

    在编译自定义插件时,Log4J pom.xml 定义了一个插件,该插件会在文件 META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat 中自动生成缓存数据 您可以在 Maven 项目中的目标/类下看到这一点。

    log4j-core-2.x.x.jar 还包含定义其缓存数据的 Log4j2Plugins.dat。

    问题是在使用 ShrinkWrap 测试 EAR 时创建了一个 JAR,并且通常会将 log4j-core-2.xxjar Log4j2Plugins.dat 添加到测试 JAR 中,因为它很可能是类路径中的第一个。

    这意味着您的自定义插件缓存丢失。

    使用 ShrinkWrap 的解决方案是创建一个新的 Log4j2Plugins.dat,将任何所需的自定义插件缓存文件与核心合并,然后将其添加到 JAR。

    下面的函数实现了...

    private static void mergeLog4J2Log4j2PluginsFile(JavaArchive ja, Class... uniqueJARClasses) {
      // @Author: Johnathan Ingram <jingram@rogueware.org>
      // Log4J2 uses /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat within a JAR to define custom plugins
      //        This is automatically generated by the plugin defined in the log4j-core-2.x.x pom.xml when compiling your custom plugin
      //        The problem with shrinkwrap is that the JAR is not preserved and only a single 
      //        /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
      //        file can exist as JAR files cannot be added to a JAR file as a library.
      //        This is normally the default contained in log4j-core-2.x.x.jar which does not expose any custom plugins
      //        To rectify, both the core and the custom plugin JAR file Log4j2Plugins.dat need to be merged into a single Log4j2Plugins.dat
      try {
         // List of a unique class in each JAR containing a Log4j2Plugins.dat requiring merging
         Vector<URL> datUrls = new Vector<URL>();
         for (Class klass : uniqueJARClasses) {
            // Find  the JAR the class belongs to
            URL classLoc = klass.getProtectionDomain().getCodeSource().getLocation();
            URL resourceURL = classLoc.toString().endsWith(".jar")
                    ? new URL("jar:" + URLDecoder.decode(classLoc.toString(), "UTF-8") + "!/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat")
                    : new URL(URLDecoder.decode(classLoc.toString(), "UTF-8") + "/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat");
            datUrls.add(resourceURL);
         }
    
         // Use the Log4J2 PluginCache to build a merged Log4j2Plugins.dat
         File mergedDatFile = new File("target/Log4j2Plugins.dat");
         try (FileOutputStream fo = new FileOutputStream(mergedDatFile)) {
            org.apache.logging.log4j.core.config.plugins.processor.PluginCache pc = new org.apache.logging.log4j.core.config.plugins.processor.PluginCache();
            pc.loadCacheFiles(datUrls.elements());
            pc.writeCache(fo);
         }
    
         // Replace the default Log4j2Plugins.dat if present
         ja.delete("/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat");
         ja.addAsManifestResource(mergedDatFile, "org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat");
    
      } catch (Exception ex) {
         ex.printStackTrace(System.err);
      }
    }
    

    使用您的示例运行:

    JavaArchive ja = ShrinkWrap.create(JavaArchive.class, "my-test.jar");
    ...
    mergeLog4J2Log4j2PluginsFile(ja, org.apache.logging.log4j.core.config.plugins.processor.PluginCache.class, EventPatternConverter.class);
    

    【讨论】:

      猜你喜欢
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      相关资源
      最近更新 更多