Forum Discussion

julienQc's avatar
julienQc
Occasional Contributor
6 years ago
Solved

No OpenAPI visible endpoint for endpoint declared in interface with default implementation

I'm writing a generic system de create REST endpoints.
I'm using Jersey + Spring in my project but my problem is only related to OpenAPI .
I use Swagger 2 (OpenAPI 3.0)

I'm declaring all my endpoints and their documentation in interfaces, with a default implementation. So in my class I don't have to declare the methods which already have a default implementation.

Here is a sample of my code :

public interface SampleEndpoints {


@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 create(Object param ) {
return "ok";
}

@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")})
String find(String id);

}


The controller class

@Component
@Path("/cars")
public class CarsController implements SampleEndpoints {

public String find(String id) {
return "Yes I've found it";
}

}


As you can see I don't have to implement the create method because its default implementation is sufficient.


My problem is that the create method doesn't appear in the generated openapi.json (but the find method is there, with all the informations)

If instead of an interface I declare SampleEndpoints as a class, and make my CarsController inherit of SampleEndpoints, then the open Api documentation works.

So I'd like to know if there is a way to make it works with interface ?

I can't manage to find a solution, but using interface instead of inheritance is mandatory because my controller needs to implements multiple interfaces.

 

Thanks for all your ideas :)

 

 

4 Replies

  • I am not able to reproduce the issue with the example provided, both find and create get correctly resolved; which swagger artifact and version are you using, and how is that configured? and whatever signficant detail.

    • julienQc's avatar
      julienQc
      Occasional Contributor

      Hi,

       

      Thanks for your answer.

      I've written a sample project to show the problem.

      Here is the repository.

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

       

      The creation of this test allows me to understand exactly where is the problem, it's a little more tricky than I thought.

       

      First of all, you're absolutely right : there is no problem with default method in interfaces.

       

      My problem is a mix between default method in interface and inheritance.

      First interface :

       

       

      public interface OriginalEndpoint<C> {
      
          String originalEndpoint(C c);
      }

      Second interface :

       

       

       

      public interface SecondEndpoint<C> extends OriginalEndpoint<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";
          }
      
          @Override
          @GET
          @Path("/original/{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 originalEndpoint(C param) {
              return "originalEndpoint-ok";
          }
      
      
      }

       

       

       

      In the swagger generated :

       

      • secondEnpoint ( Get on «/{id}) is present
      • originalEndpoint ( Get on  «/original/{id}») is not present

      The reason I used this inheritance in interfaces is because I have multiple default implementations for same «base» interfaces. One default implementation for Jersey, and another one for Spring MVC