SkillByAIOpen interactive version →

Lesson 20 / 25

Code-First with springdoc-openapi in Spring Boot

Generate an OpenAPI document from Spring Boot controllers and enrich it with annotations.

Documents from annotated controllers

In Spring Boot, springdoc-openapi (the 2.x line supports Spring Boot 3) inspects controllers, request mappings, parameter types, validation annotations and Jackson models at run time and produces an OpenAPI 3 document, served by default at /v3/api-docs (JSON) with Swagger UI at /swagger-ui.html. It understands Bean Validation constraints (@NotNull, @Size, @Min), so schemas include required fields and limits automatically. Enrich the document with io.swagger.v3.oas.annotations: @Operation(summary, description, operationId), @ApiResponse and @ApiResponses, @Parameter, @Schema on models and fields, @Tag, and @SecurityRequirement; define global metadata and security schemes with an OpenAPI bean or @OpenAPIDefinition and @SecurityScheme. In CI, export the generated document (for example with the springdoc Maven or Gradle plugin, which starts the app and downloads /v3/api-docs) and run the same linting and breaking-change checks as design-first teams. Disable Swagger UI or protect it in production if the API is not public.

A documented Spring controller

Annotations enrich what springdoc infers from the code.

@RestController
@RequestMapping("/orders")
@Tag(name = "Orders", description = "Create and track orders")
class OrderController {

    @Operation(operationId = "getOrder", summary = "Get an order")
    @ApiResponse(responseCode = "200", description = "The order")
    @ApiResponse(responseCode = "404", description = "Order not found",
        content = @Content(mediaType = "application/problem+json",
                           schema = @Schema(implementation = ProblemDetail.class)))
    @GetMapping("/{orderId}")
    OrderDto get(@Parameter(description = "Order id", example = "ord_7Fq2LmX0aB9c")
                 @PathVariable String orderId) {
        return service.get(orderId);
    }
}

@Schema(description = "An order")
record OrderDto(
    @Schema(accessMode = Schema.AccessMode.READ_ONLY, example = "ord_7Fq2LmX0aB9c") String id,
    @NotNull OrderStatus status,
    @NotEmpty @Size(max = 50) List<@Valid OrderItemDto> items,
    @Schema(example = "1499.00") BigDecimal total) { }

// application.yml
// springdoc:
//   api-docs.path: /v3/api-docs
//   swagger-ui.path: /swagger-ui.html
//   default-produces-media-type: application/json

Minutes written from a recording

Code-first is like producing meeting minutes from a recording: always faithful to what was said, but only as clear as the speakers were. Annotations are the notes you add so readers understand the intent.

Quick check: Where does springdoc-openapi serve the generated OpenAPI JSON by default?

  • /openapi.yaml
  • /swagger.json
  • /api/spec
  • /v3/api-docs
Answer

/v3/api-docs — springdoc serves the document at /v3/api-docs and Swagger UI at /swagger-ui.html by default.