# Code-First with springdoc-openapi in Spring Boot — OpenAPI / Swagger

Source: https://www.skillbyai.com/en/openapi/c-springdoc

> 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.

```java
@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.

**Quiz:** Where does springdoc-openapi serve the generated OpenAPI JSON by default?

- [ ] /openapi.yaml
- [ ] /swagger.json
- [ ] /api/spec
- [x] /v3/api-docs

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