Swagger and OpenAPI with Spring Boot
API documentation is essential. SpringDoc OpenAPI auto-generates interactive Swagger UI from your controllers.
Setup
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
</dependency>
Run the app and visit:
- Swagger UI: http://localhost:8080/swagger-ui.html
- OpenAPI JSON: http://localhost:8080/v3/api-docs
That’s it — zero configuration needed. SpringDoc reads your controllers automatically.
Customizing API Info
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI bookstoreOpenApi() {
return new OpenAPI()
.info(new Info()
.title("Bookstore API")
.description("REST API for managing books, authors, and orders")
.version("1.0.0")
.contact(new Contact()
.name("Sushil Verma")
.email("admin@bookstore.com"))
.license(new License()
.name("MIT")
.url("https://opensource.org/licenses/MIT")));
}
}
@Tag — Group Endpoints
@RestController
@RequestMapping("/api/books")
@Tag(name = "Books", description = "Book management endpoints")
public class BookController { }
@RestController
@RequestMapping("/api/authors")
@Tag(name = "Authors", description = "Author management endpoints")
public class AuthorController { }
@Operation — Document Endpoints
@Operation(
summary = "Get a book by ID",
description = "Returns a single book by its database ID"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Book found"),
@ApiResponse(responseCode = "404", description = "Book not found")
})
@GetMapping("/{id}")
public ResponseEntity<BookResponse> getById(@PathVariable Long id) {
return ResponseEntity.ok(BookResponse.from(bookService.findById(id)));
}
@Operation(summary = "Create a new book")
@ApiResponse(responseCode = "201", description = "Book created")
@PostMapping
public ResponseEntity<BookResponse> create(
@Valid @RequestBody CreateBookRequest request
) {
Book book = bookService.create(request);
return ResponseEntity.created(URI.create("/api/books/" + book.getId()))
.body(BookResponse.from(book));
}
@Schema — Document Models
@Schema(description = "Request to create a new book")
public record CreateBookRequest(
@Schema(description = "Book title", example = "Clean Code", requiredMode = REQUIRED)
@NotBlank String title,
@Schema(description = "Author name", example = "Robert Martin")
@NotBlank String author,
@Schema(description = "ISBN-13", example = "978-0132350884")
String isbn,
@Schema(description = "Price in USD", example = "39.99", minimum = "0.01")
@Positive BigDecimal price
) {}
Configuration
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
operations-sorter: method
tags-sorter: alpha
show-actuator: true
Disable in production:
# application-prod.yml
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: false
Adding JWT Authentication to Swagger
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI bookstoreOpenApi() {
return new OpenAPI()
.info(new Info().title("Bookstore API").version("1.0.0"))
.addSecurityItem(new SecurityRequirement().addList("Bearer Auth"))
.components(new Components()
.addSecuritySchemes("Bearer Auth",
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("Enter JWT token")));
}
}
Now Swagger UI shows an Authorize button — enter your JWT and all requests include the Authorization: Bearer <token> header.
Key Takeaways
- Add one dependency — Swagger UI is auto-generated from your controllers.
- Use
@Tagto group endpoints,@Operationto document them. - Use
@Schemaon DTOs with examples for clear documentation. - Disable Swagger in production via profile-specific config.
- Add JWT security scheme so testers can authenticate via Swagger UI.
What’s Next?
Next: Spring Data JPA — connecting to databases, entities, repositories, and queries.