Search code examples
spring-bootswaggeropenapispringdocspringdoc-openapi-ui

OpenAPI & spring-doc not finding all mappings in a controller class


This is a bit weird. springdoc-openapi-ui v1.2.32, the generated docs contain only a few of the mappings within a controller.

Example:

    @Operation(
            summary = "Foo",
            description = "Foo"
    )
    @PostMapping(path="/v1/foo")
    public ResponseEntity<ResponseObject> postFoo(@RequestBody FooRequestObject searchRequest, HttpServletRequest request){ ... }


    @Operation(
            summary = "Bar",
            description = "Bar"
    )
    @GetMapping(path="/v1")
    public ResponseEntity<ResponseObject> getBar(@RequestBody BarRequestObject request, HttpServletRequest request){ ... }


    @Operation(
            summary = "Bar",
            description = "Bar"
    )
    @PostMapping(path="/v1")
    public ResponseEntity<ResponseObject> postBar(@RequestBody BarRequestObject request, HttpServletRequest request){ ... }

Docs are generated only for postBar and getBar services, the other path is ignored.

What I've tried:

  1. Originally both POST methods were named post. I renamed to avoid conflict.
  2. I am not setting a controller level path.
  3. Checked annotation imports
  4. Not hitting a cached version of the doc

If I add another service to the controller (with or without the annotation tag), it also does not show in the generated Swagger. For example:

@GetMapping(path="/test")
public String getTest(){
    return "test";
}

If I add this method to a brand new controller, doc is generated.

Thanks

Edit Config class

@Configuration
public class SwaggerConfig {                                    

    @Bean
    public OpenAPI springOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("My API")
                .description("My API service documentation. ")
                .version("v1.0")
                .license(new License().name("Terms of Use").url("https://myapi.com/terms.html")));
    }
    
}

Solution

  • The issue you are facing is caused by the fact that you have used level-1 references for paths-to-match and that's causing Springdoc to filter the endpoints that are available only on the specified paths.

    springdoc.paths-to-match=/api/v1,/v2,/v3,/status
    

    The above property makes a match for endpoints that start and end with /v2, /v3, /status, /api/v1. This fails to match for endpoints that maybe of the form like /users/v2/ or even /v2/users etc.

    Though there's no support for full regex to specify the endpoints you would like to include, but there's basic support for ** that can help you specify the levels that you would like to include/exclude.

    Consider the below examples

    springdoc.paths-to-match=/**/v1/**/
    

    It'll include any endpoint that has /v1/ in it. Examples like /users/v1/, /v1/dasboard and also /user/v1/dashboard.

    springdoc.paths-to-match=/v2/**
    

    It'll match only endpoints starting with /v2 and going n-level deep. Examples like /v2/dashboard will be included but /users/v2/something will be excluded.

    springdoc.paths-to-match=/**/v1
    

    It'll only match paths that end at /v1. Examples like /users/v1 will be matched while those like /v1/user will not be matched.

    Alternatively, you can also update your Bean to do the same. But note that properties files take precedence over bean config.

    // you existing bean here
    
    // Define an API group that'll include specific version. Can be helpful in versioning the APIs.
    @Bean
    public GroupedOpenApi hideApis() {
        return GroupedOpenApi.builder().group("default")
                .pathsToExclude("/api/v2/**", "/v2/**", "/**/v3/**")
                .pathsToMatch("/v1/**", "/api/v1/**")
                .build();
    }