Search code examples
swaggerspringdoc

Using openapi.yaml in springdoc


I can customize OpenAPI from code.
Can I do same over openapi.yaml like swagger-petstore
I create simple springboot project with one @RestController.
I create openapi.yaml and copy it to /src/main/resources/.
But I see default values on open swagger-ui page.


Solution

  • The code below is all what we needed to do to use openapi.yaml specification file instead of the default one that is generated from code.

    Explanation:

    • org.springdoc.webflux.api.OpenApiResource is Controller that handles /v3/api-docs and /v3/api-docs.yaml endpoints. Swagger UI is using that endpoint to show swagger ui page - /swagger-ui.html. You can see the configuration when you hit /v3/api-docs/swagger-config endpoint.

    • org.springdoc.webflux.api.OpenApiResource bean is registered only if missing. You can see it in SpringDocWebFluxConfiguration. The method that creates the bean is annotated with @ConditionalOnMissingBean. So you just need to extend it and adjust OpenApi specification retrieval (see below).

    • org.springdoc.webflux.api.OpenApiResource is using getOpenApi() method to retrieve OpenAPI specification (by default the specification is generated based on the class annotation from code). So you just need to override getOpenApi() method and provide the specification from yaml file itself (getYamlMapper() method is also provided for you in the parent classes, so it's really that easy how it is in the file below)

    • You can see OpenApiResource is in webflux package because we use org.springdoc:springdoc-openapi-webflux-ui, Spring WebFlux. It is done similarly in Spring MVC.

    • Hope this helps :) When you hit /swagger-ui.html you should see the docs directly from .yaml spec. When you hit /v3/api-docs you should see the specs itself in JSON. When you hit /v3/api-docs.yaml you should see the specs itself in YAML. No Spring Configuration code is needed. Just the controller as you see below :)

    • Just to be clear. Our OpenAPI spec is in src/main/resources/openapi/api.yaml


    package com.your.package;
    ...imports omitted for readability...
    import org.springdoc.webflux.api.OpenApiResource;
    
    @RestController
    public class OpenApiController extends OpenApiResource {
    
      @Value("classpath:openapi/api.yaml")
      private Resource openAPIResource;
    
      private OpenAPI openAPI;
    
      public OpenApiController(ObjectFactory<OpenAPIBuilder> openAPIBuilderObjectFactory, AbstractRequestBuilder requestBuilder, GenericResponseBuilder responseBuilder, OperationBuilder operationParser, RequestMappingInfoHandlerMapping requestMappingHandlerMapping, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocConfigProperties springDocConfigProperties, Optional<ActuatorProvider> actuatorProvider) {
        super(openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, requestMappingHandlerMapping, operationCustomizers, openApiCustomisers, springDocConfigProperties, actuatorProvider);
      }
    
      @SneakyThrows
      @PostConstruct
      public void initOpenAPI() {
        openAPI = getYamlMapper().readValue(openAPIResource.getInputStream(), OpenAPI.class);
      }
    
      @Override
      protected synchronized OpenAPI getOpenApi() {
        return openAPI;
      }
    }