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)
- SprinDoc project is still being actively developed where as Sprinfox development stopped in 2020
- 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.package2
Code 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=false
Code 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=false
Code 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-ui
Code 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-uihttp://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