Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 9 automatic module dependencies cannot be resolved / module not found

I'm trying to migrate some legacy applications to the new Java 9 module system, to strengthen its encapsulation.

I'm starting from the outside-in, with the assumption that classes on the periphery will have the least external dependencies.

As you'd expect, I've declared a very open module to start with:

module com.example.user {   
    exports com.example.user;
}

This instantly breaks the entire project (inside all classes), when suddenly every import for an external dependency no longer resolves (causing over 1k Java problems):

The import com.otherexample cannot be resolved

The import org.springframework cannot be resolved

etc.

Local packages in the same project com.example.price still work - as do java.util etc.

All of the external dependencies are (were) managed with Maven. In the (Eclipse project) build path, I can still see them as "Classpath" dependencies - but only the JRE system libraries in the "Modulepath".

Can the two concepts co-exist? Currently it seems by having a single module-info.java anywhere in the project, all classpath dependencies stop working?

I did read about using automatic modules, which seemed to imply you could use legacy / non-modular jars by including them in your modulepath, then referring to them by their filename. They use the example:

module com.foo.myapp {
  requires guava;  // guava not yet modularised, so use the filename
}

I couldn't find much other info, but this appears to match the convention Eclipse uses when it auto-generates a module-info.java for example:

spring-core-4.3.8.RELEASE.jar

becomes:

requires spring.core;

However, this still results in a Java error reported by Eclipse:

spring.core cannot be resolved to a module

Maven reports:

[ERROR] module-info.java:[39,16] error: module not found: spring.core

...and every class in the project with an external dependency is still broken.

like image 299
Michael Avatar asked Oct 25 '17 18:10

Michael


1 Answers

Thanks to Robert Scholte for pointing out the updated maven-compiler-plugin 3.7.0 (I had been using 3.6.1), this really cleaned up the compile goal command-line output (with Java 9 specifics), to help me get to the route of the problem. This narrowed down the reported errors from every requires giving me the error to:

[WARNING] ********************************************************************************************************************
[WARNING] * Required filename-based automodules detected. Please don't publish this project to a public artifact repository! *
[WARNING] ********************************************************************************************************************
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 56 source files to ./target/classes
~~~ snip ~~~
[ERROR] module-info.java error: module not found: foo.bar

Matching Eclipse:

foo.bar cannot be resolved to a module

The errors appearing for just six automatic modules / libraries (jar) - rather than all (24) of them. Great.

In my POM, I'd split the output of source directories, to their own output directories (target/classes). However, as the module-info.java referred to dependencies (such as requires spring.core;) that are not used / referenced by the code (classes) in that folder - it couldn't resolve them.

Why? Basic Maven dependency management - I'd scoped those libraries outside of the default goal (to match the output directories split).

A fairly basic outcome - but I'd imagine I will not be the only person to encounter this as Java begins to encroach on some aspects of dependency management that overlap with the traditional use of Maven.

like image 118
Michael Avatar answered Sep 28 '22 07:09

Michael