Learnitweb

Documenting a Spring REST API Using OpenAPI 3.0

1. Introduction

We need documentation to understand the code or a program. For example, documentation helps us understand what a method does and what it needs as arguments to perform the operation. Similarly, API documentation can also be generated which will be helpful to provide description, request and response format.

Swagger is the most popular tool for API documentation. In this tutorial, we’ll take a look at SpringDoc — a tool that simplifies the generation and maintenance of API documentation based on the OpenAPI 3 specification for Spring Boot 2.x applications.

2. What is OpenAPI Initiative (OAI) and OpenAPI Specification (OAS)

The OpenAPI Initiative (OAI) was created by a consortium of forward-looking industry experts to standardize how the APIs are described. The goal of OAI is to to create and promote vendor neutral description format for APIs.

As mentioned at the official page of OpenAPI Initiative:

The OAS defines a standard, programming language-agnostic interface description for REST APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. When properly defined via OAS, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interface descriptions have done for lower-level programming, the OAS removes guesswork in calling a service.

3. springdoc-openapi library

The springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. This library works by examining annotation, classes and configurations at runtime to infer API semantics. This library can auto generate documentation in JSON/YAML and HTML format APIs.

4. Dependency

To integrate swagger-ui with Spring Boot, include the following dependency in the pom.xml:

 <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-ui</artifactId>
      <version>1.6.5</version>
 </dependency>

If project uses spring-data-rest, add the following dependency in addition to springdoc-openapi-ui. This provides support for spring-boot-starter-data-rest types.

 <dependency>
     <groupId>org.springdoc</groupId>
     <artifactId>springdoc-openapi-data-rest</artifactId>
     <version>1.6.5</version>
 </dependency>

If a project uses spring-security, you should add the following dependency, in addition to the springdoc-openapi-ui dependency:

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-security</artifactId>
      <version>1.6.5</version>
   </dependency>

Adding dependency is enough to get started and this will automatically deploy swagger-ui to a spring-boot application.

  • The Swagger UI page will be available at http://server:port/context-path/swagger-ui.html.
  • The OpenAPI description will be available at http://server:port/context-path/v3/api-docs in json format.
  • Documentation is available in yaml format at /v3/api-docs.yaml.

Here, server is the name of server or its IP. port is the server port. context-path is the context-path of the application.

5. Example

In this example, we’ll create a Spring Boot application and will add a couple of REST APIs to it. We’ll then add SpringDoc support to the application to create documentation of APIs.

5.1 Create a Spring Boot application

The first step is to create a Spring Boot application support.

Following is the pom.xml in our case:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.learnitweb</groupId>
	<artifactId>demoOpenApi</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demoOpenApi</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
      		<groupId>org.springdoc</groupId>
      		<artifactId>springdoc-openapi-ui</artifactId>
      		<version>1.6.5</version>
 		</dependency>
 		
    	<dependency>
        	<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-starter-actuator</artifactId>
    	</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

5.2 Add REST APIs

We’ll add test APIs to demonstrate the documentation of APIs.

HelloController.java

package com.learnitweb.demoOpenApi.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.learnitweb.demoOpenApi.model.Request;

import io.swagger.v3.oas.annotations.parameters.RequestBody;

@RestController
public class HelloController {
	@GetMapping("/message")
	public ResponseEntity<?> getTestApi() {
		Map<String, String> result = new HashMap();
		result.put("message", "Hello world");
		return new ResponseEntity(result, HttpStatus.OK);
	}

	@GetMapping("/message/{id}")
	public ResponseEntity<?> getTestApiById(@PathVariable String id) {
		// use id here
		return new ResponseEntity("test message", HttpStatus.OK);
	}

	@PostMapping("/message")
	public ResponseEntity<?> postTestApi(@RequestBody Request req) {
		Map<String, String> result = new HashMap();
		result.put("message", "Hello world");
		return new ResponseEntity(result, HttpStatus.OK);
	}
}

Request.java

package com.learnitweb.demoOpenApi.model;

import java.util.Date;

public class Request {
	String message;
	String sender;
	Date time;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getSender() {
		return sender;
	}

	public void setSender(String sender) {
		this.sender = sender;
	}

	public Date getTime() {
		return time;
	}

	public void setTime(Date time) {
		this.time = time;
	}
}

That is it. Adding dependency is enough to integrate swagger-ui with the Spring Boot application.

You can access the swagger documentation in HTML format at http://localhost:8080/swagger-ui/index.html.

Documenting a Spring REST API Using OpenAPI 3.0 example

6. Custom path of the swagger documentation in HTML format

To use a custom path of the swagger documentation in HTML format, define springdoc.swagger-ui.path property in Spring Boot configuration file:

springdoc.swagger-ui.path=/my-app-swagger-ui.html

7. Actuator support

By default, actuator endpoints are not exposed in swagger-ui page. In order to display actuator endpoints in swagger-ui, use the following property in Spring Boot configuration file:

springdoc.show-actuator=true

8. Disabling the springdoc-openapi endpoints

To disable the springdoc-openapi endpoint use the following property:

springdoc.api-docs.enabled=false

9. Selecting the Rest Controllers to include in the documentation

To restrict the generated OpenAPI description using package configuration, use the springdoc.packagesToScan property:

# Packages to include
springdoc.packagesToScan=com.firstPackage, com.secondPackage

To restrict the generated OpenAPI description using path configuration:

# Paths to include
springdoc.pathsToMatch=/v1, /api/employee/**