Spring Boot RESTful API Documentation with OpenAPI 3.0 and Swagger-UI using springdoc-openapi

Tags: Spring Boot springdoc-openapi OpenAPI 3 Swagger UI RestController SpringBootApplication RESTful API

Introduction

In this Spring Boot RESTful API tutorial, we learn how to use the springdoc-openapi Java library in the Spring Boot project to generate the documentation for the Restful API. Step by step we learn how to generate the document in OpenAPI 3.0 standard and then showing the document in Swagger-UI.

Table of contents

  1. Create New Spring Boot RESTful API Project
  2. Add springdoc-openapi to your Java Spring Boot RESTful API project
  3. Create Sample Entity class and Controller
  4. OpenAPI 3.0 and Swagger-UI
  5. Custom Configurations for OpenAPI 3.0 and Swagger-UI
  6. Final Application Source Code
  7. Download Source Code

Create New Spring Boot RESTful API Project

Open Spring Tool Suite IDE, select menu File > New > Spring Starter Project.

On the New Spring Starter Project popup input new project information as below and click Next.

  • Name: spring-boot-api-doc
  • Group: dev.simplesolution
  • Artifact: spring-boot-api-doc
  • Version: 1.0.0
  • Description: Spring Boot REST API Documentation
  • Package: dev.simplesolution.rest

Create New Spring Boot RESTful API Project

On the New Spring Starter Project Dependencies popup choose dependencies as below and click Next.

  • Spring Web

Create New Spring Boot RESTful API Project

Keep the information on the next popup as default and click Finish.

Create New Spring Boot RESTful API Project

Add springdoc-openapi to your Java Spring Boot RESTful API project

To use the springdoc-openapi Java library in the Gradle build project, add the following dependency into the build.gradle file.

implementation 'org.springdoc:springdoc-openapi-ui:1.5.3'

To use the springdoc-openapi Java library in the Maven build project, add the following dependency into the pom.xml file.

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

To have more information about the springdoc-openapi Java library you can visit the springdoc-openapi homepage at springdoc.org

Create Sample Entity class and Controller

Create a new Java package named dev.simplesolution.rest.entities and a new Contact class.

/src/main/java/dev/simplesolution/rest/entities/Contact.java

package dev.simplesolution.rest.entities;

public class Contact {
	private Long id;
	private String firstName;
	private String lastName;
	private String email;
	private String phone;
	private String address;
	
	public Contact() {
		
	}
	
	public Contact(Long id, String firstName, String lastName, String email, String phone, String address) {
		super();
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
		this.email = email;
		this.phone = phone;
		this.address = address;
	}
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}	
}

Create a new Java package named dev.simplesolution.rest.repositories and a new interface named ContactRepository.

/src/main/java/dev/simplesolution/rest/repositories/ContactRepository.java

package dev.simplesolution.rest.repositories;

import java.util.List;

import dev.simplesolution.rest.entities.Contact;

public interface ContactRepository {
	List<Contact> getAll();
	Contact getById(Long id);
	Contact save(Contact newContact);
	Contact update(Contact newContact);
	void delete(Long id);
}

Create a new Java packaged named dev.simplesolution.rest.repositories.impl and implement a new class named ContactInMemoryRepository. In this class we implement to store the Contact objects in memory.

/src/main/java/dev/simplesolution/rest/repositories/impl/ContactInMemoryRepository.java

package dev.simplesolution.rest.repositories.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import dev.simplesolution.rest.entities.Contact;
import dev.simplesolution.rest.repositories.ContactRepository;

@Service
public class ContactInMemoryRepository implements ContactRepository {
	
	private static List<Contact> contacts = new ArrayList<>();
	
	public ContactInMemoryRepository() {
		// initialize test data
		contacts.add(new Contact(1L, "John", "Doe", "john@simplesolution.dev", "123-456-789", "address 123, street 1, city 1"));
		contacts.add(new Contact(2L, "Emerson", "Wilks", "emerson@simplesolution.dev", "123-456-788", "address 456, street 2, city 1"));
		contacts.add(new Contact(3L, "Wade", "Savage", "wade@simplesolution.dev", "123-456-787", "address 789, street 3, city 1"));
		contacts.add(new Contact(4L, "Star", "Lott", "star@simplesolution.dev", "123-456-786", "address 234, street 4, city 1"));
		contacts.add(new Contact(5L, "Claudia", "James", "claudia@simplesolution.dev", "123-456-785", "address 678, street 5, city 1"));
	}

	@Override
	public List<Contact> getAll() {
		return contacts;
	}

	@Override
	public Contact getById(Long id) {
		Contact result = contacts.stream()
				.filter(contact -> contact.getId().equals(id))
				.findAny()
				.orElse(null);
		return result;
	}

	@Override
	public Contact save(Contact newContact) {
		contacts.add(newContact);
		return newContact;
	}

	@Override
	public Contact update(Contact newContact) {
		Contact currentContact = contacts.stream()
				.filter(contact -> contact.getId().equals(newContact.getId()))
				.findAny()
				.orElse(null);
		currentContact.setFirstName(newContact.getFirstName());
		currentContact.setLastName(newContact.getLastName());
		currentContact.setEmail(newContact.getEmail());
		currentContact.setPhone(newContact.getPhone());
		currentContact.setAddress(newContact.getAddress());
		return currentContact; 
	}

	@Override
	public void delete(Long id) {
		Contact currentContact = contacts.stream()
				.filter(contact -> contact.getId().equals(id))
				.findAny()
				.orElse(null);
		contacts.remove(currentContact);
	}
}

Create a new Java package named dev.simplesolution.rest.controller and a new ContactController class.

/src/main/java/dev/simplesolution/rest/controller/ContactController.java

package dev.simplesolution.rest.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import dev.simplesolution.rest.entities.Contact;
import dev.simplesolution.rest.repositories.ContactRepository;

@RestController
public class ContactController {
	
	@Autowired
	private ContactRepository contactRepository;
	
	@GetMapping("/contacts")
	public List<Contact> getAll() {
		return contactRepository.getAll();
	}

	@GetMapping("/contacts/{id}")
	public Contact getContactById(@PathVariable Long id) {
		return contactRepository.getById(id);
	}
	
	@PostMapping("/contacts")
	public Contact createNewContact(@RequestBody Contact newContact) {
		return contactRepository.save(newContact);
	}
	
	@PutMapping("/contacts/{id}")
	public Contact updateContact(@RequestBody Contact newContact, @PathVariable Long id) {
		newContact.setId(id);
		return contactRepository.update(newContact);
	}
	
	@DeleteMapping("/contacts/{id}")
	public void deleteContact(@PathVariable Long id) {
		contactRepository.delete(id);
	}
}

OpenAPI 3.0 and Swagger-UI

Run the Spring Boot project then the springdoc-openapi library automatically generate the OpenAPI 3.0 document at the link http://localhost:8080/v3/api-docs/

Create New Spring Boot RESTful API Project

And the Swagger UI at http://localhost:8080/swagger-ui/index.html

Create New Spring Boot RESTful API Project

Custom Configurations for OpenAPI 3.0 and Swagger-UI

In order to customize the OpenAPI 3.0 link and Swagger UI link above you can update the following properties in the application.properties file.

  • The springdoc.api-docs.path property to configure OpenAPI 3.0 path.
  • The springdoc.swagger-ui.path property to configure Swagger UI path.

/src/main/resources/application.properties

springdoc.api-docs.path=/v1/api
springdoc.swagger-ui.path=/documentation.html

Re-run your Spring Boot application and visit new link at http://localhost:8080/v1/api

Create New Spring Boot RESTful API Project

And new Swagger UI link at http://localhost:8080/documentation.html

Create New Spring Boot RESTful API Project

Final Application Source Code

At this step we have the complete Spring Boot project with code structure as below.

Create New Spring Boot RESTful API Project

Download Source Code

The source code in this article can be found at: github.com/simplesolutiondev/spring-boot-api-doc

or clone at:

git clone https://github.com/simplesolutiondev/spring-boot-api-doc.git

or download at:

Download Source Code

Happy Coding 😊