问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/46939741/java-9-automatic-module-dependencies-cannot-be-resolved-module-not-found