eclipse / microprofile-open-api

Microprofile open api
Apache License 2.0
131 stars 82 forks source link

Micro profile Open API @Parameter annotations cannot currently be used at a class level #479

Closed dawuzi closed 2 years ago

dawuzi commented 3 years ago

The org.eclipse.microprofile.openapi.annotations.parameters.Parameter annotation is currently qualified with a @Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD }). So it cannot be used at a class level

This becomes very unpleasant when there are numerous parameters that is repeated across multiple @Path methods of a resource class

Can the annotation's @Target be modified to include ElementType.TYPE. This is so it can be used on a class level and hence applicable to all the REST endpoints in the resource class

MikeEdgar commented 3 years ago

Hi @dawuzi - have you tried using field injection for the redundant parameter(s)? For example, if you have a filter parameter that applies to every endpoint, you could use a field in your resource class:

@QueryParam("filter")
@Parameter(name = "filter", in = ParameterIn.QUERY, description = "Used to filter the results")
private String filter;

Then you can use that param from any of the resource methods via this.filter.

dawuzi commented 3 years ago

Hi @MikeEdgar , this is for query params. My current use case is for headers.

Hi @dawuzi - have you tried using field injection for the redundant parameter(s)? For example, if you have a filter parameter that applies to every endpoint, you could use a field in your resource class:

@QueryParam("filter")
@Parameter(name = "filter", in = ParameterIn.QUERY, description = "Used to filter the results")
private String filter;

Then you can use that param from any of the resource methods via this.filter.

MikeEdgar commented 3 years ago

My current use case is for headers.

@dawuzi - that would be supported using @HeaderParam instead of @QueryParam and then using ParameterIn.HEADER in the @Parameter annotation.

dawuzi commented 3 years ago

Hi @MikeEdgar ,

Exactly my point. With the way it is now I would have to replicate something like the following for every method

dawuzi commented 3 years ago

Imagine having to repeat the following for every method. It would have been more convenient putting this on the class and have it applied for every path method since I want them for all of them. Do you understand my point now ?

@Parameter(in = ParameterIn.HEADER, name = BaseConstant.BASE_TIMEZONE_HEADER_KEY, schema = @Schema(type = SchemaType.STRING))

MikeEdgar commented 3 years ago

@dawuzi - the solution I'm suggesting would look like the class below. The header is injected as a field in the resource class and can be used by any of the methods.

@Path("/my-resource")
public class MyResource {

    @HeaderParam("X-My-Header")
    @Parameter(name = "X-My-Header", in = ParameterIn.HEADER, description = "Say something about the header")
    private String myHeader;

    @GET
    public Response get() {
         // ... do something with this.myHeader and return the response
    }

    @PUT
    public Response update(String input) {
         // ... do something with this.myHeader and return the response
    }

}
dawuzi commented 3 years ago

@MikeEdgar So what happens if you want that same "X-My-Header" key in the swagger doc for the get and update end points. You would have to add them again to them right ?

MikeEdgar commented 3 years ago

@dawuzi, the MicroProfile OpenAPI annotation scanner implementation you are using should make that header apply to both of the REST endpoints. Are you seeing different behaviour?

MikeEdgar commented 3 years ago

@dawuzi - were you able to get this working using a field in your resource class?

MikeEdgar commented 2 years ago

Closing due to inactivity. Please re-open if this is still an issue for you.