How to use log4j with maven and java9 in Eclipse Oxygen?
Asked Answered
P

2

4

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>
    
Planoconvex answered 10/11, 2017 at 13:4 Comment(4)
You shouldn't bind the compiler plugin another time to the life cycle. Define the maven-compiler-plugin only in pluginManagement version 3.7.0 and define source/target...no bindings.. The log4j-api does not contain a modules-info.class file so only automodule name is used which is log4j-api ? and not log4j...Convulse
If none of the requires is recognized, I would insist you to share the complete project structure followed and <build> config of your pom.xml. Also the automatic module name derived for the above dependencies are log4j.api and log4j.core respectively.Reest
You can use the jar command (from Java 9) to find out the name of a module: jar --describe-module --file $JAR-FILE tells you by which name you have to require it. Furthermore, you can use JDeps to identify which JARs you directly depend on.Goofball
@nullpointer The pom packaging that I want to use (I did not mention it in my question because I first thought it would not be relevant) does not include the compile phase. Therefore I had to explicitly include the compiler plugin.Planoconvex
P
3

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:

Re-Export dependencies

In order to automatically make log4j visible for a grandparent project

grandparent => parent => log4j

you might want to use

requires transitive log4j.api 

in parent instead of

requires log4j.api

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:

<packaging>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

Working example as a reference

enter image description here

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Log4JWithJava9</groupId>
  <artifactId>Log4JWithJava9</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <release>9</release>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
  <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>
  </dependencies>

</project>

module-info.java:

module Log4JWithJava9 {
    requires javafx.base;
    requires log4j.api; 
}

Main.java:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


public class Main {

    private static Logger sysLog = LogManager.getLogger(Main.class);

    public static void main(String[] args) {

    }

}

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 use requires org.apache.logging.log4j

enter image description here

Planoconvex answered 10/11, 2017 at 14:3 Comment(0)
A
0

I was able to make this work somehow.

  1. I downloaded the latest Eclipse Photon Release (4.8.0), I don't know if this fix will work with older versions.
  2. I changed the module-info.java to have the following lines: requires log4j.api; requires log4j.core;
  3. I had to switch to an earlier version of log4j, 2.8.2.
  4. I changed all my imports that say 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.

Asphyxiate answered 6/9, 2018 at 12:27 Comment(3)
That doesnt work for me, using the same eclipse and the same setup as described by you i get either: "log4j.api cannot be resolved to a module" in the module-info Class or "The package org.apache.logging.log4j is accessible from more than one module: org.apache.logging.log4j, org.apache.logging.log4j.core" when I do not create the module-info file.Wein
See: bugs.eclipse.org/bugs/show_bug.cgi?id=534624 Looks like we have to wait for Eclipse 4.8.1 or even 4.9.0 Release to get this fixed.Wein
I changed the instructions. Changed step 2 and added step 3. I have it workingAsphyxiate

© 2022 - 2024 — McMap. All rights reserved.