Hello!
I'm back in this tutorial to teach you how to develop a REST API using Spring Boot. As I said earlier, this tutorial is divided into 5 parts as shown in the following table:
Part | Content |
---|---|
Part 01 | Application Startup |
Part 02 | Settings and Database |
Part 03 | API Implementation |
Part 04 | Tests + Coverage |
Part 05 | Swagger Documentation |
It is expected that from this final part you will learn the following:
- Use of Swagger for project documentation.
Remembering that in this tutorial the following tools are used:
- JDK 17
- IntelliJ
- Insomnia
- Maven
- MySQL database
We arrived at our last part of the tutorial. In the previous part you learned how to do unit and integration tests. In addition to also checking the coverage of tests performed.
In this last part, which will be a little shorter, you'll learn how to document your API.
When we work with an API we have to keep in mind that other developers will want access to it. Not necessarily to your source code, but to the responses from requests.
Therefore, we need to create documentation that will visually present all possible access routes of our system and their responses.
Step 01 - Added the SpringDoc library
We will be using Swagger which is already well known for documenting APIs
To use it within our application, we will have to add the Spring Doc dependency within the pom.xml
file:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
By doing this (and restarting your server), we can access the URL http://localhost:8080/swagger-ui/index.html and the following screen will be seen:
As you can see, Swagger already mapped all the routes we created in the system, but it didn't complete all the necessary information for a good documentation. For example, clicking to see more information about the following route:
It only shows that the response will be a String, instead of showing the actual content. Therefore, we will have to make the following modification to our controller:
package com.simplelibrary.simplelibraryAPI.controller;
import com.simplelibrary.simplelibraryAPI.dto.BookRequestDTO;
import com.simplelibrary.simplelibraryAPI.dto.BookResponseDTO;
import com.simplelibrary.simplelibraryAPI.model.Book;
import com.simplelibrary.simplelibraryAPI.service.BookService;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import java.io.IOException;
@RestController
@RequestMapping("books")
public class BookController {
@Autowired
private BookService bookService;
@ApiResponse(
content = { @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = BookResponseDTO.class)))})
@GetMapping
public ResponseEntity<Page<BookResponseDTO>> getAllBooks(@PageableDefault(size=10, sort={"title"}) Pageable pagination) throws IOException {
var page = bookService.getAllBooks(pagination);
return ResponseEntity.ok(page);
}
@ApiResponse(
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = BookResponseDTO.class))})
@GetMapping("/{id}")
public ResponseEntity show(@PathVariable Long id){
var book = bookService.show(id);
return ResponseEntity.ok(book);
}
@ApiResponse(
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Book.class))})
@PostMapping
public ResponseEntity store(@RequestBody @Valid BookRequestDTO bookRequest, UriComponentsBuilder uriBuilder) throws IOException {
var book = bookService.store(bookRequest);
var uri = uriBuilder.path("/books/{id}").buildAndExpand(book.getId()).toUri();
return ResponseEntity.created(uri).body(book);
}
@ApiResponse(
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Book.class))})
@PutMapping("/{id}")
public ResponseEntity update(@PathVariable Long id, @RequestBody @Valid BookRequestDTO bookRequest){
var book = bookService.update(id, bookRequest);
return ResponseEntity.ok(book);
}
@DeleteMapping("/{id}")
public ResponseEntity delete(@PathVariable Long id){
bookService.delete(id);
return ResponseEntity.noContent().build();
}
}
Note that the @ApiResponse
annotation has been added. Inside it, we put what will be the response content of each route. So, when checking the same route:
You can, if you want, create requests from this screen by clicking on the Try it out button:
What we learned in this tutorial
Well folks, I hope you enjoyed this sequel of the Spring Boot tutorial. I believe that with the knowledge gained from these 5 parts, you can start moving towards creating more robust applications.
Don't stick to just what was taught in this tutorial, be free to modify any piece of code that was added here. Any questions you can contact me!
Remembering once again, the complete project you can find HERE
Oldest comments (1)
Great article, you got my follow, keep writing!