I try to migrate a Java8 project to Java9. The auto generated module-info.java contains an entry
requires log4j;
and an error is shown:
log4j cannot be resolved to a module
=> How do I correctly include log4j as a module dependency with Java9?
(I have the same issue for following dependencies: requires hibernate.core; requires hibernate.jpa.2.1.api; requires jcommander; requires junit; requires reflections; )
What I did so far:
- Installed Java 9.0.1
- Upgraded Eclipse to Oxygen.1a Release (4.7.1a)
- Changed Compliance level of my Java project to 9
Generated module-info.java with Right click on project=>Configure=>Generate module-info.java
Updated the plugins in my pom.xml file (also see https://cwiki.apache.org/confluence/display/MAVEN/Java+9+-+Jigsaw) and set java version to 9:
<!-- plugin for compile phase (and test-compile phase) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <!-- specify current java version here: --> <source>9</source> <target>9</target> </configuration> </plugin>
Updated log4j version in pom.xml file since log4j 1.2 does not seem to work with Java9 (see https://blogs.apache.org/logging/entry/moving_on_to_log4j_2)
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.9.1</version> </dependency>
Errors in module-info.java
Even if the compliance level of the project has been set to Java9, there might be shown misleading errors for module-info.java in Eclipse.
I expected that an update of the maven project would only be required if I change the pom.xml file. Now I learned that changing the module-info.java also requires a manual update of the maven project.
=> update the maven project (Alt+F5)
After that update my errors vanished.
I also learned that it is better to first update the versions in the pom.xml file and then generate the module-info.java. Otherwise the module-info.java will include non-existing modules like "requires log4j" instead of "requires log4j.api"
Another misleading error in module-info.java might occur due to pom packaging, see below.
Unresolved imports
For the case that an import can not be resolved the question might be "Which corresponding (new) module do I need for that (old) import?". What might help here:
Search at following page for the required page: http://cr.openjdk.java.net/~mr/jigsaw/ea/module-summary.html (lists all exported packages of the JDK-modules)
Use JDeps on the (old) *.jar file to get a list of required jar files, e.g.
jdeps --class-path "lib" -recursive MY-OLD.jar >output.txt
Use jar to find the module for a jar file
jar --describe-module --file REQUIRED-JAR-FILE.jar
Also see:
What are the predefined modules in JDK9 or Which module do I need to fix dependency problems?
https://blog.codefx.org/tools/jdeps-tutorial-analyze-java-project-dependencies/#Getting-To-Know-JDeps
Re-Export dependencies
In order to automatically make log4j visible for a grandparent project
you might want to use
in parent instead of
in grandparent. Also see:
What's the difference between requires and requires transitive statements in Java 9 module declaration
POM packaging
My main issue seems to be that my Java8 pom.xml file used pom packaging:
If I remove that line, no errors are shown in module-info.java
Also see this extra question: How to use maven with Java9.0.1 and pom packaging in Eclipse Oxygen 1a Release (4.7.1a)?
New log4j version
A. In addition to the change "requires log4j" => "requires log4j.api" I had to adapt the calling code for the new log4j version that is compatible to Java9:
private static Logger sysLog = Logger.getLogger(Main.class);
to
private static Logger sysLog = LogManager.getLogger(Main.class);
B. log4j 2 does not have PropertyConfigurator. Also see this related question:
PropertyConfigurator in log4j2
C. log4j 2 does not support log4j.properties files. Previously I used
src/main/resources/META-INF/log4j.properties
for configuration. Now I use
src/main/resources/log4j2.xml
Also see
Log4j 2 doesn't support log4j.properties file anymore?
Converting log4j.properties to log4j.xml
Working example as a reference
pom.xml:
module-info.java:
Main.java:
Eclipse plugins
In order to add log4j to an eclipse plugin, I copied the file log4j-api-2.10.0.jar in a folder "lib" and added the jar file to Java Build Path=>Libraries=>ModulePath
Instead of
requires log4j.api
I had to userequires org.apache.logging.log4j
I was able to make this work somehow.
module-info.java
to have the following lines:requires log4j.api; requires log4j.core;
import org.apache.logging.log4j.*;
to not use the wildcard. So they changed to:import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;
That's it, it works with both Maven and Eclipse.