在阴影jar中使用log4j的问题

时间:2015-04-28 08:49:58

标签: maven jar log4j maven-shade-plugin relocation

我的项目中存在以下情况:

  1. 一个大型模块(称为转换器)具有自己的依赖项,正在集成到主应用程序中(由不同的人单独开发并具有自己的,部分重叠的依赖项);

    < / LI>
  2. 最初这个转换器模块可以从命令行调用为可执行jar,因此它有自己的入口点(定义了main()方法的runnable类);这个可执行的jar总是通过maven shade插件创建为超级jar;

  3. 现在这个转换器模块必须可以从主应用程序中另外调用(为此,我现在在形成命令行参数后直接调用入口点类的main())。主应用程序也被创建为超级jar,并计划继续以这种方式创建。

  4. 因此,在这种情况下,我将使用shade插件实现依赖关系的正确分离,为此,我已将以下重定位规范添加到转换器模块的pom.xml中:

    <relocations>
    <relocation>
    <pattern>com</pattern>
      <shadedPattern>quase.com</shadedPattern>
    </relocation>
    <!-- ... other top-level patterns for converter dependencies -->
    <relocation>
      <pattern>org</pattern>
      <shadedPattern>quase.org</shadedPattern>
      <excludes>
        <exclude>org.aau.**</exclude> <!-- my own code for converter is not shaded -->
      </excludes>
    </relocation>
    </relocations>
    

    结果,转换器模块的所有依赖关系都被着色(对它们有预先假设),同时组合到主应用程序的超级jar中。

    此配置的问题是应用程序和转换器都使用日志记录(slf4j和log4j),并且从应用程序代码调用转换器方法并开始使用日志记录后,会发生以下错误:

    log4j:ERROR A "org.apache.log4j.FileAppender" object is not assignable to a "quase.org.apache.log4j.Appender" variable.
    log4j:ERROR The class "quase.org.apache.log4j.Appender" was loaded by
    log4j:ERROR [sun.misc.Launcher$AppClassLoader@55f96302] whereas object of type
    log4j:ERROR "org.apache.log4j.FileAppender" was loaded by [sun.misc.Launcher$AppClassLoader@55f96302].
    log4j:ERROR Could not instantiate appender named "file1".
    log4j:ERROR A "org.apache.log4j.FileAppender" object is not assignable to a "quase.org.apache.log4j.Appender" variable.
    log4j:ERROR The class "quase.org.apache.log4j.Appender" was loaded by
    log4j:ERROR [sun.misc.Launcher$AppClassLoader@55f96302] whereas object of type
    log4j:ERROR "org.apache.log4j.FileAppender" was loaded by [sun.misc.Launcher$AppClassLoader@55f96302].
    log4j:ERROR Could not instantiate appender named "file2".
    log4j:ERROR A "org.apache.log4j.ConsoleAppender" object is not assignable to a "quase.org.apache.log4j.Appender" variable.
    log4j:ERROR The class "quase.org.apache.log4j.Appender" was loaded by
    log4j:ERROR [sun.misc.Launcher$AppClassLoader@55f96302] whereas object of type
    log4j:ERROR "org.apache.log4j.ConsoleAppender" was loaded by [sun.misc.Launcher$AppClassLoader@55f96302].
    log4j:ERROR Could not instantiate appender named "console".
    log4j:WARN No appenders could be found for logger (org.aau.quase.quontology.builder.QuLogHandler).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    

    因此在我看来,从转换器模块调用的着色日志记录代码获取了对已在主应用程序中初始化的非着色日志记录代码的引用,并因为它需要着色代码而失败,因为它需要分配非阴影org.apache.log4j.FileAppender以遮蔽quase.org.apache.log4j.Appender)。

    我试图在转换器的pom.xml中排除日志中的日志记录依赖项:

    <excludes>
        <exclude>org.aau.**</exclude>
        <exclude>org.apache.log4j.**</exclude>
        <exclude>org.slf4j.**</exclude>
    </excludes>
    

    但这导致了进一步的问题:整个应用程序失败如下:

    Exception in thread "main" java.lang.NoClassDefFoundError
            at org.apache.log4j.Category.class$(Category.java:118)
            at org.apache.log4j.Category.<clinit>(Category.java:118)
            at org.apache.log4j.LogManager.<clinit>(LogManager.java:82)
            at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:66)
            at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:277)
            at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:288)
            at org.aau.quase.application.LoggingProtocolHandler.<clinit>(LoggingProtocolHandler.java:16)
            at org.aau.quase.application.QuASEApplication$1.<init>(QuASEApplication.java:71)
            at org.aau.quase.application.QuASEApplication.<init>(QuASEApplication.java:65)
            at org.aau.quase.application.util.QuASERunner.main(QuASERunner.java:8)
    Caused by: java.lang.ClassNotFoundException: quase/org.apache.log4j.Category
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Unknown Source)
            ... 10 more
    

    看起来转换器代码仍然需要阴影版本,因为它找不到quase/org.apache.log4j.Category而quase是阴影前缀。

    我做错了什么?非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我们面临着同样的问题,我们通过从根目录本身中排除log4j而不是重新定位它们来解决了该问题。

<configuration>
                                <filters>
                                    <filter>
                                        <artifact>groupId:artifactId:*</artifact>
                                        <excludes><exclude>org/apache/log4j/**</exclude></excludes>
                                    </filter>
                                </filters>

                                <relocations>
                                    <relocation>
                                        <pattern>com</pattern>
                                        <shadedPattern>xyz.shaded.com</shadedPattern>
                                    </relocation>
                                </relocations>
                            </configuration>
相关问题