У меня есть проект, для которого я добавил необязательную зависимость к Log4j:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
<optional>true</optional>
</dependency>
В моем дескрипторе модуля я добавил требования как к реализации, так и к API:
requires static org.apache.logging.log4j;
requires static org.apache.logging.log4j.core;
Если я создам проект как предварительный модуль, проекты будут успешно построены. Однако, когда я создаю проект как модуль, JUnit дает сбой. Хотя изначально ошибка не была ясной, добавление -e к команде Maven показывает следующую ошибку:
TestEngine with ID 'junit-jupiter' failed to discover tests
org.junit.platform.commons.JUnitException: TestEngine with ID 'junit-jupiter' failed to discover tests
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:160)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:132)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:78)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:110)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:78)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.discover(DefaultLauncherSession.java:81)
at org.apache.maven.surefire.junitplatform.LazyLauncher.discover(LazyLauncher.java:48)
at org.apache.maven.surefire.junitplatform.TestPlanScannerFilter.accept(TestPlanScannerFilter.java:56)
at org.apache.maven.surefire.api.util.DefaultScanResult.applyFilter(DefaultScanResult.java:102)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.scanClasspath(JUnitPlatformProvider.java:167)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:139)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:456)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:169)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:595)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:581)
Caused by: org.junit.platform.commons.JUnitException: ClassSelector [className = 'com.github.robtimus.junit.support.extension.testlogger.Log4jLoggerContextTest'] resolution failed
at org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener.selectorProcessed(AbortOnFailureLauncherDiscoveryListener.java:39)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:103)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:83)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:113)
at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolveSelectors(DiscoverySelectorResolver.java:46)
at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:69)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:152)
... 15 more
Caused by: java.lang.NoClassDefFoundError: org/apache/logging/log4j/util/Supplier
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1096)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:759)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:680)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:605)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166)
at java.base/java.lang.Class.getDeclaredMethods(Class.java:2309)
at [email protected]/org.junit.platform.commons.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:1494)
at [email protected]/org.junit.platform.commons.util.ReflectionUtils.findMethod(ReflectionUtils.java:1343)
at [email protected]/org.junit.platform.commons.util.ReflectionUtils.isMethodPresent(ReflectionUtils.java:1244)
at org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.hasTestOrTestFactoryOrTestTemplateMethods(IsTestClassWithTests.java:50)
at org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.test(IsTestClassWithTests.java:46)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver.resolve(ClassSelectorResolver.java:67)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:135)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1632)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:189)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:126)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:92)
... 20 more
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.util.Supplier
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 52 more
К сожалению, здесь я застрял. Когда я добавляю -X, я вижу, что и API, и основные модули добавляются в путь к модулям как при компиляции, так и при запуске тестов. Это из созданного файла surefireargs:
--module-path
"D:\\Code\\Java\\github\\misc\\junit-support\\target\\classes;D:\\Programs\\Maven.repository\\org\\junit\\jupiter\\junit-jupiter-api\\5.9.0\\junit-jupiter-api-5.9.0.jar;D:\\Programs\\Maven.repository\\org\\junit\\platform\\junit-platform-commons\\1.9.0\\junit-platform-commons-1.9.0.jar;D:\\Programs\\Maven.repository\\org\\junit\\jupiter\\junit-jupiter-params\\5.9.0\\junit-jupiter-params-5.9.0.jar;D:\\Programs\\Maven.repository\\org\\hamcrest\\hamcrest\\2.2\\hamcrest-2.2.jar;D:\\Programs\\Maven.repository\\org\\mockito\\mockito-core\\4.8.0\\mockito-core-4.8.0.jar;D:\\Programs\\Maven.repository\\com\\github\\robtimus\\io-functions\\2.0\\io-functions-2.0.jar;D:\\Programs\\Maven.repository\\org\\apache\\logging\\log4j\\log4j-api\\2.19.0\\log4j-api-2.19.0.jar;D:\\Programs\\Maven.repository\\org\\apache\\logging\\log4j\\log4j-core\\2.19.0\\log4j-core-2.19.0.jar;D:\\Programs\\Maven.repository\\ch\\qos\\logback\\logback-classic\\1.4.5\\logback-classic-1.4.5.jar;D:\\Programs\\Maven.repository\\ch\\qos\\logback\\logback-core\\1.4.5\\logback-core-1.4.5.jar;D:\\Programs\\Maven.repository\\org\\slf4j\\slf4j-api\\2.0.4\\slf4j-api-2.0.4.jar;D:\\Programs\\Maven.repository\\ch\\qos\\reload4j\\reload4j\\1.2.23\\reload4j-1.2.23.jar;D:\\Programs\\Maven.repository\\org\\opentest4j\\opentest4j\\1.2.0\\opentest4j-1.2.0.jar;D:\\Programs\\Maven.repository\\org\\apiguardian\\apiguardian-api\\1.1.2\\apiguardian-api-1.1.2.jar"
--class-path
"D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-booter\\3.0.0-M7\\surefire-booter-3.0.0-M7.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-api\\3.0.0-M7\\surefire-api-3.0.0-M7.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-logger-api\\3.0.0-M7\\surefire-logger-api-3.0.0-M7.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-shared-utils\\3.0.0-M7\\surefire-shared-utils-3.0.0-M7.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-extensions-spi\\3.0.0-M7\\surefire-extensions-spi-3.0.0-M7.jar;D:\\Code\\Java\\github\\misc\\junit-support\\target\\test-classes;D:\\Programs\\Maven.repository\\org\\junit\\jupiter\\junit-jupiter\\5.9.0\\junit-jupiter-5.9.0.jar;D:\\Programs\\Maven.repository\\org\\junit\\jupiter\\junit-jupiter-engine\\5.9.0\\junit-jupiter-engine-5.9.0.jar;D:\\Programs\\Maven.repository\\org\\junit\\platform\\junit-platform-engine\\1.9.0\\junit-platform-engine-1.9.0.jar;D:\\Programs\\Maven.repository\\net\\bytebuddy\\byte-buddy\\1.12.14\\byte-buddy-1.12.14.jar;D:\\Programs\\Maven.repository\\net\\bytebuddy\\byte-buddy-agent\\1.12.14\\byte-buddy-agent-1.12.14.jar;D:\\Programs\\Maven.repository\\org\\objenesis\\objenesis\\3.2\\objenesis-3.2.jar;D:\\Programs\\Maven.repository\\commons-io\\commons-io\\2.11.0\\commons-io-2.11.0.jar;D:\\Programs\\Maven.repository\\org\\junit\\platform\\junit-platform-testkit\\1.9.0\\junit-platform-testkit-1.9.0.jar;D:\\Programs\\Maven.repository\\org\\assertj\\assertj-core\\3.23.1\\assertj-core-3.23.1.jar;D:\\Programs\\Maven.repository\\org\\junit\\platform\\junit-platform-launcher\\1.9.0\\junit-platform-launcher-1.9.0.jar;D:\\Programs\\Maven.repository\\org\\junit-pioneer\\junit-pioneer\\1.9.0\\junit-pioneer-1.9.0.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\surefire-junit-platform\\3.0.0-M7\\surefire-junit-platform-3.0.0-M7.jar;D:\\Programs\\Maven.repository\\org\\apache\\maven\\surefire\\common-java5\\3.0.0-M7\\common-java5-3.0.0-M7.jar"
--patch-module
com.github.robtimus.junit.support = "D:\\Code\\Java\\github\\misc\\junit-support\\target\\test-classes"
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.examples.collections=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.examples.covariantreturn=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.examples.delegation=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.examples.io=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testlogger=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testresource=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.params=ALL-UNNAMED
--add-opens
com.github.robtimus.junit.support/com.github.robtimus.junit.support.test.collections=ALL-UNNAMED
--add-modules
com.github.robtimus.junit.support
--add-reads
com.github.robtimus.junit.support=ALL-UNNAMED
org.apache.maven.surefire.booter.ForkedBooter
Я также пытался открыть пакет класса, но потом получаю следующее предупреждение:
WARNING: Unknown module: org.apache.logging.log4j specified to --add-opens
Таким образом, несмотря на то, что оба модуля Log4j добавлены в путь к модулю, а org.apache.logging.log4j.util.Supplier присутствует в файле JAR, его невозможно найти при запуске тестов. Это даже не локализовано на моей локальной машине; действие GitHub также не выполняется: https://github.com/robtimus/junit-support/actions/runs/3558874573/jobs/5977845973
Редактировать: добавление следующего плагина не решает проблему (плагин уже имеет источник и цель, установленные на 11):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>11</release>
</configuration>
</plugin>
К сожалению, это дает мне ошибки компилятора из-за несовместимости между версиями 2.x и 3.x. Например, github.com/apache/logging-log4j2/blob/release-2.x/log4j-core/… перемещен на github.com/apache/logging-log4j2/blob/master/log4j. -plugins/src/…
Мы будем очень признательны за отзывы о версии 3.0, так как она приближается к тому моменту, когда мы хотим ее выпустить. Поскольку основной мотивацией для версии 3.0 была полная поддержка JPMS, чем раньше мы получим обратную связь, тем лучше. Плагины НЕ должны перекомпилироваться, но если вы перекомпилируете, вам придется обновить исходный код.
@rgoers Теперь я вижу, что плагины были выделены в отдельный модуль. Однако с переименованием пакета это означает, что любые существующие плагины (вероятно) не будут работать. Это проверялось?
Я нашел решение, смотрите ниже. Не знаю, почему мне пришлось делать это для Log4j и logback, но не для reload4j, SLF4J или java.logging.
@RobSpoor Да, это было протестировано, но вполне возможно, что со всеми изменениями, происходящими в 3.0, что-то не работает. Если вы столкнетесь с какими-либо проблемами, будет приятно, если вы предоставите команде Log4j тест, иллюстрирующий это.
@rgoers Я проверил это и создал Issues.apache.org/jira/browse/LOG4J2-3640 с моими выводами.




Я решил проблему, добавив --add-modules к плагину surefire argLine. Пришлось добавить не только Logj4, но и logback, у которого была та же проблема. Кроме того, поскольку я добавил несколько пользовательских тестовых приложений в конфигурацию ведения журнала, мне также пришлось открыть пакет для этих модулей.
Результат:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-modules org.apache.logging.log4j
--add-modules ch.qos.logback.classic
--add-modules ch.qos.logback.core
--add-opens com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testlogger=java.logging
--add-opens com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testlogger=org.apache.logging.log4j.core
--add-opens com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testlogger=ch.qos.logback.core
--add-opens com.github.robtimus.junit.support/com.github.robtimus.junit.support.extension.testlogger=ch.qos.reload4j
<!-- other existing add-opens omitted -->
</argLine>
</configuration>
</plugin>
Да, вам придется открывать свои пакеты для других модулей, которым необходим к ним доступ.
В этом случае нужно только позволить фреймворкам ведения журналов создавать экземпляры моих классов приложений. Фактический код использует их общедоступные API только в качестве потребителя.
Поскольку версия 2.x не полностью модульная, можете ли вы проверить последнюю версию
3.0.0-SNAPSHOT? Он доступен в репозитории Apache Repository Maven.