Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an annotation to declare what JAX-RS resources are associated with a given Application #520

Open
tjquinno opened this issue Mar 21, 2022 · 2 comments

Comments

@tjquinno
Copy link

Developers can extend the JAX-RS Application class, for example to specify an app path for all resources within that app.

Such subclasses can also override getClasses and getSingletons.

The JAX-RS spec https://jakarta.ee/specifications/restful-ws/3.0/jakarta-restful-ws-spec-3.0.html#servlet describes how servlet implementations must handle this:

if both Application.getClasses and Application.getSingletons return an empty collection then all root resource classes and providers packaged in the web application MUST be included

It continues (importantly):

If either getClasses or getSingletons returns a non-empty collection then only those classes or singletons returned MUST be included in the published JAX-RS application.

Of course, MicroProfile neither refers to nor implements servlets, but it is very reasonable for our users to expect MP-compliant servers to honor the JAX-RS semantics described there. Two server implementations I checked (OpenLiberty and Helidon) do so and I suspect so do others.

There is no way for the developer to declare, at build-time, this same information using annotations so that the OpenAPI document derived from annotations agrees with the runtime behavior of the application. It would be possible for MP OpenAPI implementations to instantiate the Applications and invoke their getClasses and getSingletons methods simply to derive the correct OpenAPI document, but this could force such instantiation earlier than might otherwise be necessary and might create undesired side-effects in some implementations.

This issue proposes adding a new annotation to MicroProfile OpenAPI to allow (but not force) developers to declare which resources belong to which Applications.

Possibilities:

  1. Add the @APIApplication annotation which applies to subclasses of Application:
    @APIApplication(resources = {PetResource.class, PetStoreResource.class})
    public class PetStoreApp extends Application {
        ...
        public Set<Class> getClasses() {
            return Set.of(PetResource.class, PetStoreResource.class);
        }
        ...
  }
  1. Add the @APIResource annotation which applies to subclasses of Application:
    @APIResource(PetResource.class)
    @APIResource(PetStoreResource.class)
    public class PetStoreApp extends Application {
        ...
        public Set<Class> getClasses() {
            return Set.of(PetResource.class, PetStoreResource.class);
        }
        ...
  }
  1. Add the @APIResource annotation which applies to JAX-RS resource classes:
    @APIResource(applications = {PetStoreApp.class})
    public class PetResource {...}

An advantage of the @APIApplication annotation is its consistency with other MP OpenAPI annotations which are typically named for the entity they describe (e.g., @APIResponse) with settings pertinent to that entity's OpenAPI behavior. This annotation would also be a convenient place to put any future OpenAPI-related attributes on Applications for which we might see a need.

An advantage of @APIApplication and @APIResource when applied to the Application subclass is that the declaration of the resources and the runtime manifestation (getClasses and/or getSingletons) are syntactically close to each other and so more likely to be kept in sync.

Disadvantages of any such new annotation:

  1. The list of resources declared in the annotation can become inconsistent with the implementation of getClasses and getSingletons, meaning that the declared OpenAPI information and the runtime behavior are different.

To help mitigate that, when otherwise invoking Applications' getClasses and getSingletons methods during the normal course of runtime processing, the MicroProfile implementation could check that the classes and instances returned match the declared resources for that application, issuing a warning if they do not.

(For some background, see #498)

@josoder
Copy link

josoder commented Nov 16, 2023

Any progress with this issue?
Does anyone know of a workaround for this limitation?

We are currently unable to use mp openapi since our deployed WAR contains multiple jax-rs applications. The generated docs are faulty, only one, seemingly arbitrarily choosen, application path is prepended to all paths.

@Azquelt
Copy link
Member

Azquelt commented Nov 27, 2023

Maybe it would also be a good idea to also allow this to be set via configuration?

On the call this week we thought of:

mp.openapi.resources.com.example.myApplication=com.example.myResourceA,com.example.myResourceB
mp.openapi.resources.com.example.myApplication2=com.example.myResourceA,com.example.myResourceC

Or possibly:

mp.openapi.resources=com.example.myApplication=com.example.myResourceA;com.example.myApplication2=com.example.myResourceA,com.example.myResourceB

I'm not really a fan of having to do this - it would be preferable for the implementation to get the list of applications and their root resources from JAX-RS if possible - but if we want to allow implementations to pre-compute this, or to build an OpenAPI document at build time, then I think we do need some way of specifying this information.

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

No branches or pull requests

3 participants