Using openapi.yaml in springdoc

Viewed 5962

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.

3 Answers

This is available from the FAQ page in the spring-doc documentation. See What is a proper way to set up Swagger UI to use provided spec.yml? and How can use custom json/yml file instead of generated one ? of the same page.

Example from the FAQ page

  1. Turn off auto-generation in the project property file springdoc.api-docs.enabled=false
  2. Put your yaml file in src/main/resources/static such as src/main/resources/static/myApiFile.yaml
  3. Set the swagger-ui url for the file springdoc.swagger-ui.url=/myApiFile.yaml
  4. Enable the minimal beans configuration
import org.springdoc.core.SpringDocConfigProperties;
import org.springdoc.core.SpringDocConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringDocsConfiguration {

  @Bean
  SpringDocConfiguration springDocConfiguration() {
    return new SpringDocConfiguration();
  }

  @Bean
  public SpringDocConfigProperties springDocConfigProperties() {
    return new SpringDocConfigProperties();
  }
}

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;
  }
}
Related