Проблемы с использованием log4j в затененной банке

У меня есть следующая ситуация в моем проекте:

  1. в основное приложение (которое разрабатывалось отдельно разными людьми и имеет свои, частично пересекающиеся, зависимости) интегрируется большой модуль (назовем его конвертер) со своими зависимостями;

  2. изначально этот модуль преобразователя можно было вызывать из командной строки как исполняемый файл jar, поэтому он имеет свои собственные точки входа (выполняемые классы с определенными методами main()); этот исполняемый файл jar всегда создавался как uber-jar с помощью плагина maven shadow;

  3. теперь этот модуль преобразователя должен быть дополнительно вызываемым из основного приложения (для этого я пока напрямую вызываю main() классов точки входа после формирования аргументов командной строки). Основное приложение также создано в виде uber-jar и в дальнейшем планируется создавать его таким же образом.

Поэтому я собираюсь добиться правильного разделения зависимостей с помощью плагина оттенка для этого случая, для этого я добавил следующие спецификации перемещения в 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>

В результате все зависимости модуля преобразователя заштрихованы (с добавлением к ним quase.) при объединении в uber-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.

Поэтому мне кажется, что затененный код ведения журнала, вызываемый из модуля преобразователя, получает ссылку на незатененный код ведения журнала, уже инициализированный в основном приложении, и терпит неудачу, потому что он ожидает затененный код (см. 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 — это префикс затенения.

Что я делаю не так? Любая помощь приветствуется.


person shekvl    schedule 28.04.2015    source источник
comment
Я нашел обходной путь, добавив дополнительные спецификации добавления в log4j.properties, в которых явно упоминаются затененные классы: log4j.appender.file3=quase.org.apache.log4j.FileAppender; в этом случае инициализация логгера по-прежнему приводит к указанной выше ошибке для исходного приложения (из основного приложения), но тогда приложение из конвертера инициализируется правильно и затем используется для ведения журнала. Это, однако, не является реальным решением и вовсе не является автоматическим.   -  person shekvl    schedule 28.04.2015


Ответы (1)


Мы столкнулись с той же проблемой, и мы исправили ее, исключив 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>
person Sanchi Girotra    schedule 14.08.2018