Skip to content

Feature Request: Ignore JAX-RS interface types annotated with @Path during resource discovery #26113

Description

@OndroMih

Feature Request: Ignore JAX-RS Interface Types Annotated with @path During Resource Discovery

Summary

When Jersey server scans application classes, interfaces annotated with @Path should not be treated as deployable JAX-RS resource classes.

This can currently lead to two problems observed in Payara:

Why This Should Be Added to GlassFish

MicroProfile Rest Client APIs commonly use interfaces and may include JAX-RS annotations such as @Path on the interface type. Server-side resource scanning must ignore such interfaces unless they are explicitly backed by concrete resource classes.

Without this filtering, applications can fail at runtime in subtle ways, including endpoint shadowing and false-positive deployment warnings.

Current Status in GlassFish (2026-06-18)

Not implemented in GlassFish source.

Verification notes:

  • MP Rest Client support exists and is wired via jersey-mp-rest-client.
  • MP Rest Client TCK runner already exists in appserver/tests/tck/microprofile/rest-client.
  • No GlassFish-specific Jersey integration code was found that filters out interface types annotated with @Path during application resource discovery.

Proposed Behavior

  • During JAX-RS resource model construction, skip interface types as root resources.
  • Preserve existing behavior for concrete classes (including CDI-managed resources).
  • Ensure no warning is logged for interface-only @Path declarations used by client-side APIs.

Acceptance Criteria

  • An interface annotated with @Path no longer produces resource-instantiation warnings.
  • If a concrete class exists with the same path, it remains reachable and is not shadowed by the interface.
  • Existing JAX-RS and MP Rest Client TCK coverage continues to pass.
  • Add regression tests for:
    • Interface @Path + concrete class with same path
    • Interface @Path without concrete class

Candidate Implementation Areas

  • Jersey integration point used by GlassFish for application resource bootstrapping.
  • If no suitable hook exists in GlassFish layer, coordinate with Jersey extension/model processing hook or dependency update strategy.

GlassFish Integration Details

Where app resource bootstrapping happens today

  • Servlet container startup triggers SCI execution in appserver/web/web-core/src/main/java/org/apache/catalina/core/StandardContext.java (callServletContainerInitializers).
  • SCI discovery and class matching happen in appserver/web/war-util/src/main/java/org/glassfish/web/loader/ServletContainerInitializerUtil.java:
    • getServletContainerInitializers(...)
    • getInterestList(...)
    • getInitializerList(...)
    • checkAgainstInterestList(...)
  • The Jersey SCI receives classes matched by @HandlesTypes and builds resource classes from those sets.
    • In Jersey 4.0.2, JerseyServletContainerInitializer is annotated with @HandlesTypes({Path, Provider, Application, ApplicationPath}).
    • Its root-class collection includes all classes annotated with @Path/@Provider, without excluding interfaces.

Why the issue can happen in GlassFish

  • MP Rest Client interfaces commonly carry @Path and @RegisterRestClient.
  • SCI class matching can include these interfaces in the candidate class set.
  • Jersey then attempts to process them as server-side resource candidates, causing warning logs and potential path collisions with real endpoint classes.

Proposed Hook Design for GlassFish

Option A (recommended): Generic SCI blacklist/transform hook in war-util

  1. Add an SPI contract in war-util, similar to:
    • ServletContainerInitializerFilter (name can vary)
    • method input/output: Map<Class<? extends ServletContainerInitializer>, Set<Class<?>>>
  2. In ServletContainerInitializerUtil#getInitializerList(...), invoke the SPI via ServiceLoader after interest matching and before returning the initializer map.
  3. Provide MP Rest Client-specific implementation in an MP module (to avoid hard dependency from core web code to MP APIs):
    • filter out classes annotated with @RegisterRestClient
    • optionally also filter pure interfaces annotated with @Path
  4. Register implementation in META-INF/services/....

Benefits:

  • Keeps web core generic.
  • Avoids adding MP API dependency to war-util.
  • Reusable for future SCI filtering needs.

Option B: Direct filter in ServletContainerInitializerUtil

  • Add an inline filter for interface types and/or @RegisterRestClient directly in war-util.

Trade-off:

  • Simpler change set, but introduces tighter coupling and may require reflection or direct MP API dependency.

Option C: Jersey-level model filtering

  • Add a Jersey model processor/customization that drops interface @Path classes before resource model finalization.

Trade-off:

  • Works, but is later in pipeline and less aligned with existing GlassFish SCI-driven bootstrapping path.

Payara-Inspired Adaptation

Payara PR #5518 implemented a pattern worth reusing:

  • Added generic blacklist SPI in web layer.
  • Added MP Rest Client module implementation that removes @RegisterRestClient interfaces from SCI class sets.
  • Added integration tests with real resource + MP Rest Client interface sharing path.

GlassFish can adapt this with minimal conceptual change:

  • Introduce a neutral hook in war-util.
  • Implement MP-specific filtering in a separate MP module already present in GlassFish layout.
  • Add regression tests under appserver/tests to validate:
    • no warning for MP interface-only @Path
    • endpoint remains reachable when interface/resource paths overlap.

Suggested Implementation Sequence

  1. Add hook interface + ServiceLoader call in war-util.
  2. Add MP Rest Client filter implementation module/class.
  3. Register service provider.
  4. Add regression test app containing:
    • concrete JAX-RS endpoint class
    • @RegisterRestClient interface with overlapping @Path
  5. Verify with existing MP Rest Client TCK and web tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions