4

I want to switch from Oracle JDK 8 to Open JDK 11 using Eclipse 2018-12. I have the following situation:

In my Eclipse workspace I have a main maven project called example with some maven dependencies my_dependency_1, my_dependency_2 that are also maven projects in the same workspace. Currently, only example is modular (and thus contains a module-info.java). The other projects are non-modular and are included in the pom.xml as well as required (automatic) modules in the module-info.java of example. I recognized the following:

When I close all Eclipse projects in my workspace except example, then all (non-modular) dependency .jars get correctly included from the .m2 repository in the module-path as automatic modules and my example project runs fine. I can verify this by looking at Run Configurations > Arguments > Show Command Line.

In contrast, when I open the projects with my dependencies in my workspace as well, the dependencies get not included into the module-path and thus the example project doesn't run (resulting in Error occurred during initialization of boot layer, java.lang.module.FindException: Module my_dependency_1, ... not found, required by example).

My question is: Do I need to convert all my_dependencies_1, ... from non-modular to modular dependencies if I want to open and work with them along with my modular example project in my workspace, or is there any option that lets me keep working even with the non-modular dependency projects? I'm looking for a simple and clean solution and not for a "hack" with manually appending funky stuff to the startup arguments. If this is not possible I'd prefer to take some time to convert each dependency into a modular one with the drawback of being not usable anymore in other projects still written for Java 8.

Thanks for clarification :)

Here is a basic example for demonstration:

pom.xml (of project example)

<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>com.example</groupId>
  <artifactId>example</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>com.example</groupId>
      <artifactId>mydependency</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

Example.java (of project example)

package example;
import mydependency.MyDependency;

public class Example {
    public static void main(String[] args) { 
        MyDependency.run();
    }
}

module-info.java (of project example)

open module example {
    requires mydependency;
}

pom.xml (of project mydependency)

<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>com.example</groupId>
  <artifactId>mydependency</artifactId>
  <version>1.0-SNAPSHOT</version>
</project>

MyDependency.java (of project mydependency)

package mydependency;
public class MyDependency {
    public static void run() {
        System.out.println("run");
    }
}

Command line when running if project is closed (works properly):

C:\me\jdk-11.0.1\bin\javaw.exe
-Dfile.encoding=UTF-8
-p "C:\me\workspace\example\target\classes;C:\me\.m2\repository\com\example\mydependency\1.0-SNAPSHOT\mydependency-1.0-SNAPSHOT.jar"
-m example/example.Example

Command line when running if project is opened (target/classes of mydependency is missing):

C:\me\jdk-11.0.1\bin\javaw.exe
-Dfile.encoding=UTF-8
-p "C:\me\workspace\example\target\classes"
-m example/example.Example
user27772
  • 522
  • 1
  • 4
  • 18
  • *when I open the projects with my dependencies in my workspace as well, the dependencies get not included into the module-path*... possibly that is where the answer lies and Eclipse manipulating the dependencies as such could be the issue? – Naman Jan 15 '19 at 09:38
  • @nullpointer: Thank you for your feedback. The problem is that the /target/classes folders of open projects won't get included in the _--module-path_ (or _-p_), whereas the the .jar's in .m2 get properly included in _--module-path_. Thus, the dependencies themselves does not get modified but are just missing in _--module-path_. For my it would be logical if Eclipse would also include /target/classes but by default this is obviously not the case. The question for me is if there is an option in Eclipse that I can use to achieve this behaviour? – user27772 Jan 15 '19 at 09:53
  • Can you give a code example (`pom.xml`, `module-info.java` and Java code) to reproduce your issue? What is the benefit of using JPMS in this scenario? – howlger Jan 15 '19 at 09:58
  • @howlger: I added a complete example in my original post: Having the project open I get _Error occurred during initialization of boot layer java.lang.module.FindException: Module mydependency not found, required by example_. After doing _maven install_ and close the project in the workspace the example code runs. Concerning your question about JPMS benefits: For our main project we use jlink, so we had to upgrade to Java 9+ and JPMS and its benefits. – user27772 Jan 15 '19 at 10:43
  • @user27772 I see. Is the goal less disk space or a faster startup? If the latter, have you tried OpenJ9 with `-Xshareclasses`? I'd like to know that even if it is not really related to your question. – howlger Jan 15 '19 at 12:04
  • @howlger: No, the goal is just to get my project running under Java 11. In my opinion the problem is that JPMS relies on analyzing the names of .jar files on the class-path (or respectively use the Automatic-Module-Name property in their MANIFEST.MF if present) to create automatic modules, but, if _Resolving dependencies from workspace_ is activated (as it is by default and very usable while working) no .jar files exist since /target/classes is used directly. Currently I don't see any simple option to work with non-modularized dependency projects in the Eclipse workspace. – user27772 Jan 15 '19 at 13:00
  • @howlger: Thank you anyway for the OpenJ9 link, it's surely worth to investigate but for now it is not relevant for us. – user27772 Jan 15 '19 at 13:04
  • I filed a bug report here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=543768 – user27772 Jan 24 '19 at 08:18
  • This is a very good question concerning a serious problem. I have given up my transition to the module system mostly because of this problem which turns out to be a JPMS design flaw and not so much an IDE/Eclipse problem. – mipa Oct 02 '19 at 09:29

1 Answers1

5

A source project cannot possibly be an automatic module, because the name of an automatic module is derived from the jar filename.

What you need is:

  • mvn install in each dependency
  • Maven > Disable Workspace Resolution on each project that depends on an automatic module (context menu in the Package Explorer)

Edits:

  • Alternatively, instead of disabling workspace resolution, all projects containing automatic modules can be closed.
  • People affected by this may champion Eclipse Bug 543925, where a cooperation between m2e and JDT could go beyond what is specified by JPMS: m2e could tell JDT what would be the automatic module name, if a given project would be accessed from it's jar file. Behind the scenes running that program would then require to ignore the workspace resolution, so that the JVM finds the needed jar file.
Stephan Herrmann
  • 7,963
  • 2
  • 27
  • 38
  • I’d wish that Eclipse could handle these cases automatically since m2e does actually know what the name of the resulting .jar file would be and could build the correct module-path and classpath _without_ the manual steps you described. But for now, I understand that each non-modular workspace project like mydependency (or more specifically, projects that do _not_ contain module-info.java) must be installed into .m2 and closed afterwards when other projects in the workspace depend on it. – user27772 Jan 28 '19 at 15:23
  • 1
    Anyway, you write that _each_ project that depend on an automatic module must have workspace resolution turned off. This seems unacceptable to me: It would effect e. g. _all_ projects that depend only on non-modular artifacts of the external Maven Repository and also _all_ projects that depends on a mix on modular workspace projects _and_ non-modular external artifacts with workspace resolution being enabled. Is this really intended? We use workspace resolution a lot, so coding such projects would be much less fun :( – user27772 Jan 28 '19 at 15:31