Swagger and OpenAPI with Spring Boot

2 minute read

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:

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

  1. Add one dependency — Swagger UI is auto-generated from your controllers.
  2. Use @Tag to group endpoints, @Operation to document them.
  3. Use @Schema on DTOs with examples for clear documentation.
  4. Disable Swagger in production via profile-specific config.
  5. 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.

Updated: