Spring Boot – REST API Documentation with SpringDoc OpenAPI

In this blog post, we will see how to generate Spring Boot REST API documentation in Open API format and REST client with SpringDoc library . SpringDoc library generates API docs based on the OpenAPI 3 specification for Spring Boot 1.x and 2.x applications.

In one of my previous blog post , I have shown how to generate REST API documentation using Springfox Swagger libraries.

springdoc-openapi java library helps to automate the generation of API documentation of spring boot projects. springdoc-openapi works by examining an application at runtime to infer API semantics based on spring configurations, class structure and various annotations.

Advantages of using Sprindoc over Springox ( Swagger 2)

  1. SprinDoc project is still being actively developed where as Sprinfox development stopped in 2020
  2. Works with all version of Spring Boot without any issues

Documenting REST API

springdoc-openapi automatically generates documentation in JSON/YAML (OpenAPI complaint format) and HTML format APIs. This documentation can be completed by comments using swagger-api annotations. Springdoc internally uses swagger-ui to generate the HTML documentation.

This library supports:

  • OpenAPI 3
  • Spring-boot (v1 and v2)
  • JSR-303, specifically for @NotNull, @Min, @Max, and @Size.
  • Swagger-ui
  • OAuth 2
  • GraalVM native images

Adding SpringDoc Dependencies

To generate documentation with SpringDoc , first we need to add the following dependency in pom.xml

<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-ui</artifactId>
      <version>1.6.9</version>
   </dependency>Code language: HTML, XML (xml)

Create Config File

There is no need to write config file while using SpringDoc library for default implementation.

If you want to group the APIs, you need to write below code

@SpringBootApplication
public class SpringbootSpringdocOpenapiApplication {  
....
@Bean
  public GroupedOpenApi publicApi() {
      return GroupedOpenApi.builder()
              .group("eis-user")
              .pathsToMatch("/user/**")
              .build();
  }
  @Bean
  public GroupedOpenApi adminApi() {
      return GroupedOpenApi.builder()
              .group("eis-admin")
              .pathsToMatch("/admin/**")              
              .build();
  }
}

Code language: Java (java)

Accessing the REST API Documentation

Now let’s start the application

After starting application, you can access REST API documentation by visiting following URL’s

http://localhost:8080/v3/api-docs – shows API in JSON format

http://localhost:8080/v3/api-docs.yaml – shows the API in YAML format

http://localhost:8080/swagger-ui/index.html – shows API documentation using HTML

The above screenshot shows the all the Controllers and Models available in the application.

By clicking on the each controller , we can see the path to invoke controllers and operations supported by it.

By clicking on each Model, we can see the model fields and its data types.

Testing REST API

Apart from nicely showing all the documentation of API, Springdoc also provides interface to test it.

By clicking on the operation/method shows a test page, where you can see the required input and sample response in the page.

Clicking on the Try it out button enables the form for input and shows the execute button, which you can use to submit the request.

Customizing the Documentation Page

Restricting the Scope of API Documentation

If you want to include API only from certain packages, use following property in application.properties

springdoc.packagesToScan=com.package1, com.package2Code language: HTML, XML (xml)

Paths to include

If you want include API with certain paths, use following property in application.properties.

# Paths to include
springdoc.pathsToMatch=/employee/**
Code language: plaintext (plaintext)

Adding API Info

We can customize the page to show API information such as company branding, license , contact info and description on the page by adding OpenAPI bean.

@SpringBootApplication
public class SpringbootSpringdocOpenapiApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootSpringdocOpenapiApplication.class, args);
	}

	@Bean
	public OpenAPI springShopOpenAPI() {
		return new OpenAPI()
				.info(new Info().title("EIS API")
						.description("Employee Information System sample application")
						.version("v0.0.1")
						.license(new License().name("Apache 2.0").url("http://springdoc.org"))
						.description("SpringShop Wiki Documentation")
						.contact(new Contact().email("[email protected]").url("http://fullstackcode.dev")))
						;
	}
}Code language: Java (java)

Describing Model classes

Sprindoc provides annotation to describe the Model class and Its fields.

Springdoc supports swagger 3 annotations.

We use @Schema annotation to describe the models

@Schema(description="Manages employee object ")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@Entity
@ConditionalNotNull(fields = "salary,email",dependsOn = "hire_date" )
public class Employee implements Serializable {


    @Schema(description="Auto generated unique id",required = true)
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Null(groups = {OnCreate.class})
    @NotNull(groups = OnUpdate.class)
    private Integer id;

    @Schema(description="FirstName should not be blank",required = true,example = "Suresh")
    @NotBlank(message = "FirstName should not be blank")
    @Size(min = 3, message = "{validation.firstNameSize}")
    @ValidName
    private String first_name;


    @Schema(description="Last name of employee",required = true,example = "Suresh")
    @NotBlank(message = "LastName should not be blank")
    @Size(min = 3,message = "LastName should be at least ${min} chars")

    private String last_name;


    @Schema(description="Gender of employee")
    @Enumerated(EnumType.STRING)
    private Gender gender;


    @PastOrPresent
    private LocalDate birth_date;


    @PastOrPresent
    private LocalDate hire_date;


    @Schema(description="Email of employee")
    @Email   
    private String email;

    @Schema(description="Salary of employee",minimum="0")
    @PositiveOrZero
    private BigDecimal salary;

    @Schema(description="Department details of employee")
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
     ...

}Code language: Java (java)

Describing Controller classes

Similar to the model classes we can describe the controller classes.

Springdoc supports swagger 3 annotations.

We use following annotation to describe the controllers

@Tag

@Operation

@Tag(name = "EmployeeController", description = "Manages operations on Employee")
@RestController
@RequestMapping("/employee")
@Validated
public class EmployeeController {

    @Autowired
    EmployeeService employeeService;


    @Operation(description = "List of all employees")
    @GetMapping()
    public List<Employee> getEmployees() {
        return employeeService.getAllEmployees();
    }


   @Operation( description = "Find employee by ID",
           parameters = { @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") },
           responses = { @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Employee.class))),
                   @ApiResponse(responseCode = "404", description = "Employee not found", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) })
    @GetMapping("/{id}")
    public Employee getEmployee(   @PathVariable @Min(1) Integer id) {
        return employeeService.getEmployeeById(id).orElseThrow(() ->new ResponseStatusException(HttpStatus.NOT_FOUND,"Employee not found with id : "+ id));
    }



    @Operation( description = "createEmployee")
    @ResponseStatus(HttpStatus.CREATED) // send HTTP 201 instead of 200 as new object created
    @PostMapping
    @Validated(OnCreate.class)
    public Employee createEmployee( @RequestBody @Valid Employee employee) {
        return employeeService.createEmployee(employee);
    }


    @Operation(description = "updateEmployee details")
    @PutMapping()
    public Employee updateEmployee(@RequestBody  @Validated({OnUpdate.class, Default.class}) Employee employee) {
        return employeeService.updateEmployee(employee);
    }

    @Operation(description = "Delete employee  based on the employee id")
    @DeleteMapping(value="/{id}")
    public  void deleteEmployee(  @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") @PathVariable("id") @Min(1) Integer id){
        employeeService.deleteEmployee(id);
    }

    @Operation(description = "Update employee department based on the employee id")
    @PatchMapping("/{id}/dept/{deptId}")
    public Employee updateEmpDepartment(@PathVariable("id") @Min(1) Integer emp_id , @PathVariable("deptId") @Min(1) Integer dept_id, @PathParam("id") @Min(1) String id) {
       return employeeService.updateEmpDepartment(emp_id,dept_id);
    }


    @Operation(description = "Update employee department based on the employee id")
    @PatchMapping("/{id}")
    public Employee updateEmpDepartmentById(@PathVariable("id") Integer emp_id , @RequestBody Department department) {
        return employeeService.updateEmpDepartment(emp_id,department.getId());
    }


    @Operation( description = "Get employees base on gender")
    @GetMapping(value="/gender/{gender}")
    public List<Employee> getEmployeesByGender(@PathVariable String gender) {

        return employeeService.findEmployeesByGender(Gender.valueOf(gender));
    }



}

Code language: Java (java)

Disabling the springdoc-openapi endpoints

In order to disable the springdoc-openapi endpoint (/v3/api-docs by default) use the following property:

# Disabling the /v3/api-docs endpoint
springdoc.api-docs.enabled=falseCode language: Java (java)

Disabling the swagger-ui

In order to disable the swagger-ui, use the following property:

# Disabling the swagger-ui
springdoc.swagger-ui.enabled=falseCode language: Java (java)

Display the actuator endpoints

springdoc.show-actuator=true
Code language: Java (java)

If you are using different management port you can enable actuator end points on that port instead of default port 8080

management.server.port=9090
springdoc.use-management-port=true
# This property enables the openapi and swagger-ui endpoints to be exposed beneath the actuator base path.
management.endpoints.web.exposure.include=openapi, swagger-uiCode language: Java (java)

if you are using above properties, API documentation will be available on following endpoints

  • http://serverName:9090/actuator
  • http://serverName:9090/actuator/swagger-ui – An Endpoint, that routes to the swagger-ui
  • http://serverName:9090/actuator/openapi – REST API that holdes the OpenAPI definition

Springdoc-openapi Support for Spring modules

Springdoc supports auto generation of documentation for various spring /spring boot modules.We need to add corresponding dependency along with the springdoc-openapi-ui jar

Spring WebMvc

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-webmvc-core</artifactId>
      <version>1.6.9</version>
   </dependency>
Code language: Java (java)

Spring WebFlux 

<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-webflux-ui</artifactId>
      <version>1.6.9</version>
   </dependency>Code language: Java (java)

Spring Hateoas

<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-hateoas</artifactId>
      <version>1.6.9</version>
   </dependency>Code language: Java (java)

Spring Data Rest

<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-data-rest</artifactId>
      <version>1.6.9</version>
   </dependency>Code language: Java (java)

Spring Security

 <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-security</artifactId>
      <version>1.6.9</version>
   </dependency>Code language: Java (java)

Spring Native

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-native</artifactId>
      <version>1.6.9</version>
   </dependency>
Code language: Java (java)

You can download source code for this blog post from GitHub

Similar Posts