DEV Community

Francisco Pereira
Francisco Pereira

Posted on

Creating a REST API using Spring Boot + Tests + Documentation [part 05]

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>

Enter fullscreen mode Exit fullscreen mode

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:

Swagger initial screen

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:

Route description

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();
}




}


Enter fullscreen mode Exit fullscreen mode

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:

Updated route description

You can, if you want, create requests from this screen by clicking on the Try it out button:

Request

Response


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)

Collapse
 
naucode profile image
Al - Naucode

Great article, you got my follow, keep writing!