Forum Discussion

julienQc's avatar
julienQc
Occasional Contributor
6 years ago

@ApiResponse messages inheritance

Hi,

 

I'm facing a problem that I don't know if it's an issue or a normal behaviour of swagger.

And if it's a normal behaviour, maybe it could be improved

 

I'm defining interfaces and swagger documentation on the interfaces' methods like this :

 

public interface FirstEndpoint<C> {

    @POST
    @Path("/")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "Created"),
            @ApiResponse(responseCode = "400", description = "Bad Request"),
            @ApiResponse(responseCode = "403", description = "Forbidden"),
            @ApiResponse(responseCode = "404", description = "Not Found")})
    default String firstEndpoint(C param) {
        return "firstEndpoint-ok";
    }
}

And

 

public interface SecondEndpoint<C> {

    @GET
    @Path("/{id}")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "OK"),
            @ApiResponse(responseCode = "400", description = "Bad Request"),
            @ApiResponse(responseCode = "403", description = "Forbidden"),
            @ApiResponse(responseCode = "404", description = "Not Found")})
    default String secondEnpoint(C param) {
        return "secondEnpoint-ok";
    }



}

Then in some cases I may want to change the description so in the class of my controller which implements these interfaces I do this :

 

@Path("/testresponse")
@Tag(name = "Test response messages")
public class TestApiResponseResource
    implements FirstEndpoint<SampleDTO>,
        SecondEndpoint<SampleOtherDTO> {
    @Override
    public String firstEndpoint(SampleDTO param) {
        return "firstEndpoint Implemented !";
    }

    @Override
    @ApiResponse(responseCode = "404", description = "I said : not Found")
    public String secondEnpoint(SampleOtherDTO param) {
        return "secondEnpoint Implemented !";
    }
}

As you can see :

 

  • for «firstEndpoint» I don't override any @ApiResponse
  • for «secondEndpoint» I've override only one @ApiResponse for 404 response

 

Full source code available here :

https://github.com/githubjul/test-swagger-with-interfaces

 

The expected behaviour would be for :

  • for «firstEndpoint», get all messages declared in interface

       => Ok, I get them !

 

  • for «secondEnpoint», get all messages declared in interface, except for 404, I want to have my custom message

=> Ko, in only get my 404 message, I've lost all messages declared in interface

 

Si is this a bug ?
If it's not, how can I simply overrid only one @ApiResponse message ?

 

The expected behaviour I want would be :

 

  • override only specific messages : use @ApiResponse
  • replace all messages : use @ApiResponses

 

Thanks for your help,

 

Julien

  • this is not supported atm as the container annotation ApiRepsonses is overriden in full, and there are no short term plans to change this behaviour; however you can possibly achieve what you need, more as a side effect, by including your ApiResponse annotations of "base interface" (first and second enpoint) within `@Operation` annotation, and keeping controller as is; as responses within Operation are resolved first, and responses defined on method are then merged with these, this match your desired behaviour.

     

    e.g.

     

    public interface FirstEndpoint<C> {
    
        @POST
        @Path("/")
        @Operation(responses = {
                @ApiResponse(responseCode = "201", description = "Created"),
                @ApiResponse(responseCode = "400", description = "Bad Request"),
                @ApiResponse(responseCode = "403", description = "Forbidden"),
                @ApiResponse(responseCode = "404", description = "Not Found")})
        default String firstEndpoint(C param) {
            return "firstEndpoint-ok";
        }
    }
    public interface SecondEndpoint<C> {
    
        @GET
        @Path("/{id}")
        @Operation(responses = {
                @ApiResponse(responseCode = "200", description = "OK"),
                @ApiResponse(responseCode = "400", description = "Bad Request"),
                @ApiResponse(responseCode = "403", description = "Forbidden"),
                @ApiResponse(responseCode = "404", description = "Not Found")})
        default String secondEnpoint(C param) {
            return "secondEnpoint-ok";
        }
    
    
    
    
  • this is not supported atm as the container annotation ApiRepsonses is overriden in full, and there are no short term plans to change this behaviour; however you can possibly achieve what you need, more as a side effect, by including your ApiResponse annotations of "base interface" (first and second enpoint) within `@Operation` annotation, and keeping controller as is; as responses within Operation are resolved first, and responses defined on method are then merged with these, this match your desired behaviour.

     

    e.g.

     

    public interface FirstEndpoint<C> {
    
        @POST
        @Path("/")
        @Operation(responses = {
                @ApiResponse(responseCode = "201", description = "Created"),
                @ApiResponse(responseCode = "400", description = "Bad Request"),
                @ApiResponse(responseCode = "403", description = "Forbidden"),
                @ApiResponse(responseCode = "404", description = "Not Found")})
        default String firstEndpoint(C param) {
            return "firstEndpoint-ok";
        }
    }
    public interface SecondEndpoint<C> {
    
        @GET
        @Path("/{id}")
        @Operation(responses = {
                @ApiResponse(responseCode = "200", description = "OK"),
                @ApiResponse(responseCode = "400", description = "Bad Request"),
                @ApiResponse(responseCode = "403", description = "Forbidden"),
                @ApiResponse(responseCode = "404", description = "Not Found")})
        default String secondEnpoint(C param) {
            return "secondEnpoint-ok";
        }
    
    
    
    
    • julienQc's avatar
      julienQc
      Occasional Contributor

      Awesome, it works !

       

      Hope this side effect will stay as is forever :)