Here you can find the the following about automatic modules:
The module system also scans META-INF/services and makes the automatic module provide the services named therein. An automatic module is assumed allowed to use all services.
However, I have the following situation. I want to use log4j2 with slf4j in JPMS. In order to do it log4j-slf4j-impl-2.11.1.jar
must provide JPMS service to slf4j-api-1.8.0-beta2.jar
. The developers of log4j made log4j-slf4j-impl-2.11.1.jar
as automatic module and provided service via META-INF/services. However, it doesn't work, at it gives the following:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/Logger
at org.apache.logging.log4j.slf4j@2.11.1/org.apache.logging.slf4j.SLF4JServiceProvider.initialize(SLF4JServiceProvider.java:53)
at org.slf4j/org.slf4j.LoggerFactory.bind(LoggerFactory.java:153)
at org.slf4j/org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:141)
at org.slf4j/org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:419)
at org.slf4j/org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:405)
at org.slf4j/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:354)
at org.slf4j/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:380)
at Log4j2Slf4jJdk11/com.temp.NewMain.<clinit>(NewMain.java:12)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Logger
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 8 more
I decided to add module-info to log4j-slf4j-impl-2.11.1.jar
and export service in JPMS manner via provides ... with..
. And the problem was solved - I don't get any NoClassDefFoundError
. This is link to the issue.
So my questions:
- does JPMS support services in META-INF/services of automatic modules?
- if yes, then how to explain such behavior?
EDIT There are total 5 modules:
slf4j-api-1.8.0-beta2.jar // name: org.slf4j
log4j-slf4j18-impl-2.11.1.jar // name: org.apache.logging.log4j.slf4j
log4j-core-2.11.1.jar // name: org.apache.logging.log4j.core
log4j-api-2.11.1.jar // name: org.apache.logging.log4j
log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar // name: Log4j2Slf4jJdk11
VARIANT 1 If I run --show-module-resolution when log4j-slf4j18-impl-2.11.1.jar
has META-INF/services
I get the following piece of output (I replaced full path with ...
):
...
root Log4j2Slf4jJdk11 file:.../log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar
Log4j2Slf4jJdk11 requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar
jdk.compiler binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic
org.slf4j binds org.apache.logging.log4j.slf4j file:.../log4j-slf4j18-impl-2.11.1.jar automatic
VARIANT 2 If I run --show-module-resolution when log4j-slf4j18-impl-2.11.1.jar
has module-info
I get the following piece of output:
...
root Log4j2Slf4jJdk11 file:.../log4j2-slf4j-jdk11-1.0-SNAPSHOT.jar
Log4j2Slf4jJdk11 requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar
jdk.compiler binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic
org.slf4j binds org.apache.logging.log4j.slf4j file:.../log4j-slf4j18-impl-2.11.1.jar
org.apache.logging.log4j.slf4j requires org.slf4j file:.../slf4j-api-1.8.0-beta2.jar
org.apache.logging.log4j.slf4j requires org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic
org.apache.logging.log4j.slf4j requires org.apache.logging.log4j file:.../log4j-api-2.11.1.jar
org.apache.logging.log4j binds org.apache.logging.log4j.core file:.../log4j-core-2.11.1.jar automatic
In VARIANT 1 the service from org.apache.logging.log4j.slf4j
can not load class (org.apache.logging.log4j.Logger
) from org.apache.logging.log4j.core
. In VARIANT 2 the service from org.apache.logging.log4j.slf4j
loads all classes from org.apache.logging.log4j.core
and everything is ok. We see in the ouput of VARIANT 2 that there is a line
org.apache.logging.log4j.slf4j requires org.apache.logging.log4j.core
and there is no such line in VARIANT 1. Is the problem in this? But if two modules are automatic can't they be resolved automatically?