Documenting API in Java Application with Swagger and OpenAPI 3.0

A web application often contains an API to interact with it. By documenting your APIs, your customers can quickly understand how to use your services. If the API is closed from the outside world, then it is still worth taking the time to the specification - it will help your new colleagues to quickly understand the system.







Creating documentation by hand is a tedious process. Swagger will help you make this job easier.







What is Swagger?



Swagger automatically generates API documentation as json. And the Springdoc project will create a user-friendly UI for visualization. You will not only be able to view the documentation, but also send requests and receive responses.







It is also possible to generate a client or server directly according to the Swagger API specification, for this you need a Swagger-Codegen code generator .







Swagger takes a declarative approach, everything we love. You annotate methods, parameters, DTOs.







You will find all examples provided here in my repository .







Creating a REST API



To document the API, let's start by writing it: smile: You can move on to the next chapter so you don't waste time.







Let's add primitive controllers and one DTO. The essence of our system is a user loyalty program.







, . .







DTO UserDto



— . , 3 : , , , ,







public class UserDto {

    private String key;
    private String name;
    private Long points = 0L;
    private Gender gender;
    private LocalDateTime regDate = LocalDateTime.now();

    public UserDto() {
    }

    public UserDto(String key, String name, Gender gender) {
        this.key = key;
        this.name = name;
        this.gender = gender;
    }

    public static UserDto of(String key, String value, Gender gender) {
        return new UserDto(key, value, gender);
    }

    // getters and setters

}
      
      





public enum Gender {
    MAN, WOMAN
}
      
      





-, : UserController



, PointContoller



, SecretContoller



.







UserController



, .







@RestController
@RequestMapping("/api/user")
public class UserController {

    private final Map<String, UserDto> repository;

    public UserController(Map<String, UserDto> repository) {
        this.repository = repository;
    }

    @PutMapping(produces = APPLICATION_JSON_VALUE)
    public HttpStatus registerUser(@RequestBody UserDto userDto) {
        repository.put(userDto.getKey(), userDto);
        return HttpStatus.OK;
    }

    @PostMapping(produces = APPLICATION_JSON_VALUE)
    public HttpStatus updateUser(@RequestBody UserDto userDto) {
        if (!repository.containsKey(userDto.getKey())) return HttpStatus.NOT_FOUND;
        repository.put(userDto.getKey(), userDto);
        return HttpStatus.OK;
    }

    @GetMapping(value = "{key}", produces = APPLICATION_JSON_VALUE)
    public ResponseEntity<UserDto> getSimpleDto(@PathVariable("key") String key) {
        return ResponseEntity.ok(repository.get(key));
    }

}
      
      





PointContoller



. .







@RestController
@RequestMapping("api/user/point")
public class PointController {

    private final Map<String, UserDto> repository;

    public PointController(Map<String, UserDto> repository) {
        this.repository = repository;
    }

    @PostMapping("{key}")
    public HttpStatus changePoints(
            @PathVariable String key,
            @RequestPart("point") Long point,
            @RequestPart("type") String type
    ) {
        final UserDto userDto = repository.get(key);
        userDto.setPoints(
                "plus".equalsIgnoreCase(type) 
                    ? userDto.getPoints() + point 
                    : userDto.getPoints() - point
        );
        return HttpStatus.OK;
    }

}
      
      





destroy



SecretContoller



.







@RestController
@RequestMapping("api/secret")
public class SecretController {

    private final Map<String, UserDto> repository;

    public SecretController(Map<String, UserDto> repository) {
        this.repository = repository;
    }

    @GetMapping(value = "destroy")
    public HttpStatus destroy() {
        repository.clear();
        return HttpStatus.OK;
    }

}
      
      





Swagger



Swagger . .







<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>2.1.6</version>
</dependency>
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.5.2</version>
</dependency>
      
      





Swagger , . HTTP (DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT).







: , .







, . , : localhost:8080/swagger-ui.html







Swagger launched with default settings







. .









. .







SwaggerConfig



— .







@Configuration
public class SwaggerConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(
                        new Info()
                                .title("Example Swagger Api")
                                .version("1.0.0")
                );
    }

}
      
      





  • title



  • version



    — API


UI .









API, ,







@Bean
public OpenAPI customOpenAPI() {
    return new OpenAPI()
            .info(
                    new Info()
                            .title("Loyalty System Api")
                            .version("1.0.0")
                            .contact(
                                    new Contact()
                                            .email("me@upagge.ru")
                                            .url("https://uPagge.ru")
                                            .name("Struchkov Mark")
                            )
            );
}
      
      







, . @Tag



.







@Tag(name=" ", description=" ")
public class ControllerName {

    // ... ... ... ... ...

}
      
      





Added a description of controllers to Swagger









, — SecretController



. @Hidden



.







@Hidden
@Tag(name = " ", description = "   ")
public class SecretController {

    // ... ... ... ... ...

}
      
      





Swagger. . API.







, .









@Operation



. :







  • summary



    — .
  • description



    — .


@Operation(
    summary = " ", 
    description = "  "
)
public HttpStatus registerUser(@RequestBody UserDto userDto) {

    // ... ... ... ... ...

}
      
      





Method annotated with Operation









Parameter



, .







public HttpStatus changePoints(
    @PathVariable @Parameter(description = " ") String key,
    @RequestPart("point") @Parameter(description = " ") Long point,
    @RequestPart("type") @Parameter(description = " ") TypeOperation type
) {

    // ... ... ... ... ...

}
      
      





required



. .







DTO



, . - DTO @Schema









@Schema(description = " ")
public class UserDto {

    @Schema(description = "")
    private String key;

    // ... ... ... ... ...

}
      
      





, : enum, . DTO , .







@Schema(description = "", example = "A-124523")
      
      





:







Schema annotation markup







Schema annotation markup







, . . swagger Schema.AccessMode.READ_ONLY



:







public class UserDto {

    @Schema(accessMode = Schema.AccessMode.READ_ONLY)
    private String key;

    ...

}
      
      







PointController



. , .







.







public HttpStatus changePoints(
    // ... ... ... ... ...
    @RequestPart("point") @Min(0) @Parameter(description = " ") Long point,
    // ... ... ... ... ...
) {

    // ... ... ... ... ...

}
      
      





. point



minimum: 0



.







Swagger validation







.









, API .







, .








All Articles