Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

API documentation: OpenAPI and Swagger UI

Whoever writes the front end or a mobile app needs to know the API addresses, parameters and JSON fields. Describing them by hand takes long, and the description soon goes stale. OpenAPI is the standard format for describing a REST API in JSON or YAML. The springdoc-openapi library reads your controllers and records and builds such a description itself, and Swagger UI turns it into a page where every address can be called with a button.

Adding it

springdoc is not part of Spring Boot, so you state the version explicitly. Spring Boot 4 needs the 3.x line (the 2.x line is for Spring Boot 3):

<!-- pom.xml -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>3.1.1</version>
</dependency>

Nothing else is needed: after a restart two addresses appear.

AddressWhat is there
http://localhost:8080/swagger-ui.htmlThe Swagger UI page (redirects to /swagger-ui/index.html)
http://localhost:8080/v3/api-docsThe API description in the OpenAPI format (JSON)

What we get

Open http://localhost:8080/swagger-ui.html. The page groups the addresses: GET /api/posts, POST /api/posts, POST /api/images and others. Expand any of them, press Try it out, then Execute — the request goes to the application, and the response appears below along with a ready-made curl command.

The JSON description starts like this (shortened):

{"openapi":"3.1.0","info":{"title":"OpenAPI definition","version":"v0"},"paths":{"/api/posts/{id}":{"get":{"tags":["post-controller"],"operationId":"show", ...

springdoc found the addresses, path and query parameters, request bodies and codes such as 201 and 204 from @ResponseStatus on its own.

API title and description

// src/main/java/com/example/blog/OpenApiConfig.java
package com.example.blog;
 
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class OpenApiConfig {
 
    @Bean
    public OpenAPI blogOpenApi() {
        return new OpenAPI().info(new Info()
                .title("Blog API")
                .description("Posts, comments and users")
                .version("1.0"));
    }
}

Instead of OpenAPI definition the page header now shows "Blog API" with a description.

Annotations on a controller

// src/main/java/com/example/blog/PostController.java
@RestController
@RequestMapping("/api/posts")
@Tag(name = "Posts", description = "Reading and changing blog posts")
public class PostController {
 
    @Operation(summary = "A single post by id")
    @ApiResponse(responseCode = "200", description = "The post was found")
    @ApiResponse(responseCode = "404", description = "There is no post with this id")
    @GetMapping("/{id}")
    public Post show(@PathVariable Long id) {
        return postService.findById(id);
    }
}
AnnotationWhat it does
@TagA name for the address group instead of post-controller
@Operation(summary)A short caption for the address
@ApiResponseA possible response code and its meaning
@SchemaA description and an example for a record field

All of them come from the io.swagger.v3.oas.annotations package. DTO fields are described like this:

// src/main/java/com/example/blog/NewPostRequest.java
public record NewPostRequest(
        @Schema(description = "Title", example = "Hello, Spring")
        @NotBlank @Size(max = 120) String title,
        @Schema(description = "Post text", example = "The first post")
        @NotBlank String body,
        @Schema(description = "Author name", example = "anna")
        @NotBlank String author) {
}

springdoc takes the validation rules into account too: the title description gets "maxLength":120, and all three fields go into the required list. The Try it out button fills in the values from example.

Turning it off on the server

In the production version the documentation is often hidden:

# src/main/resources/application-prod.yaml
springdoc:
  api-docs:
    enabled: false
  swagger-ui:
    enabled: false

The warning at startup reminds you of the same: SpringDoc /swagger-ui.html endpoint is enabled by default.

Common mistake

Once Spring Security is added (chapter six), the documentation page stops opening: curl -i http://localhost:8080/swagger-ui.html answers 302 and sends you to the /login form. The springdoc addresses do not start with /api, so the site chain handles them, and there everything is closed. Open them explicitly:

// src/main/java/com/example/blog/SecurityConfig.java
.requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**").permitAll()

The line goes into the site chain before anyRequest().

Thanks for reading!

Donate to the site — we work hard for you.