-
Notifications
You must be signed in to change notification settings - Fork 82
Description
when investigating #768 my genie came to a conclusion and I figured to rather create a new top lvl issue for this, just for the java modules topic.
Also create a reproducer example at https://github.com/approvals/ApprovalTests.java.StarterProject/tree/reproduce-jpms-issue-770
Summary
When a consumer project uses Java Platform Module System (JPMS) via module-info.java, compilation fails because the module system eagerly resolves all types referenced by all classes in the approvaltests jar — including types from optional dependencies that are not on the module path.
This is broader than #768 (which reports the gson-specific symptom). Every optional dependency that is referenced in a class signature causes problems for JPMS consumers.
Reproduction
Add a module-info.java to a consumer project that depends on approvaltests (without explicitly adding gson):
module myproject {
exports org.samples;
}Compile → fails with:
package com.google.gson does not exist
cannot find symbol: class GsonBuilder
location: class org.approvaltests.JsonApprovals
package java.sql is not visible
(package java.sql is declared in module java.sql, which is not in the module graph)
reference to verify is ambiguous
both method verify(java.lang.Object) and method verify(ResultSet) match
Root Cause
In 2018 (commit 2e3bbfd), all dependencies were marked <optional>true</optional>. This works fine for classpath-based consumers (types are lazily resolved), but JPMS forces full upfront resolution of every type in the module graph.
Affected optional dependencies include at least:
- gson →
JsonApprovals,JsonUtilsexposeGsonBuilderin public API - java.sql →
Approvals.verify(ResultSet)causes ambiguous overloads whenjava.sqlmodule is not in the graph - Likely also: xstream, jackson, velocity, commons-net, quartz, servlet-api, xom
Real-World Impact
This affects chicory (a JPMS project) and likely any other modular Java project.
Chicory already has workarounds in their build: --add-modules java.sql, --add-modules java.desktop, and a Java 11 profile that disables the module path entirely.
Options to Discuss
- Remove
<optional>from core deps (gson, java.sql-related) — simplest but adds transitive deps for all consumers - Separate modules (e.g.
approvaltests-gson,approvaltests-jdbc) — clean but breaking change - Hide optional types from public API — remove
GsonBuilder/ResultSetetc. from method signatures, use reflection internally - Add
module-info.javato approvaltests withrequires staticfor optional deps — proper JPMS support but requires moving off Java 8 source level - Combination — e.g. move optional-dep classes to sub-modules + add module-info
Needs discussion with maintainers before picking an approach.
Related
- Missing gson transitive dependency #768 (gson-specific report from chicory)