Skip to content

Ship an explicit module descriptor in microprofile-jwt-auth-api - #353

Open
antoinesd wants to merge 3 commits into
microprofile:mainfrom
antoinesd:module-info
Open

antoinesd wants to merge 3 commits into
microprofile:mainfrom
antoinesd:module-info

Conversation

@antoinesd

@antoinesd antoinesd commented Sep 3, 2026 •

Copy link
Copy Markdown

Fixes #352

Adds an explicit module-info.java to microprofile-jwt-auth-api so the MicroProfile JWT Auth API can be consumed as a proper Java module instead of an automatic one (context: mailing-list thread, same change proposed for every affected MicroProfile API).

The change is designed to be mergeable in the next minor release without touching the Java 8 baseline: the API classes are still compiled with --release 8, and the only Java 9 element is the module-info.class itself, compiled by a dedicated execution (the approach used by e.g. SLF4J 2.x). Moving to microprofile-parent 3.x / Java 11 is a separate decision for the project; if and when it happens, the special-casing below disappears and the wiring becomes identical to the Health and Metrics PRs.

The descriptor

module org.eclipse.microprofile.jwt {
    requires static transitive jakarta.cdi;
    requires static transitive jakarta.inject;
    requires transitive jakarta.json;

    exports org.eclipse.microprofile.auth;
    exports org.eclipse.microprofile.jwt;
    exports org.eclipse.microprofile.jwt.config;
}

The module name follows the org.eclipse.microprofile.<spec> convention (reverse-DNS of the root package, as already used by the Config API's Automatic-Module-Name and by the OpenAPI API's existing descriptor). jakarta.json is a hard dependency (three Claims enum constants reference JsonObject.class directly) and stays requires transitive. The CDI and Inject modules are only referenced by the @Claim qualifier and its ClaimLiteral; JsonWebToken, Claims and the config package do not depend on them. They are therefore declared requires static transitive:

  • static: optional at resolution time, so the module resolves on a module path without a CDI container. Whenever the annotations are actually used at run time it is through a CDI container, whose own module requires the Jakarta modules and therefore resolves them.
  • transitive: when they are resolved, a module using @Claim reads jakarta.cdi and jakarta.inject implicitly, which is needed for the meta-annotations and the AnnotationLiteral supertypes to be resolvable from that module.

The same trade-off is applied to the other MicroProfile APIs whose Jakarta dependency is annotation-only (see the discussion on microprofile/microprofile-health#344, microprofile/microprofile-metrics#805 and microprofile/microprofile-fault-tolerance#660). The module Javadoc is deliberately kept to a one-liner; this rationale lives here instead.

Build changes (api/pom.xml)

  • The descriptor lives in src/main/module-info/ and is compiled by a dedicated maven-compiler-plugin execution patched onto the already compiled classes (--patch-module). The main compilation is left untouched on the class path, and the descriptor does not have to requires the OSGi/bnd annotation jars used by package-info.java, which are compile-time only and ship no module descriptor of their own.
  • The descriptor source root is registered with build-helper-maven-plugin at prepare-package (after compilation) so that the attached *-sources.jar ships module-info.java alongside the other sources.
  • maven-javadoc-plugin is kept in class path mode (legacyMode) with an explicit sourcepath limited to src/main/java: javadoc would otherwise switch to module mode as soon as it finds a module-info.java at the root of a source path.
  • The project baseline is Java 8 (microprofile-parent 2.x), so the dedicated execution uses --release 9 — the only Java 9 exception in the build, so that this can land in the next minor release without waiting for a Java baseline bump. Should the project move to microprofile-parent 3.x (Java 11), this special case simply goes away. The resulting module-info.class (class file version 53) sits at the jar root next to Java 8 classes — the same layout used by e.g. SLF4J 2.x; a Java 8 runtime never loads module-info and OSGi/bnd ignore it. Packaging it as META-INF/versions/9/ (multi-release) is possible too if the project prefers.

Verification

  • mvn install -DskipTests on the whole reactor passes.
  • jar --describe-module on the built jar shows the descriptor above; OSGi headers (Bundle-SymbolicName, Export-Package, Import-Package) generated by bnd are unchanged.
  • java --module-path <api jar + compile deps> --describe-module org.eclipse.microprofile.jwt resolves the module graph successfully (with only jakarta.json next to the api jar it resolves as well, the CDI/Inject modules being optional).
  • The *-sources.jar contains module-info.java; the *-javadoc.jar is unchanged.

Adds module-info.java declaring the org.eclipse.microprofile.jwt module so the
MicroProfile JWT Auth API can be used as an explicit module on the
module path (stable name, real encapsulation, jlink/AOT compatibility)
instead of an automatic module.

The descriptor is compiled in a dedicated maven-compiler-plugin
execution patched onto the already compiled classes, which keeps the
main compilation unchanged (class path) and avoids requiring the
OSGi/bnd annotation jars used by package-info.java, which ship no module
descriptor of their own. The javadoc plugin is kept in class path mode
(legacyMode) since the descriptor lives outside its source roots.

Fixes microprofile#352

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Antoine Sabot-Durand <antoine@sabot-durand.net>
Copilot AI lite review requested due to automatic review settings September 3, 2026 21:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The module-info compilation execution should be moved to a later Maven phase to avoid relying on compile-phase execution ordering with --patch-module.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds an explicit Java module descriptor for the MicroProfile JWT Auth API and wires the build to compile and package module-info.class while keeping the main API sources on the Java 8 classpath baseline.

Changes:

  • Introduces module org.eclipse.microprofile.jwt descriptor exporting the API packages and declaring Jakarta module dependencies.
  • Updates api/pom.xml to compile module-info.java in a dedicated maven-compiler-plugin execution using --patch-module.
  • Forces Javadoc generation to remain on the classpath (legacyMode) since the descriptor is outside the normal source roots.
File summaries
File Description
api/src/main/module-info/module-info.java Adds explicit JPMS module descriptor for the API jar (name, requires, exports).
api/pom.xml Adds a dedicated compiler execution to build/patch module-info.class and configures Javadoc to stay in legacy (classpath) mode.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread api/pom.xml Outdated
Comment thread api/src/main/module-info/module-info.java Outdated
Comment thread api/src/main/module-info/module-info.java Outdated
Address review feedback: make the ordering with the default compile
explicit by binding the module-info execution to process-classes, and
only mention Claims as the type exposing jakarta.json (JsonWebToken
does not reference it).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Antoine Sabot-Durand <antoine@sabot-durand.net>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The module descriptor/build wiring introduces potentially breaking module-resolution/runtime requirements (and build JDK constraints) that should be clarified/adjusted before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

api/src/main/module-info/module-info.java:32

  • Using non-static requires transitive for CDI and Inject forces jakarta.cdi / jakarta.inject to be present at runtime whenever this module is resolved. Since these are only referenced via annotations / ClaimLiteral and Issue #352 proposed requires static, consider switching these to requires static transitive (keeping jakarta.json non-static) and update the Javadoc accordingly.
 * {@code AnnotationLiteral}, so the JSON-P, CDI and Inject modules are required transitively.
 */
module org.eclipse.microprofile.jwt {
    requires transitive jakarta.cdi;
    requires transitive jakarta.inject;
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread api/pom.xml
…java in the sources jar

The API only depends on jakarta.cdi and jakarta.inject through the
@claim qualifier and its ClaimLiteral, so both modules are now optional
at resolution time and re-exported when present. jakarta.json remains a
mandatory transitive dependency since the Claims enum references
JsonObject and friends directly.

The module descriptor source root is registered at prepare-package so
that the sources jar carries module-info.java without exposing it to
the default compilation, and javadoc is pinned to the regular source
directory so it stays in class path mode. The module Javadoc is reduced
to a one-liner; the rationale lives in the pull request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Antoine Sabot-Durand <antoine@sabot-durand.net>
@antoinesd

Copy link
Copy Markdown
Author

Pushed d8e51d0: jakarta.cdi / jakarta.inject are now requires static transitive (they are only referenced by @Claim and ClaimLiteral, same reasoning as microprofile/microprofile-health#344, microprofile/microprofile-metrics#805 and microprofile/microprofile-fault-tolerance#660); jakarta.json stays a plain requires transitive since Claims and JsonWebToken reference JSON-P types directly. The *-sources.jar now ships module-info.java, and the module Javadoc is reduced to a one-liner. PR description updated accordingly.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The descriptor and build configuration consistently implement the stated modularization approach without unresolved issues.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@radcortez

Copy link
Copy Markdown
Contributor

@sberyozkin seems ok to me. Do you want to confirm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ship an explicit module-info.java in microprofile-jwt-auth-api

3 participants