Have you ever finished implementing a REST API, only to be told “please write the documentation” — and felt completely lost? Managing docs in hand-crafted Excel sheets leads to missed updates, and writing them in Notion means the gap between docs and implementation quietly grows over time.
With springdoc-openapi, you can auto-generate API documentation directly from your code. Add a few annotations, and your API becomes browsable and executable through a polished web UI called Swagger UI. This article walks you through setup to practical usage, step by step.
From springfox to springdoc-openapi
springfox used to be the go-to choice for auto-generating API docs in Spring Boot. However, compatibility issues became widespread starting with Spring Boot 2.6, and the project has since stalled in maintenance. If you’re working on an existing project using springfox and running into mysterious errors, you’re not alone.
springdoc-openapi is compliant with OpenAPI 3.0 and officially supports Spring Boot 3.x. For any new project, springdoc is the clear choice.
Adding the Dependency
Maven
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
Gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
If you’re using Spring Boot 2.x, use springdoc-openapi-ui (version 1.x) instead. Note that the artifact ID differs. This article assumes Spring Boot 3.x.
Checking Swagger UI First
Simply add the dependency and start your app — Swagger UI is immediately available.
- Swagger UI:
http://localhost:8080/swagger-ui/index.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
Your existing Controllers are scanned automatically and the endpoint list is displayed. It’s genuinely impressive how much works out of the box with zero configuration.
Configuring API Info and JWT Authentication
To customize the Swagger UI title and description, define an OpenAPI Bean in a configuration class. For projects with JWT authentication, setting up a SecurityScheme at the same time is standard practice.
@Configuration
@SecurityScheme(
name = "bearerAuth",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT"
)
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("My API")
.version("1.0.0")
.description("Sample API documentation"));
}
}
Adding @SecurityScheme makes an Authorize button appear in the top-right corner of Swagger UI. Enter your JWT token there and all subsequent requests will automatically include Authorization: Bearer {token}. For details on obtaining a JWT and implementing the authentication flow, see How to Implement JWT Authentication in Spring Boot.
Documenting Endpoints with @Operation
Adding @Operation to a controller method makes the endpoint description appear in Swagger UI. Use @Tag to group endpoints, and @Parameter to document path parameters and query parameters.
@RestController
@RequestMapping("/users")
@Tag(name = "Users", description = "User management API")
public class UserController {
@Operation(summary = "Get user", description = "Returns the user with the specified ID")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "404", description = "User not found")
})
@GetMapping("/{id}")
public ResponseEntity<UserResponseDto> getUser(
@Parameter(description = "User ID", example = "1")
@PathVariable Long id
) {
// implementation
}
@Operation(summary = "Create user")
@SecurityRequirement(name = "bearerAuth")
@PostMapping
public ResponseEntity<UserResponseDto> createUser(
@RequestBody UserRequestDto dto
) {
// implementation
}
}
Endpoints annotated with @SecurityRequirement(name = "bearerAuth") display a lock icon in Swagger UI. The token configured via Authorize is applied automatically, making it easy to test JWT-protected endpoints directly from the UI.
Documenting error responses like 400 or 404 with @ApiResponse makes it much easier for your frontend team to implement accordingly. For a consistent approach to exception handling, see How to Unify Exception Handling in a Spring Boot REST API.
Documenting DTO Fields with @Schema
Adding @Schema to a DTO class makes field descriptions and example values appear in Swagger UI.
public class UserRequestDto {
@Schema(description = "Username", example = "John Doe")
@NotBlank
private String name;
@Schema(description = "Email address", example = "[email protected]")
@Email
private String email;
}
Validation annotations like @NotBlank and @Email are automatically picked up by springdoc-openapi and reflected as required flags and format values — no need to duplicate that information. For details on implementing validation, see How to Implement Validation with @Valid in Spring Boot.
If your pagination API accepts Pageable directly, add @ParameterObject to automatically document the page and size parameters. For implementing pagination itself, see How to Implement Pagination in a Spring Boot REST API.
Fetching YAML/JSON and CI Integration
You can easily fetch the OpenAPI spec file with curl.
# JSON format
curl http://localhost:8080/v3/api-docs
# YAML format
curl http://localhost:8080/v3/api-docs.yaml -o api-docs.yaml
Pass the fetched YAML to openapi-generator to auto-generate client code in TypeScript, Kotlin, or other languages. Committing this YAML to your repository also lets your CI pipeline detect API changes as diffs.
Disabling Swagger UI in Production
Avoid releasing to production with Swagger UI publicly accessible. You can disable it with just two lines in application-prod.properties.
springdoc.swagger-ui.enabled=false
springdoc.api-docs.enabled=false
For managing environment-specific configuration with Spring Profiles, see How to Switch Environment Configuration with Spring Boot Profiles.
Summary
This article covered everything from setting up springdoc-openapi to practical usage. Adding a single dependency gets Swagger UI running immediately, and you can incrementally enrich your documentation by adding annotations over time.
- Use
@Operation,@ApiResponse, and@Schemato build up documentation incrementally - Combine
@SecuritySchemewith@SecurityRequirementto test JWT-protected endpoints directly from Swagger UI /v3/api-docs.yamlserves as the entry point for CI integration and client code generation- Always disable with
enabled=falsein production environments
Your communication with the frontend team will become significantly smoother.