-
Notifications
You must be signed in to change notification settings - Fork 0
Explicit module path
This page describes the first work item for better support of Java Module Platform System (JPMS) with Maven.
In Maven 3, an artifacts of type jar could be placed on the class-path or on the module-path,
depending on an heuristic rule on which users have no control.
It was a problem because the behavior of a library can be sensitive to the kind of path where it is placed.
In particular, all methods based on reflection behave differently:
service loaders do not load services in the same way, which can potentially causes failure to load services
(problem demonstrated by a test case);
classes loading after application startup, e.g., for adding plugins, are done in a completely different way
(using ClassLoader versus ModuleLayer), etc.
For resolving those problems, developers need more control about which path to place dependency on.
To achieve this goal, the following types are proposed for Maven 4:
jar, test-jar, classpath-jar, modular-jar and more
(the two first types already exist in Maven 3).
Each sub-section below describes one artifact type.
JAR file that can be placed either on the class-path or on the module-path. The path (classes or modules) is chosen by Maven or by the plugin, possibly using heuristic rules. The heuristic rule inherited from Maven 3 is to use the module-path if and only if:
- the dependency is modular,
- and the project using the dependency is modular.
For deciding if a dependency is modular (i.e., for responding to the first condition), the algorithm examines the path to the dependency as below (note: package hierarchy, module hierarchy, and module source hierarchy are terms defined in Oracle's documentation):
- If the path is an output directory, then there is a choice:
-
Package hierarchy: If a
module-info.classfile is found at the root, the dependency is modular. -
Module hierarchy: Otherwise, if
module-info.classfiles are found in sub-directories at a deep intentionally restricted to one level, then the dependency is modular. - There is no check for Module Source Hierarchy because the dependencies are assumed to be compiled code, not source.
-
Package hierarchy: If a
- Otherwise, if the given path is a JAR file, then there is a choice:
- If a
module-info.classfile is found in the root directory or in aMETA-INF/versions/{n}subdirectory, the dependency is modular. - Otherwise, if an
Automatic-Module-Nameattribute is declared in theMETA-INF/MANIFEST.MFfile, the dependency is modular.
- If a
- Otherwise, the dependency is considered non-modular.
JAR file to unconditionally place on the class-path. If the JAR is modular, then its module information is ignored. This type is new in Maven 4.
JAR file to unconditionally place on the module-path. If the JAR is not modular, then it is loaded by Java as an unnamed module. This type is new in Maven 4.
JAR file containing test classes. If the main artifact is placed on the class-path
(jar or classpath-jar types), then the test artifact will also be placed on the class-path.
Otherwise, if the main artifact is placed on the module-path (jar or modular-jar types),
then the test artifact will be added using --patch-module option.
The rules are more complex for the output test directory. In that case, the algorithm is as below. Those rules may seem arbitrary, but actually most of them are mandated by the compiler. For example, it is not legal to place two modules of the same name in the module-path: one of them must be patching the other.
- If module hierarchy is detected in either the main output or the test output, then:
- For each module found in both outputs, place the path to the test classes
of that specific module in a
--patch-module <module>=<path>option. - For each module that exists in the test output but not in the main output, place the path to the test classes of that specific module on the module-path.
- For each module found in both outputs, place the path to the test classes
of that specific module in a
- Otherwise, if the main output is modular, unconditionally place the path
to the test classes in a single
--patch-module <module>=<path>option. - Otherwise (no module), place the path to the test classes on the class-path.
JAR file to place on Javac --processor-path option.
JAR file to place on Javadoc -docletpath option.
Not yet implemented in current prototype.
JAR file to place on Javadoc -tagletpath option.
Not yet implemented in current prototype.
To support above types, new classes and methods are added. An idea to keep in mind is that the class-path, module-path and patch-module options need to be computed together, so having separated methods for computing them separately is not practical.
-
PathType: an enumeration-like class for identifying where a dependency can be placed: class-path, module-path, doclet-path, etc. A dependency may declare more than one type of path. For example, a library may declare that the JAR file can work on both the class-path and the module-path. - New
getDispatchedPaths()method inDependencyResolverResultreturning a map of paths for each path type. - New method in
DependencyResolverRequestfor specifying the types of path of interest. For example, the compiler plugin may declare that it is interested in the class-path and module-path, but not in doclet and taglet paths. This information can resolve ambiguities when a dependency declares that it can be placed on many types of path.
- JIRA task: https://issues.apache.org/jira/browse/MNG-8015
- GitHub PR: https://github.com/apache/maven/pull/1378