OpenAPI (Swagger) — a standard for describing REST APIs. springdoc-openapi automatically generates documentation from controller annotations.
Simple analogy: OpenAPI is like IKEA instructions. It describes every endpoint: URL, parameters, request body, response, errors. A frontend developer can read and understand without reading code. Or think of it as a table of contents for your API — it lists every chapter (endpoint), what inputs it accepts, and what it outputs.
Why it matters: Without API documentation, frontend developers, mobile developers, and third-party integrators must read your Java source code to understand your API. OpenAPI generates a living, interactive documentation that is always in sync with your code because it is generated from the code itself.
Dependency:
1<dependency>2 <groupId>org.springdoc</groupId>3 <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>4 <version>2.3.0</version>5</dependency>
Controller with annotations:
1@Tag(name = "Users", description = "User management")2@RestController3@RequestMapping("/api/users")4public class UserController {56 @Operation(summary = "Get user by ID")7 @ApiResponses({8 @ApiResponse(responseCode = "200", description = "User found"),9 @ApiResponse(responseCode = "404", description = "Not found",10 content = @Content(schema = @Schema(implementation = ErrorResponse.class)))11 })12 @GetMapping("/{id}")13 public ResponseEntity<UserDto> getUser(14 @Parameter(description = "User ID", example = "1")15 @PathVariable Long id) {16 return ResponseEntity.ok(service.findById(id));17 }1819 @Operation(summary = "Create user")20 @io.swagger.v3.oas.annotations.parameters.RequestBody(21 description = "New user data"22 )23 @PostMapping24 public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {25 return ResponseEntity.ok(service.create(request));26 }2728 @Operation(summary = "Search users")29 @GetMapping30 public Page<UserDto> search(31 @ParameterObject Pageable pageable,32 @RequestParam(required = false) String name) {33 return service.search(name, pageable);34 }35}
Swagger UI: http://localhost:8080/swagger-ui/index.html
OpenAPI JSON: http://localhost:8080/v3/api-docs
Grouping (multiple API docs):
1@Bean2public GroupedOpenApi publicApi() {3 return GroupedOpenApi.builder()4 .group("public")5 .pathsToMatch("/api/public/**")6 .build();7}89@Bean10public GroupedOpenApi adminApi() {11 return GroupedOpenApi.builder()12 .group("admin")13 .pathsToMatch("/api/admin/**")14 .build();15}
Hiding internal endpoints:
1@Hidden // This endpoint won't appear in docs2@GetMapping("/api/internal/health")3public String internalHealth() { return "ok"; }
Common mistakes:
springdoc.api-docs.enabled=false and springdoc.swagger-ui.enabled=false in production profiles.@Schema on DTOs — without it, the docs show field names but no descriptions or examples.@OpenAPIDefinition(info = @Info(title = "API", version = "1.0")).