I have a project for which I've added an optional dependency to Log4j:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
<optional>true</optional>
</dependency>
In my module descriptor, I've added requirements for both the implementation and the API:
requires static org.apache.logging.log4j;
requires static org.apache.logging.log4j.core;
If I build the project as a pre-module project, the projects builds successfully. However, when I build the project as a module, JUnit fails. While initially the error wasn't clear, adding -e
to the Maven command shows the following error:
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
Unfortunately, this is where I get stuck. When I add -X
I see that both the API and core modules are added to the module path both when compiling and when running the tests. This is from the surefireargs
file that's created:
--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
I've also tried opening the package of the class, but then I get the following warning:
WARNING: Unknown module: org.apache.logging.log4j specified to --add-opens
So even though both Log4j modules are added to the module path, and the org.apache.logging.log4j.util.Supplier
is present in the JAR file, it can't be found when running the tests. This isn't even localized to my local machine; the GitHub action also fails: https://github.com/robtimus/junit-support/actions/runs/3558874573/jobs/5977845973
Edit: adding the following plugin doesn't fix the issue (the plugin already had the source and target set to 11):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>11</release>
</configuration>
</plugin>
CodePudding user response:
I've solved the issue by adding --add-modules
to the surefire plugin's argLine
. I had to add not just Logj4, but also logback, which had the same problem. In addition, because I added some custom test appenders to the logging configuration, I had to open the package to these modules as well.
The result:
<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>