<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Francisco Pereira</title>
    <description>The latest articles on Forem by Francisco Pereira (@franciscotis).</description>
    <link>https://forem.com/franciscotis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F794996%2F023425f4-78ec-48c7-84c1-2a2c1228322e.jpg</url>
      <title>Forem: Francisco Pereira</title>
      <link>https://forem.com/franciscotis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/franciscotis"/>
    <language>en</language>
    <item>
      <title>Creating a REST API using Spring Boot + Tests + Documentation [part 05]</title>
      <dc:creator>Francisco Pereira</dc:creator>
      <pubDate>Wed, 01 Feb 2023 18:16:34 +0000</pubDate>
      <link>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6</link>
      <guid>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6</guid>
      <description>&lt;p&gt;Hello!&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Part&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Part 01&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262"&gt;Application Startup&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 02&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i"&gt;Settings and Database&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 03&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e"&gt;API Implementation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 04&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;Tests + Coverage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Part 05&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Swagger Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It is expected that from this final part you will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use of Swagger for project documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remembering that in this tutorial the following tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;IntelliJ&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;MySQL database&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;We arrived at our last part of the tutorial. In the &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;previous part&lt;/a&gt; you learned how to do unit and integration tests. In addition to also checking the coverage of tests performed.&lt;/p&gt;

&lt;p&gt;In this last part, which will be a little shorter, you'll learn how to document your API.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Therefore, we need to create documentation that will visually present all possible access routes of our system and their responses.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 01 - Added the SpringDoc library&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We will be using &lt;a href="https://swagger.io" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt; which is already well known for documenting APIs &lt;/p&gt;

&lt;p&gt;To use it within our application, we will have to add the &lt;a href="https://springdoc.org" rel="noopener noreferrer"&gt;Spring Doc&lt;/a&gt; dependency within the &lt;code&gt;pom.xml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springdoc&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;springdoc-openapi-starter-webmvc-ui&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this (and restarting your server), we can access the URL &lt;a href="http://localhost:8080/swagger-ui/index.html" rel="noopener noreferrer"&gt;http://localhost:8080/swagger-ui/index.html&lt;/a&gt; and the following screen will be seen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjttgved09bs44byms32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjttgved09bs44byms32.png" alt="Swagger initial screen" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fratc4t60tygef8ckw7s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fratc4t60tygef8ckw7s8.png" alt="Route description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
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&amp;lt;Page&amp;lt;BookResponseDTO&amp;gt;&amp;gt; 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();
}




}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;@ApiResponse&lt;/code&gt; annotation has been added. Inside it, we put what will be the response content of each route. So, when checking the same route:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotmjmjtcfhj3nwh6gdvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotmjmjtcfhj3nwh6gdvx.png" alt="Updated route description" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can, if you want, create requests from this screen by clicking on the &lt;em&gt;Try it out&lt;/em&gt; button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzd6rkiv6ycxosq91jrge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzd6rkiv6ycxosq91jrge.png" alt="Request" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptl1of778eaonfen6q0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptl1of778eaonfen6q0n.png" alt="Response" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What we learned in this tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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! &lt;/p&gt;

&lt;p&gt;Remembering once again, the complete project you can find &lt;a href="https://github.com/franciscotis/simple-library-api" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

</description>
      <category>community</category>
      <category>howto</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Creating a REST API using Spring Boot + Tests + Documentation [part 04]</title>
      <dc:creator>Francisco Pereira</dc:creator>
      <pubDate>Wed, 01 Feb 2023 18:16:33 +0000</pubDate>
      <link>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190</link>
      <guid>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190</guid>
      <description>&lt;p&gt;Hello!&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Part&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Part 01&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262"&gt;Application Startup&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 02&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i"&gt;Settings and Database&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 03&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e"&gt;API Implementation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Part 04&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tests + Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 05&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6"&gt;Swagger Documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;It is expected that from this fourth part you will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use of Junit&lt;/li&gt;
&lt;li&gt;Creation of Unit Tests&lt;/li&gt;
&lt;li&gt;Creation of Integration Tests&lt;/li&gt;
&lt;li&gt;Using Fakers to create test data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that in this tutorial the following tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;IntelliJ&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;MySQL database&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 01 - Creating test properties&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Usually when we have to test our application, we create a properties file dedicated to the tests. This is done to have a better organization of development and test environments.&lt;br&gt;
So, inside &lt;code&gt;resources&lt;/code&gt; you can create a new file called &lt;code&gt;application-test.properties&lt;/code&gt; which will contain the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
spring.datasource.url=jdbc:mysql://localhost:3307/small_library_test
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first three items are responsible of the database connection. Note that a new database (&lt;code&gt;small_library_test&lt;/code&gt;) has been created for the tests but if you want, you can use the same database used for development.&lt;br&gt;
The last item is present to avoid the &lt;code&gt;LazyInitializationException&lt;/code&gt; exception.&lt;/p&gt;

&lt;p&gt;Therefore, when we create our tests, they will be using the properties defined in this new file.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Step 02 - Exception Handlers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By default, Spring handles some exceptions through classes, such as &lt;code&gt;EntityNotFoundException&lt;/code&gt; and &lt;code&gt;EmptyResultDataAccessException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first case happens when the user tries to search for an object in the database that does not exist, for example they would like to find a book whose id is equal to 9999999999 (thinking about the case in which this id does not exist in the database). By default, it returns error 500 (bad request) along with the exception body.&lt;/p&gt;

&lt;p&gt;But let's think that in this case instead of returning the error 500, we would like to return the error 404 (Not Found). How can we carry out this modification?&lt;/p&gt;

&lt;p&gt;That's why there is the &lt;code&gt;RestControllerAdvice&lt;/code&gt;, it is used for handling exceptions in controllers. For its creation, you'll have to go to the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package and create a new package called &lt;code&gt;exception&lt;/code&gt;. And inside this, create a class called &lt;code&gt;ErrorHandler&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.exception;

import jakarta.persistence.EntityNotFoundException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.simplelibrary.simplelibraryAPI.dto.ErrorValidatorDTO;

@RestControllerAdvice
public class ErrorHandler {
    @ExceptionHandler({EntityNotFoundException.class, EmptyResultDataAccessException.class})
    public ResponseEntity error404(){
        return ResponseEntity.notFound().build();
    }


    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity error400(MethodArgumentNotValidException exception){
        var erros = exception.getFieldErrors();
        return ResponseEntity.badRequest().body(erros.stream().map(ErrorValidatorDTO::new).toList());
    }



}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order for Spring to recognize that class as a Rest Controller Advice, you must place the &lt;code&gt;@RestControllerAdvice&lt;/code&gt; annotation before the class initialization.&lt;/p&gt;

&lt;p&gt;For each exception you want to handle, you must put it inside the &lt;code&gt;@ExceptionHandler&lt;/code&gt; annotation saying that that exception will be handled inside the next method.&lt;br&gt;
Note that the &lt;code&gt;error404&lt;/code&gt; method will handle exceptions that normally throw the 500 error and cause them to throw the 404 error.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;error400&lt;/code&gt; method will handle the exception MethodArgumentNotValidException. This exception is triggered when there is a validation error, for example, when the user tries to register a book without its title. Originally, the response he will receive is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
    "timestamp": "2023-01-27T19:04:03.372+00:00",
    "status": 400,
    "error": "Bad Request",
    "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.simplelibrary.simplelibraryAPI.controller.BookController.store(com.simplelibrary.simplelibraryAPI.dto.BookRequestDTO,org.springframework.web.util.UriComponentsBuilder) throws java.io.IOException: [Field error in object 'bookRequestDTO' on field 'title': rejected value [null]; codes [NotBlank.bookRequestDTO.title,NotBlank.title,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [bookRequestDTO.title,title]; arguments []; default message [title]]; default message [não deve estar em branco]] \r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:144)\r\n\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:181)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:148)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1010)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:913)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:731)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:884)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:833)\r\n",
    "message": "Validation failed for object='bookRequestDTO'. Error count: 1",
    "errors": [
        {
            "codes": [
                "NotBlank.bookRequestDTO.title",
                "NotBlank.title",
                "NotBlank.java.lang.String",
                "NotBlank"
            ],
            "arguments": [
                {
                    "codes": [
                        "bookRequestDTO.title",
                        "title"
                    ],
                    "arguments": null,
                    "defaultMessage": "title",
                    "code": "title"
                }
            ],
            "defaultMessage": "must not be blank",
            "objectName": "bookRequestDTO",
            "field": "title",
            "rejectedValue": null,
            "bindingFailure": false,
            "code": "NotBlank"
        }
    ],
    "path": "/books"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Realize the amount of information that is sent to the user, when in fact we just want them to know which field is with the  error and what the error message is. Therefore, we will carry out your treatment through a DTO.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API.dto&lt;/code&gt; package we will create a record called &lt;code&gt;ErrorValidatorDTO&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.dto;
import org.springframework.validation.FieldError;
public record ErrorValidatorDTO(String field, String message){
    public ErrorValidatorDTO(FieldError error){
        this(error.getField(), error.getDefaultMessage());
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there we will get the error object and return to the user only the necessary information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[
    {
        "field": "title",
        "message": "must not be blank"
    }
]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Step 03 - Book Factory&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For our tests it will be necessary to create several books with different information. Carrying out this manual work is a bit exhausting, so we can use mechanisms created by the community.&lt;/p&gt;

&lt;p&gt;One of the mechanisms we will use is &lt;code&gt;Faker&lt;/code&gt;. From it, we will be able to generate random values for the fields and create our book object. For that, you'll need to import the following dependency into your &lt;code&gt;pom.xml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.github.javafaker&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;javafaker&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;1.0.2&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this we can create the &lt;code&gt;BookFactory&lt;/code&gt; class that will be responsible for creating book objects (DAO and DTO request models):&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API.factory&lt;/code&gt; package we will create a class called &lt;code&gt;BookFakerFactory&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.factory;

import com.github.javafaker.Faker;
import com.simplelibrary.simplelibraryAPI.dto.BookRequestDTO;
import com.simplelibrary.simplelibraryAPI.model.Book;

public class BookFakerFactory {

    private Faker faker;

    public BookFakerFactory(){
        this.faker = new Faker();
    }

    public BookRequestDTO createBook(){
        var book = new BookRequestDTO(faker.book().title(), faker.book().author(),
                faker.number().randomDigit(), faker.number().digits(13), faker.number().randomDouble(1,1,10),
                faker.random().nextBoolean());

        return book;
    }

    public BookRequestDTO createBook(Book bookCreated){
        var book = new BookRequestDTO(bookCreated);
        return book;
    }

    public Book createBookModel(){
        var bookDTO = new BookRequestDTO(faker.book().title(), faker.book().author(),
                faker.number().randomDigit(), faker.number().digits(13), faker.number().randomDouble(1,1,10),
                faker.random().nextBoolean());

        var book = new Book(bookDTO);
        return book;
    }



    public BookRequestDTO createBookIncomplete(){
        var book = new BookRequestDTO(faker.book().title(), "",
                faker.number().randomDigit(), faker.number().digits(13), faker.number().randomDouble(1,1,10),
                faker.random().nextBoolean());

        return book;
    }

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we have 4 methods and the objective of all is to create an object that will later be used in tests.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;createBook&lt;/code&gt; method will create a &lt;code&gt;BookRequestDTO&lt;/code&gt; object that will be used to test requests.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;createBook&lt;/code&gt; method (with parameter) will create a &lt;code&gt;BookRequestDTO&lt;/code&gt; object from a previously created book.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;createBookModel&lt;/code&gt; method will create a &lt;code&gt;Book&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;createBookIncomplete&lt;/code&gt; method will create a &lt;code&gt;BookRequestDTO&lt;/code&gt; object without author information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that all methods use the &lt;code&gt;Faker&lt;/code&gt; library.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 04 - Unit Tests&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are ready to create our tests. If you look inside the &lt;code&gt;test&lt;/code&gt; package, there is already a class called &lt;code&gt;SimplelibraryApiApplicationTests&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SimplelibraryApiApplicationTests {


    @Test
    void contextLoads() throws Exception {


    }

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will use &lt;code&gt;JUnit&lt;/code&gt; for testing.&lt;/p&gt;

&lt;p&gt;Note some annotations that are important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@SpringBootTest&lt;/code&gt; indicates that that class will contain methods that should be tested.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Test&lt;/code&gt; indicates that that method should be run as a test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we can create our first unit test. This one will test some features of our repository: inside the &lt;code&gt;src.main.test.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package we will create a package called &lt;code&gt;unit&lt;/code&gt; and inside it a class called &lt;code&gt;BookTest&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.unit;

import com.simplelibrary.simplelibraryAPI.factory.BookFakerFactory;
import com.simplelibrary.simplelibraryAPI.repository.BookRepository;
import com.simplelibrary.simplelibraryAPI.service.BookService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.assertj.core.api.Assertions.*;
import java.io.IOException;

@SpringBootTest
@ActiveProfiles("test")
public class BookTest {

    @Autowired
    private BookRepository repository;

    @Autowired
    private BookService service;

    private BookFakerFactory bookFakerFactory;

    public BookTest() {
        this.bookFakerFactory = new BookFakerFactory();
    }



}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;@ActiveProfiles("test")&lt;/code&gt; annotation. It is used to inform Spring that we are using the properties defined inside the &lt;code&gt;application-test.properties&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;We can think of some tests to be done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Test for successfully creating a book.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test to verify if the service of collecting the rating of a given book is working correctly (verifying that the rating value is populated when it is from an existing book and that it is not populated with a non-existing book).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The class with all the tests looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.unit;

import com.simplelibrary.simplelibraryAPI.factory.BookFakerFactory;
import com.simplelibrary.simplelibraryAPI.repository.BookRepository;
import com.simplelibrary.simplelibraryAPI.service.BookService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.assertj.core.api.Assertions.*;
import java.io.IOException;

@SpringBootTest
@ActiveProfiles("test")
public class BookTest {

    @Autowired
    private BookRepository repository;

    @Autowired
    private BookService service;

    private BookFakerFactory bookFakerFactory;

    public BookTest() {
        this.bookFakerFactory = new BookFakerFactory();
    }

    @Test
    public void itShouldCreateABookSuccessfully(){
        var book = bookFakerFactory.createBookModel();
        repository.save(book);

        var bookFinder = repository.findBookByisbn(book.getIsbn());

        Assertions.assertThat(book).isEqualTo(bookFinder);
    }

    @Test
    public void itShouldFillTheRatingValueFromExistingBook() throws IOException {
        var book = bookFakerFactory.createBookModel();
        book.setTitle("Harry Potter and the Philosopher's Stone");

        var bookCreated = service.store(bookFakerFactory.createBook(book));

        assertThat(bookCreated.getRate()).isNotNull()
                .isNotZero()
                .isGreaterThan(Double.valueOf(0));

    }

    @Test
    public void itShouldNotFillTheRatingValueFromNonexistentBook() throws IOException {
        var book = bookFakerFactory.createBookModel();
        book.setTitle("blablablablablabla");

        var bookCreated = service.store(bookFakerFactory.createBook(book));

        assertThat(bookCreated.getRate()).isZero();

    }



}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of the &lt;code&gt;assertThat&lt;/code&gt; method present in JUnit, which allows checking values.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 05 - Integration tests&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We can now create the integration test that will allow us to test our system's routes. We will also check if the requests are returned correctly and if the http codes also match expectations. &lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src.main.test.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package we will create a package called &lt;code&gt;integration&lt;/code&gt; and inside it a class called &lt;code&gt;BookControllerTest&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.integration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.simplelibrary.simplelibraryAPI.factory.BookFakerFactory;
import com.simplelibrary.simplelibraryAPI.repository.BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;

import static org.junit.jupiter.api.Assertions.assertNotNull;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.assertj.core.api.Assertions.*;
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class BookControllerTest {

@Autowired
    private MockMvc mockMvc;

    @Autowired
    private BookRepository repository;

    private BookFakerFactory bookFakerFactory;

    public BookControllerTest() {
        this.bookFakerFactory = new BookFakerFactory();
    }


} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of a new annotation: &lt;code&gt;@AutoConfigureMockMvc&lt;/code&gt; from it we will be able to use the injected &lt;code&gt;MockMvc&lt;/code&gt; class to make requests to our server.&lt;/p&gt;

&lt;p&gt;We can think of the following test cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verification if a book is successfully created&lt;/li&gt;
&lt;li&gt;Verification if a book is not created when we don't send all the necessary fields (http code 400)&lt;/li&gt;
&lt;li&gt;Verification if all books are successfully listed&lt;/li&gt;
&lt;li&gt;Verification if the information of a single book appears successfully.&lt;/li&gt;
&lt;li&gt;Verification if a book's information is changed successfully&lt;/li&gt;
&lt;li&gt;Verification that a book's information is not successfully changed when its information is not submitted.&lt;/li&gt;
&lt;li&gt;Verification if a book is successfully deleted.&lt;/li&gt;
&lt;li&gt;Verification that a non-existent book is not deleted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The class with all implemented methods looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.integration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.simplelibrary.simplelibraryAPI.factory.BookFakerFactory;
import com.simplelibrary.simplelibraryAPI.repository.BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;

import static org.junit.jupiter.api.Assertions.assertNotNull;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.assertj.core.api.Assertions.*;
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class BookControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private BookRepository repository;

    private BookFakerFactory bookFakerFactory;

    public BookControllerTest() {
        this.bookFakerFactory = new BookFakerFactory();
    }

    @Test
    void testIfBookIsCreatedSuccessfully() throws Exception {
        var book = this.bookFakerFactory.createBook();

        var result = this.mockMvc.perform(post("/books")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(asJsonString(book)))
                .andExpect(status().isCreated())
                .andReturn();

        String content = result.getResponse().getContentAsString();
        assertNotNull(content);

    }

    @Test
    void testIfBookIsNotCreatedWithMissingAttributes() throws Exception{
        var book = this.bookFakerFactory.createBookIncomplete();
        this.mockMvc.perform(post("/books")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(asJsonString(book)))
                .andExpect(status().isBadRequest())
                .andReturn();

    }

    @Test
    void testIfAllBooksAreListedSuccessfully() throws Exception{
        this.mockMvc.perform(get("/books"))
                .andExpect(status().isOk())
                .andReturn();
    }

    @Test
    void testIfSingleBookInformationIsShown() throws  Exception {
        this.mockMvc.perform(get("/books"))
                .andExpect(status().isOk())
                .andReturn();
    }

    @Test
    void testIfBookIsUpdatedSuccessfully() throws Exception{
        var book = this.bookFakerFactory.createBookModel();
        var bookCreated = repository.save(book);

        book.setAuthor("New Author name");

        var book2 = this.bookFakerFactory.createBook(book);

        this.mockMvc.perform(put("/books/{id}",bookCreated.getId())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(asJsonString(book2)))
                .andExpect(status().isOk())
                .andReturn();

        var bookUpdated = repository.getReferenceById(bookCreated.getId());

        assertThat(bookUpdated.getId()).isEqualTo(bookCreated.getId());
        assertThat(bookUpdated.getAuthor()).isNotEqualTo(bookCreated.getAuthor());


    }

    @Test
    void testIfBookIsNotUpdatedSuccessfully() throws Exception{
        var book = this.bookFakerFactory.createBookModel();
        var bookCreated = repository.save(book);


        this.mockMvc.perform(put("/books/{id}",bookCreated.getId()))
                .andExpect(status().isBadRequest())
                .andReturn();


    }

    @Test
    void testIfBookIsDeletedSuccessfully() throws Exception{
        var book = this.bookFakerFactory.createBookModel();
        var bookCreated = repository.save(book);
        this.mockMvc.perform(delete("/books/"+bookCreated.getId()))
                .andExpect(status().isNoContent())
                .andReturn();
    }

    @Test
    void testIfBookIsNotDeletedSuccessfully() throws Exception{
        this.mockMvc.perform(delete("/books/999999"))
                .andExpect(status().isNotFound())
                .andReturn();

    }

    public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of the &lt;code&gt;asJsonString&lt;/code&gt; method. It is used to take all the attribute values of an object and transform it into a Json string.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 06 - Running the tests&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To run the tests you will have to go to the terminal and type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
\.mvnw test

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this you will inform maven that you want to run all the tests in your application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmholdx2yr2rcjifmujlt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmholdx2yr2rcjifmujlt.png" alt="Tests being executed" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If all tests run successfully, you will see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4umjyqfmao0c7qbm9oxa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4umjyqfmao0c7qbm9oxa.png" alt="Tests run successfully" width="477" height="135"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 07 - Test Coverage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Finally, many times when we do tests we would like to understand how broad it was. We would like to reach as many classes and methods as possible in our project, thus avoiding letting any part go unnoticed.&lt;/p&gt;

&lt;p&gt;We can use the &lt;strong&gt;JaCoCo&lt;/strong&gt; plugin to check test coverage. Its documentation is present &lt;a href="https://www.jacoco.org/jacoco/" rel="noopener noreferrer"&gt;at this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To use it, you'll need to go to your &lt;code&gt;pom.xml&lt;/code&gt; file and add the following &lt;code&gt;plugin&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;plugin&amp;gt;
   &amp;lt;groupId&amp;gt;org.jacoco&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jacoco-maven-plugin&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;0.8.8&amp;lt;/version&amp;gt;
   &amp;lt;executions&amp;gt;
      &amp;lt;execution&amp;gt;
         &amp;lt;goals&amp;gt;
            &amp;lt;goal&amp;gt;prepare-agent&amp;lt;/goal&amp;gt;
         &amp;lt;/goals&amp;gt;
      &amp;lt;/execution&amp;gt;
      &amp;lt;execution&amp;gt;
         &amp;lt;id&amp;gt;report&amp;lt;/id&amp;gt;
         &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;
         &amp;lt;goals&amp;gt;
            &amp;lt;goal&amp;gt;report&amp;lt;/goal&amp;gt;
         &amp;lt;/goals&amp;gt;
      &amp;lt;/execution&amp;gt;
   &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just that! Now you can rerun your tests and when they are finished a &lt;code&gt;.html&lt;/code&gt; file will be generated inside &lt;code&gt;target.site.jacoco&lt;/code&gt;. The file is &lt;code&gt;index.html&lt;/code&gt; and when accessing it you will have a screen similar to this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycan806qud8dqr75uxtk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycan806qud8dqr75uxtk.png" alt="JaCoCo's initial screen" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the &lt;code&gt;com.simplelibrary.simplelibraryAPI.model&lt;/code&gt; package had 70% of coverage. For more information, you can click on the package and then on the desired class to have the following coverage view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rfq1wjrpyj4cff7e4d2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rfq1wjrpyj4cff7e4d2.png" alt="Book coverage" width="730" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Green means that the code snippet was called.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, you can use the plugin and add new tests so that the coverage value of a given class is as high as possible!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What we learned in this tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this third part, we learned how to perform unit and integration tests using JUnit. We also saw how we can check test coverage using the JaCoCo plugin.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6"&gt;next part&lt;/a&gt; you will see about project documentation using Swagger.&lt;/p&gt;

&lt;p&gt;Remembering that the complete project can be found &lt;a href="https://github.com/franciscotis/simple-library-api" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Creating a REST API using Spring Boot + Tests + Documentation [part 03]</title>
      <dc:creator>Francisco Pereira</dc:creator>
      <pubDate>Wed, 01 Feb 2023 18:16:31 +0000</pubDate>
      <link>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e</link>
      <guid>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e</guid>
      <description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Part&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Part 01&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262"&gt;Application Startup&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 02&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i"&gt;Settings and Database&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Part 03&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;API Implementation&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 04&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;Tests + Coverage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 05&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6"&gt;Swagger Documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;It is expected that from this third part you will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to create a service containing the system's business rule&lt;/li&gt;
&lt;li&gt;How to create the controllers containing the system's routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that in this tutorial the following tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;IntelliJ&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;MySQL database&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 01 - Creating the service&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We created the Book class repository which will allow us to perform the necessary manipulations in the database (inserting, deleting, editing and viewing data, for example).&lt;/p&gt;

&lt;p&gt;Now we can implement the system's business rule, this implementation can be done directly in &lt;code&gt;Controller&lt;/code&gt; where we will have access routes to the system. But in doing so we are not following the &lt;em&gt;Single Responsibility Principle&lt;/em&gt;. Therefore, Spring Boot indicates the creation of a &lt;strong&gt;service&lt;/strong&gt; for the implementation of the business rule.&lt;/p&gt;

&lt;p&gt;To create the service, we'll go into the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package and create a new package called &lt;code&gt;service&lt;/code&gt;. And inside of this, we create an interface called &lt;code&gt;BookService&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.simplelibrary.simplelibraryAPI.service;

import com.simplelibrary.simplelibraryAPI.dto.BookRequestDTO;
import com.simplelibrary.simplelibraryAPI.dto.BookResponseDTO;
import com.simplelibrary.simplelibraryAPI.model.Book;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.io.IOException;

public interface BookService {
    public Page&amp;lt;BookResponseDTO&amp;gt; getAllBooks(Pageable pagination);

    public BookResponseDTO show(Long id);

    public Book store(BookRequestDTO book) throws IOException;

    public BookResponseDTO update(Long id, BookRequestDTO book);

    public void delete(Long id);

    public long count();

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;getAllBooks&lt;/code&gt; method will be used to get all the books in the database. It will receive as a parameter an object of type &lt;code&gt;Pageable&lt;/code&gt; which is responsible for pagination. Later when we implement the route, we'll talk about this class. Finally, it will return an object of type &lt;code&gt;Page&lt;/code&gt; that will contain the contents of the &lt;code&gt;BookResponseDTO&lt;/code&gt; class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;show&lt;/code&gt; method will be used to get the information of only 1 book. It will receive the id of this book as a parameter and return the &lt;code&gt;BookResponseDTO&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;store&lt;/code&gt; method will be used to store a book in the database. It will receive the information from the &lt;code&gt;BookRequestDTO&lt;/code&gt; and return the &lt;code&gt;Book&lt;/code&gt;. In its implementation we will talk more about this return.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;update&lt;/code&gt; method will be used to update the book information. It will receive the id of the book and its information (&lt;code&gt;BookRequestDTO&lt;/code&gt;) and will return the &lt;code&gt;BookResponseDTO&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;delete&lt;/code&gt; method will be used to delete a book from the database. For this we only need your id.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;count&lt;/code&gt; method will be used to check how many books have been registered in the database. A long value will be returned.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After creating the interface, we can now create its implementation. For that, we'll go into the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API.service&lt;/code&gt; package and create a new package called &lt;code&gt;impl&lt;/code&gt;. And inside this, we create an interface called &lt;code&gt;BookServiceImpl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Initially the class will have the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.stereotype.Service;
import com.simplelibrary.simplelibraryAPI.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class BookServiceImpl implements BookService {

@Autowired
    private BookRepository bookRepository;

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we are creating the implementation of a service, we need to insert the &lt;code&gt;@Service&lt;/code&gt; annotation at the beginning of the class. By doing this, Spring will understand that this class is indeed a Service.&lt;/p&gt;

&lt;p&gt;And notice the &lt;code&gt;@Autowired&lt;/code&gt; annotation it is used for &lt;strong&gt;dependency injection&lt;/strong&gt;. We want to inject the &lt;code&gt;BookRepository&lt;/code&gt; to be used in your database manipulation methods. Therefore, we need to inform the &lt;code&gt;@Autowired&lt;/code&gt; annotation before its declaration so that Spring can be taking care of this dependency.&lt;/p&gt;

&lt;p&gt;Once this is done, we can implement the methods that belong to the interface we created earlier:&lt;/p&gt;

&lt;h3&gt;
  
  
  getAllBooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
public Page&amp;lt;BookResponseDTO&amp;gt; getAllBooks(Pageable pagination){
        var page = bookRepository.findAll(pagination).map(BookResponseDTO::new);
        return page;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository has a method called &lt;code&gt;findAll&lt;/code&gt; which will return all the books present in the database. It can receive a Pageable object as a parameter that will contain the paging information (trust me, we'll talk more about how this object is built later).&lt;/p&gt;

&lt;p&gt;This result, by default, will return objects of type &lt;code&gt;Book&lt;/code&gt; (DAO), because in the declaration of the repository we inform in the generics that it is of type &lt;code&gt;Book&lt;/code&gt;. However, we previously defined that the return to the user has to be of type &lt;code&gt;BookResponseDTO&lt;/code&gt;. Therefore, we will make a &lt;code&gt;map&lt;/code&gt; to call the &lt;code&gt;BookResponseDTO&lt;/code&gt; constructor that will receive data from an object of type &lt;code&gt;Book&lt;/code&gt; and fill in its attributes.&lt;/p&gt;

&lt;p&gt;Finally, we will return the result that has been found.&lt;/p&gt;

&lt;h3&gt;
  
  
  show
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  @Override
    public BookResponseDTO show(Long id) {
        return new BookResponseDTO(bookRepository.getReferenceById(id));
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;show&lt;/code&gt; method is quite simple to understand.&lt;br&gt;
 We will use the &lt;code&gt;getReferenceById&lt;/code&gt; method that will return a &lt;code&gt;Book&lt;/code&gt; type object based on its id. Finally, we do the conversion to &lt;code&gt;BookResponseDTO&lt;/code&gt; by calling its constructor.&lt;/p&gt;
&lt;h3&gt;
  
  
  store
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
    public Book store(BookRequestDTO bookRequest) throws IOException {
        var book = new Book(bookRequest);
        book.setRate(this.scrapRatings(book.getTitle()));
        bookRepository.save(book);
        return book;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;store&lt;/code&gt; method is used to store a book in the database. Notice that in the first line, a &lt;code&gt;Book&lt;/code&gt; object is created and passed in its constructor the &lt;code&gt;bookRequest&lt;/code&gt; object. Therefore, you will create the constructor inside the &lt;code&gt;Book&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 public Book(BookRequestDTO bookRequest){
        this.title = bookRequest.title();
        this.author = bookRequest.author();
        this.pages = bookRequest.pages();
        this.isbn = bookRequest.isbn();
        this.rate = bookRequest.rate();
        this.finished = bookRequest.finished();
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we make the logic for filling in the value of the book's rate. As presented in the system scenario, this attribute will be filled according to what is found on the site &lt;a href="http://www.skoob.com.br" rel="noopener noreferrer"&gt;http://www.skoob.com.br&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To extract data from the web (web scraping) I am using the Jsoup library. You can go to your pom.xml file and import it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;            
   &amp;lt;groupId&amp;gt;org.jsoup&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jsoup&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;1.15.3&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;scrapRatings&lt;/code&gt; method will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
private Double scrapRatings(String title) {
        Double rating = Double.valueOf(0);
        try{
            String titleEdited = title.replace(" ","-");
            Document doc = Jsoup.connect("https://www.skoob.com.br/"+titleEdited).get();
            Elements info = doc.select( "div#resultadoBusca")
                    .select("div.box_lista_busca_vertical")
                    .select("div.detalhes")
                    .select("a");
            Element firstBook = info.first();
            if(firstBook != null){
                Document book = Jsoup.connect("https://www.skoob.com.br/"+firstBook.attr("href")).get();
                Elements ratingElement = book.select("div#pg-livro-box-rating")
                        .select("span.rating");
                rating = Double.parseDouble(ratingElement.text());
            }
        }catch (Exception e){
        }
        finally {
            return rating;
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I won't go into much detail about Jsoup, but basically it will access a web page and return its html content where we can get its data. &lt;br&gt;
The &lt;code&gt;scrapRatings&lt;/code&gt; method will search the desired site based on the book title. And will return your evaluation. If the book is not found, your evaluation will be reset to zero.&lt;/p&gt;

&lt;p&gt;If you want to know more about the Jsoup, you can go to this link: &lt;a href="https://jsoup.org" rel="noopener noreferrer"&gt;https://jsoup.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going back to the book insert method, after getting the book rating value, we can call the &lt;code&gt;save&lt;/code&gt; method of the repository. This method will perform data persistence. Finally, we return the book that was created.&lt;/p&gt;
&lt;h3&gt;
  
  
  update
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Override
    public BookResponseDTO update(Long id, BookRequestDTO bookRequest) {
        var book = bookRepository.getReferenceById(id);
        book.update(bookRequest);
        return new BookResponseDTO(book);


    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The update method will look for a book based on its id (using the &lt;code&gt;getReferenceById&lt;/code&gt; method) and based on the data sent by the user, it will update them inside the Book object. So let's go back to the &lt;code&gt;Book&lt;/code&gt; class and add the &lt;code&gt;update&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public void update(BookRequestDTO bookRequest){
        this.title = bookRequest.title();
        this.author = bookRequest.author();
        this.pages = bookRequest.pages();
        this.isbn = bookRequest.isbn();
        this.rate = bookRequest.rate();
        this.finished = bookRequest.finished();
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we return the response DTO.&lt;/p&gt;

&lt;h3&gt;
  
  
  delete
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Override
    public void delete(Long id) {
        bookRepository.deleteById(id);
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;delete&lt;/code&gt; method will only call the &lt;code&gt;deleteById&lt;/code&gt; method that belongs to the book repository. In this method we don't need to return anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  count
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
public long count(){
        return bookRepository.count();
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;count&lt;/code&gt; method will return the &lt;code&gt;count&lt;/code&gt; method which belongs to the book's repository.&lt;/p&gt;

&lt;p&gt;Well done! We finalized the implementation of the business rule from the repository. We can go to the last step which is creating the routes that will call the repository!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 02 - Implementing the Route Controller&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We arrived at the last step of creating our API. So far we have created our DAO class and the DTO records. The first one will serve as a base for the repository to carry out manipulations in the database. The second one will be used for data input and output.&lt;/p&gt;

&lt;p&gt;In addition, we also created the Service that will contain the implementation of our system's business rule.&lt;/p&gt;

&lt;p&gt;Now we can create the route controller. &lt;/p&gt;

&lt;p&gt;Just like we did earlier in creating a controller to present a simple message to the user when accessing a route, we'll create a robust controller.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;controller&lt;/code&gt; package you will create a class called &lt;code&gt;BookController&lt;/code&gt; which will have the following initial body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.simplelibrary.simplelibraryAPI.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("books")
public class BookController {

@Autowired
private BookService bookService;


} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time we are injecting the &lt;code&gt;BookService&lt;/code&gt; so we can use the methods we created earlier. If you noticed, we are importing the &lt;strong&gt;interface&lt;/strong&gt; we created and not the implementation. But don't worry, Spring will automatically recognize the implementation we made from the interface.&lt;/p&gt;

&lt;p&gt;We have to create the following routes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;HTTP Method&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;books&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/books/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/books&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;/books/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/books/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Route to get all books:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping
public ResponseEntity&amp;lt;Page&amp;lt;BookResponseDTO&amp;gt;&amp;gt; getAllBooks(@PageableDefault(size=10, sort={"title"}) Pageable pagination) throws IOException {
    var page = bookService.getAllBooks(pagination);
    return ResponseEntity.ok(page);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route to get all the books will be accessed through a GET request on the URL &lt;a href="http://localhost:8080/books" rel="noopener noreferrer"&gt;http://localhost:8080/books&lt;/a&gt;. When performing the request, the &lt;code&gt;getAllBooks&lt;/code&gt; method will be called.&lt;/p&gt;

&lt;p&gt;Note that in the method's signature we are adding an object of type &lt;code&gt;Pageable&lt;/code&gt; called pagination in the parameter. Associated with it there is the signature &lt;code&gt;@PageableDefault(size=10, sort={"title"})&lt;/code&gt;, this object will allow us to define the pagination properties of my result (we passed this object inside the Service, remember?).&lt;/p&gt;

&lt;p&gt;We are injecting the &lt;code&gt;Pageable&lt;/code&gt; inside our method, we don't need to worry about creating your object or anything, Spring will do it for you! As per the project requirements we have the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to get all the books registered in the system through pagination. Having only 10 books per page and sorting by title.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are placing inside the annotation the &lt;code&gt;size&lt;/code&gt; properties in which we specify how many books we want to be displayed per page. And the &lt;code&gt;sort&lt;/code&gt; property which specifies what the ordering criteria will be, in this case it is &lt;code&gt;title&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will call the &lt;code&gt;getAllBooks&lt;/code&gt; method of the Service we implemented and finally we return the &lt;code&gt;ResponseEntity&lt;/code&gt; with the http code response 200, and the pagination in its body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route to get the information of a single book:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping("/{id}")
public ResponseEntity show(@PathVariable Long id){
    var book = bookService.show(id);
    return ResponseEntity.ok(book);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route to get the information of a single book will be accessed through a GET request on the URL &lt;a href="http://localhost:8080/books/%7Bid%7D" rel="noopener noreferrer"&gt;http://localhost:8080/books/{id}&lt;/a&gt;. When performing the request, the &lt;code&gt;show&lt;/code&gt; method will be called.&lt;/p&gt;

&lt;p&gt;Note that for us to know which book the user would like to see the information, they need to specify the id. Therefore, the value of their id is passed in the URL. For this value to be recognized, we put the &lt;code&gt;@PathVariable&lt;/code&gt; annotation in the parameters of the method and then its type and the variable where its value will be stored.&lt;/p&gt;

&lt;p&gt;We will call the &lt;code&gt;show&lt;/code&gt; method of the service and return the &lt;code&gt;ResponseEntity&lt;/code&gt; with the http code 200.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route to store a book
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@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);
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path to store a book will be accessed via a POST request to the URL &lt;a href="http://localhost:8080/books/" rel="noopener noreferrer"&gt;http://localhost:8080/books/&lt;/a&gt;. When performing the request, the &lt;code&gt;store&lt;/code&gt; method will be called.&lt;/p&gt;

&lt;p&gt;In this method, the user will send in the body of the request (&lt;code&gt;@RequestBody&lt;/code&gt;) the fields that we inform in the &lt;code&gt;BookRequestDTO&lt;/code&gt; record and where we put all the validations. For these validations to be "called" we need to put the &lt;code&gt;@Valid&lt;/code&gt; annotation.&lt;br&gt;
We are also injecting the &lt;code&gt;UriComponentsBuilder&lt;/code&gt; into the parameters, which will be used in the response return.&lt;/p&gt;

&lt;p&gt;If all validations are successful, the &lt;code&gt;store&lt;/code&gt; method of the Service will be called and the &lt;code&gt;book&lt;/code&gt; object will be returned.&lt;br&gt;
It is a good API practice, when storing an object in the database, to add a URL to the response headers where the user can access to obtain information about the object that was created. This URL is obtained from the following snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var uri = uriBuilder.path("/books/{id}").buildAndExpand(book.getId()).toUri();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, it is also a good practice to fully return the object that was created in the request body. Therefore, we will not return a DTO object, but a &lt;code&gt;Book&lt;/code&gt; type object. In addition to returning status 201 (created).&lt;/p&gt;

&lt;h3&gt;
  
  
  Route to update a book
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@PutMapping("/{id}")
    public ResponseEntity update(@PathVariable Long id, @RequestBody @Valid BookRequestDTO bookRequest){
    var book = bookService.update(id, bookRequest);
    return ResponseEntity.ok(book);

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route to update a book will be accessed through a PUT request in the URL &lt;a href="http://localhost:8080/books/id" rel="noopener noreferrer"&gt;http://localhost:8080/books/id&lt;/a&gt;. When performing the request, the &lt;code&gt;update&lt;/code&gt; method will be called.&lt;/p&gt;

&lt;p&gt;This method is similar to the &lt;code&gt;store&lt;/code&gt; method, only this time the user has to pass the book's id in the URL.&lt;/p&gt;

&lt;p&gt;After calling the &lt;code&gt;update&lt;/code&gt; method of the service, we will return the updated book with http status 200.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route to delete a book
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@DeleteMapping("/{id}")
    public ResponseEntity delete(@PathVariable Long id){
    bookService.delete(id);
    return ResponseEntity.noContent().build();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route to delete a book will be accessed through a DELETE request in the URL &lt;a href="http://localhost:8080/books/id" rel="noopener noreferrer"&gt;http://localhost:8080/books/id&lt;/a&gt;. When performing the request, the &lt;code&gt;delete&lt;/code&gt; method will be called.&lt;/p&gt;

&lt;p&gt;This method only receives the id of the book and later the &lt;code&gt;delete&lt;/code&gt; method of the service will be called where the book will be successfully deleted.&lt;/p&gt;

&lt;p&gt;In this case, we are returning http code 204 (no content).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What we learned in this tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Well done! We have finished creating our Rest API using Spring Boot. You can use Insomnia to test the requests and see if everything is working as expected.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;next part&lt;/a&gt; of the tutorial, you will learn how to create unit and integration tests on your application!&lt;/p&gt;

&lt;p&gt;You can find the full project &lt;a href="https://github.com/franciscotis/simple-library-api" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Creating a REST API using Spring Boot + Tests + Documentation [part 02]</title>
      <dc:creator>Francisco Pereira</dc:creator>
      <pubDate>Wed, 01 Feb 2023 18:16:29 +0000</pubDate>
      <link>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i</link>
      <guid>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i</guid>
      <description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Part&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Part 01&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262"&gt;Application Startup&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Part 02&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Settings and Database&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 03&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e"&gt;API Implementation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 04&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;Tests + Coverage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 05&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6"&gt;Swagger Documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;It is expected that from this second part you will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to create the system routes&lt;/li&gt;
&lt;li&gt;How to view the system through user stories&lt;/li&gt;
&lt;li&gt;How to view the system through ER diagram&lt;/li&gt;
&lt;li&gt;How to create the database&lt;/li&gt;
&lt;li&gt;How to integrate the database with the system&lt;/li&gt;
&lt;li&gt;How to create migrations using &lt;code&gt;flyway&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How to create DAO classes&lt;/li&gt;
&lt;li&gt;How to create a repository to interact with the database&lt;/li&gt;
&lt;li&gt;How to create DTO records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that in this tutorial the following tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;IntelliJ&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;MySQL database&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 01 - Creating routes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262"&gt;first part&lt;/a&gt; of the tutorial we created the project using &lt;em&gt;Spring Initializr&lt;/em&gt; and ran the server. It turns out that when accessing the URL &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; we come across the following response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
    "timestamp": "2023-01-31T18:08:42.607+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This response, as shown earlier, appears because we have not defined any route for our application.&lt;/p&gt;

&lt;p&gt;So let's create our route!&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package we will create a new package called &lt;code&gt;controller&lt;/code&gt;. Inside it, we will store the &lt;em&gt;Controllers&lt;/em&gt; of the system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Inside a controller we will have the mapping of our application's routes. Thus, when defining a route, such as "/test", when the user accesses the url &lt;a href="http://localhost:8080/test" rel="noopener noreferrer"&gt;http://localhost:8080/test&lt;/a&gt;, he will no longer find the response seen above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The class that we will create in this controller will have the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.simplelibrary.simplelibraryAPI.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("test")
public class SimpleRouteController {

    @GetMapping
    public ResponseEntity test(){
        return ResponseEntity.ok("it works!");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first lines we see some imports that are necessary for the project. Also note that some &lt;strong&gt;annotations&lt;/strong&gt; are used, such as &lt;code&gt;@RequestController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;According to Spring's own documentation, this annotation means that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[...] Marks the class as a controller where every method returns a domain object instead of a view.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next annotation, &lt;code&gt;RequestMapping("test")&lt;/code&gt; indicates that all requests that have the /test mapping will be handled in this class. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@GetMapping&lt;/code&gt; annotation indicates that the method below it will handle a &lt;strong&gt;get&lt;/strong&gt; type request. That is, if the user accesses the URL &lt;a href="http://localhost:8080/test" rel="noopener noreferrer"&gt;http://localhost:8080/test&lt;/a&gt; (using the HTTP GET method), the method below will be called. The method itself is &lt;code&gt;test&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping
    public ResponseEntity test(){
        return ResponseEntity.ok("it works!");
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you want to know more about HTTP methods, you can visit these links: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods&lt;/a&gt;, &lt;a href="https://www.w3schools.com/tags/ref_httpmethods.asp" rel="noopener noreferrer"&gt;https://www.w3schools.com/tags/ref_httpmethods.asp&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As shown, the method returns an object of type &lt;code&gt;ResponseEntity&lt;/code&gt;. This class represents an HTTP return, where we can also insert the return codes (2xx, 4xx, 5xx...).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to know more about HTTP response codes, you can visit this link: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ResponseEntity&lt;/code&gt; class already carries the possible HTTP response codes. In our case we are using the return &lt;strong&gt;ok&lt;/strong&gt; which is indicated by the code &lt;strong&gt;200&lt;/strong&gt;. From this return, you can insert a body containing a message. In this case we are returning it works!".&lt;/p&gt;

&lt;p&gt;Now when performing a GET request for the URL &lt;a href="http://localhost:8080/test" rel="noopener noreferrer"&gt;http://localhost:8080/test&lt;/a&gt; we get the following response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fog8dvlyub45swiehfvlr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fog8dvlyub45swiehfvlr.png" alt="Image description" width="531" height="235"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 02 - User stories&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we know how to create a route, we can now see our system's scenarios from the user's point of view.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to register books in the system by registering the following information: &lt;strong&gt;id, title, author, number of pages, isbn, evaluation, status (finished or not)&lt;/strong&gt;. I would also like that the evaluation of the book should be obtained automatically from the page of this book on the site &lt;a href="http://skoob.com.br" rel="noopener noreferrer"&gt;http://skoob.com.br&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to get all the books registered in the system through pagination. Having only 10 books per page and sorting by title.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to obtain information of only one book, identified by its id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to update the information of a book, identified by its id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As a user&lt;/strong&gt;, I would like to delete a book based on its id.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 03 - System modeling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;From the specifications presented above, we can model our system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2avk8exymzkbylsbbcc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2avk8exymzkbylsbbcc2.png" alt="ER Diagram" width="297" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the entity-relationship diagram, we will only have a single table in the database called &lt;code&gt;Book&lt;/code&gt; and it will contain the following columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id (primary key)&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;author&lt;/li&gt;
&lt;li&gt;pages&lt;/li&gt;
&lt;li&gt;isbn (unique)&lt;/li&gt;
&lt;li&gt;rate (nullable)&lt;/li&gt;
&lt;li&gt;finished&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only the rate column can have a null value.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 04 - Creating the database&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this tutorial I will not be focusing on installing the database on your machine. On my machine I'm using a Docker container that contains the MySQL database.&lt;/p&gt;

&lt;p&gt;Our database will be called &lt;code&gt;small_library&lt;/code&gt;. So, to create the database you can run the following command in SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
create database small_library;
use small_library;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, your database will be created and ready for use in the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 05 - Integration of the database with the system&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once your database is ready, we can add some dependencies to the project that will help us connect the system to the database and perform some manipulations. Therefore, in your &lt;code&gt;pom.xml&lt;/code&gt; file you can add the following dependencies between the &lt;code&gt;&amp;lt;dependencies&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/dependencies&amp;gt;&lt;/code&gt; tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ... --&amp;gt;

&amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt;
   &amp;lt;/dependency&amp;gt;
   &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;spring-boot-starter-validation&amp;lt;/artifactId&amp;gt;
   &amp;lt;/dependency&amp;gt;
   &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.flywaydb&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;flyway-core&amp;lt;/artifactId&amp;gt;
   &amp;lt;/dependency&amp;gt;
   &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.flywaydb&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;flyway-mysql&amp;lt;/artifactId&amp;gt;
   &amp;lt;/dependency&amp;gt;
   &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;com.mysql&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;mysql-connector-j&amp;lt;/artifactId&amp;gt;
      &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
   &amp;lt;/dependency&amp;gt;

&amp;lt;!-- ... --&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following dependencies are being added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flyway Migration&lt;/strong&gt;: from it, we can create migrations for the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MySQL Driver&lt;/strong&gt;: is the driver that will allow the connection between our server and the MySQL database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Data JPA&lt;/strong&gt;: from it we can persist data in the database from entities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: it is the validation service that we will use to verify that the data arriving at the server is in accordance with the established validation rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that, you can reload the Maven dependencies. When running your application, the terminal will display the following message:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uzn3xhlik9vd8xyuklm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8uzn3xhlik9vd8xyuklm.png" alt="Terminal error" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This message means that you have added the database dependencies on the system but have not added any connection properties. That is, Spring is trying to fetch the connection URL, the username and password to connect, but it is not finding it.&lt;/p&gt;

&lt;p&gt;To change that, I recommend you close the server, and go to the &lt;code&gt;application.properties&lt;/code&gt; file inside &lt;code&gt;resources&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.datasource.url=jdbc:mysql://localhost:3307/small_library
spring.datasource.username=root
spring.datasource.password=root

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;spring.datasource.url&lt;/code&gt; tag, we inform you the URL to access your database. In my case, I'm using the mysql database and it's running on port &lt;strong&gt;3307&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, in the &lt;code&gt;spring.datasource.username&lt;/code&gt; and &lt;code&gt;spring.datasource.password&lt;/code&gt; tags we inform the database user name and password, respectively. In my case, I fill both with &lt;strong&gt;root&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By doing this we can start the server again and it will run successfully&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 06 - Creating migrations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have successfully connected to the database, we can now create the scripts to create our &lt;strong&gt;books&lt;/strong&gt; table. For the versioning of these scripts, we will be using the migrations system that is provided from the &lt;code&gt;flyway&lt;/code&gt; dependency.&lt;/p&gt;

&lt;p&gt;For those who don't know, a migration is a versioned sql script that allows you to add or modify a table in the database. This versioning is important to have a control of the modifications that are made in the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flyway&lt;/strong&gt; documentation can be found at this link &lt;a href="https://flywaydb.org/documentation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Spring Boot, migrations are inside the &lt;code&gt;resources.db.migration&lt;/code&gt; folder and each script must be saved with the following name:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Prefix&amp;gt;&amp;lt;Version&amp;gt;__&amp;lt;Description&amp;gt;.sql&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usually in the &lt;strong&gt;prefix&lt;/strong&gt; we insert the letter &lt;strong&gt;V&lt;/strong&gt;, meaning &lt;strong&gt;version&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the version, we insert the version number, starting with 1 (and it will be incremented with each new script).&lt;/li&gt;
&lt;li&gt;And in the description we insert what we are doing in that script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can create the following migration:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;V1__create-table-books.sql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And inside of it the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
create table books(
      id bigint not null auto_increment,
      title varchar(100) not null,
      author varchar(100) not null,
      pages int not null,
      isbn varchar(100) not null unique,
      finished tinyint not null,
      rate float,

      primary key(id)
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE: It is highly recommended that you stop the server before creating a migration to avoid any problems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When creating the migration, we can start the server and it will automatically run the migration, creating the table in the database:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36cslwnd5ebgjnyk35f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36cslwnd5ebgjnyk35f7.png" alt="Migration" width="800" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsggyjdm95yqej2p2ys3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsggyjdm95yqej2p2ys3.png" alt="Tables in the database" width="336" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that in addition to the &lt;code&gt;books&lt;/code&gt; table, the &lt;code&gt;flyway_schema_history&lt;/code&gt; table was also created. This table will store all migrations that have already been run and what is the current version of the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 07 - Creating the DAO class&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So far we have made all the necessary configurations in the database. We can now create our DAO class that will help us access the data in the database.&lt;/p&gt;

&lt;p&gt;Therefore, inside the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package we will create a new package called &lt;code&gt;model&lt;/code&gt;. And inside this, we create a class called &lt;code&gt;Book&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.simplelibrary.simplelibraryAPI.model;
import jakarta.persistence.*;
import lombok.*;
@Table(name = "books")
@Entity(name = "Book")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String author;
    private Integer pages;
    private String isbn;
    private Double rate;
    private Boolean finished;

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, the amount of &lt;code&gt;Annotations&lt;/code&gt; can be daunting, but it is very easy to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;@Table(name = "books") refers to the table in the database that this class references. As we created the &lt;code&gt;books&lt;/code&gt; table, we put this value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@Entity(name = "Book") refers to the name of the DAO class - telling the Spring that it is an entity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@Getter is a &lt;strong&gt;lombok&lt;/strong&gt; annotation to generate &lt;code&gt;getters&lt;/code&gt; methods for all attributes of the class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/setter"&gt;@setter&lt;/a&gt; is a &lt;strong&gt;lombok&lt;/strong&gt; annotation to generate the &lt;code&gt;setters&lt;/code&gt; methods of all attributes of the class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@NoArgsConstructor is a &lt;strong&gt;lombok&lt;/strong&gt; annotation to generate the class constructor method with no arguments: &lt;code&gt;public Book();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@AllArgsConstructor is a &lt;strong&gt;lombok&lt;/strong&gt; annotation to generate the constructor method of the class with all the attributes of the class present in the arguments: &lt;code&gt;public Book(Long id, String title, String author, Integer pages, String isbn, Double rate, Boolean finished );&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@EqualsAndHashCode(of = "id") is a &lt;strong&gt;lombok&lt;/strong&gt; annotation to generate equals method and hashCode generator using id as parameter.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we can also add what are the attributes of the class. We will use the columns present in the database as a reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: It is important to add the annotations &lt;code&gt;@Id&lt;/code&gt; and &lt;code&gt;@GeneratedValue(strategy = GenerationType.IDENTITY)&lt;/code&gt; before the declaration of the id attribute to inform that this attribute is an identifier.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 07 - Creating the repository&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We previously created our DAO class. Now it is necessary to have a way to get the data from the database - this will be done through the repositories. A repository is an interface that inherits from the &lt;code&gt;JpaRepository&lt;/code&gt; class. From it, we can perform manipulations on the database, considering a previously created DAO class.&lt;/p&gt;

&lt;p&gt;To create the repository, we have to go inside the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package and create a new package called repository. And inside this, we create an interface called &lt;code&gt;BookRepository&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.repository;

import com.simplelibrary.simplelibraryAPI.model.Book;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookRepository extends JpaRepository&amp;lt;Book, Long&amp;gt; {

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only that! When doing the inheritance, we have to specify which entity it will use to get the data. In this case, it is the &lt;code&gt;Book&lt;/code&gt; entity. We also have to specify what the type of the primary key is (in this case it is Long).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 08 - Thinking about input and output data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are just a few steps away from finishing the implementation of our CRUD. Now is a good time to start thinking about how the data will arrive in our application and how we would like to return it to the user.&lt;/p&gt;

&lt;p&gt;In previous steps, some system scenarios that we must implement were presented. One of them was the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;As a user&lt;/strong&gt;, I would like to register books in the system by registering the following information: &lt;strong&gt;id, title, author, number of pages, isbn, evaluation, status (finished or not)&lt;/strong&gt;. I would also like that the evaluation of the book should be obtained automatically from the page of this book on the site &lt;a href="http://skoob.com.br" rel="noopener noreferrer"&gt;http://skoob.com.br&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We know that the identifier code (id) will be generated automatically by the system and that the evaluation of the book will be obtained through the website. Therefore, we expect that to register a book in the system, the user must inform the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Author&lt;/li&gt;
&lt;li&gt;Number of Pages&lt;/li&gt;
&lt;li&gt;ISBN&lt;/li&gt;
&lt;li&gt;Finished&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, we can create a class that will be used for data transfer (DTO - Data Transfer Object). We'll go into the &lt;code&gt;src.main.java.com.simplelibrary.simplelibrary.API&lt;/code&gt; package and create a new package called &lt;code&gt;dto&lt;/code&gt;. And inside this, we create a record called &lt;code&gt;BookRequestDTO&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.simplelibrary.simplelibraryAPI.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record BookRequestDTO(
        @NotBlank
        String title,
        @NotBlank
        String author,
        @NotNull
        Integer pages,
        @NotBlank
        String isbn,
        @NotNull
        Boolean finished
) {

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For those who are not familiar, a record is an immutable type of class, that is, from the moment we create an object and fill in its data, these will not be changed. Your &lt;em&gt;getters&lt;/em&gt; methods are created automatically.&lt;/p&gt;

&lt;p&gt;Note that there are some annotations that were not explained earlier. As is the case with &lt;code&gt;@NotBlank&lt;/code&gt; and &lt;code&gt;@NotNull&lt;/code&gt;. These annotations are used for input validation. By default, we don't want any of our fields to be empty, so we add the &lt;code&gt;@NotBlank&lt;/code&gt; annotation before Strings (which checks if the String is empty or null) and &lt;code&gt;@NotNull&lt;/code&gt; before other classes.&lt;/p&gt;

&lt;p&gt;When adding this validation, if the user fails to send a field, he will see a message informing the problem.&lt;/p&gt;

&lt;p&gt;Alright, we made the record for the request, now we are going to make a new record for the response. That is, we will treat the data that will be sent to the user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.simplelibrary.simplelibraryAPI.dto;

import com.simplelibrary.simplelibraryAPI.model.Book;

public record BookResponseDTO(String title, String author, Integer pages, String isbn, Double rate, Boolean finished) {
    public BookResponseDTO(Book book){
        this(book.getTitle(), book.getAuthor(), book.getPages(), book.getIsbn(), book.getRate(), book.getFinished());
    }

}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that now we will only send the following information to the user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Author&lt;/li&gt;
&lt;li&gt;Number of Pages&lt;/li&gt;
&lt;li&gt;ISBN&lt;/li&gt;
&lt;li&gt;Rate&lt;/li&gt;
&lt;li&gt;Status (finished or not).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A constructor was also created that will fill in your data from our DAO class.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What we learned in this tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Well done! So far you have seen how to configure the database and integrate it with the system. You've also learned how to create DAO classes and DTO records for accessing database information and sending data, respectively.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e"&gt;part 3&lt;/a&gt; we will finish the construction of our REST API. Creating the service which will contain the business rule. And also the rest of the access routes to the system.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Creating a REST API using Spring Boot + Tests + Documentation [part 01]</title>
      <dc:creator>Francisco Pereira</dc:creator>
      <pubDate>Wed, 01 Feb 2023 18:16:23 +0000</pubDate>
      <link>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262</link>
      <guid>https://forem.com/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-01-2262</guid>
      <description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;In this 5 parts tutorial I will be teaching you how to develop a REST API using &lt;strong&gt;Spring Boot&lt;/strong&gt;. In each part we will be focusing on a different functionality, this division is shown in the following table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Part&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Part 01&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Application Startup&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 02&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i"&gt;Settings and Database&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 03&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-03-1m5e"&gt;API Implementation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 04&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-04-4190"&gt;Tests + Coverage&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Part 05&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-05-1pd6"&gt;Swagger Documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;It is expected that from this &lt;strong&gt;first part&lt;/strong&gt; you will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializing a new Spring Boot application using &lt;strong&gt;Spring Initializr&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Project structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this tutorial the following tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDK 17&lt;/li&gt;
&lt;li&gt;IntelliJ&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;MySQL database&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 01 - Initializing the project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Spring Boot has a very simple and intuitive initialization tool, with a few steps you can already generate a Spring application with some dependencies. You can do this by going to the &lt;a href="https://start.spring.io" rel="noopener noreferrer"&gt;Spring Initializr&lt;/a&gt; website&lt;/p&gt;

&lt;p&gt;For this project, we can leave the following tags and dependencies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpid0utbkpwvmejfza8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpid0utbkpwvmejfza8d.png" alt="Spring Initilizr Tags" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the left part of the screen, we can see some technical specifications of the project. &lt;br&gt;
For project management, we use &lt;strong&gt;Maven&lt;/strong&gt; along with &lt;strong&gt;Java&lt;/strong&gt;. The Spring Boot version we are using is 3.0.2.&lt;/p&gt;

&lt;p&gt;In the metadata part, we mainly inform the name of the project. For this tutorial we will be creating a simple library system where we will only be storing book information. Therefore, we can name the project &lt;em&gt;Simple Library&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this tutorial we will not be exporting our project and deploying it, so we can put &lt;strong&gt;Packaging&lt;/strong&gt; with its default value (.jar). However, if you are going to export this project, you can select the best option for you.&lt;/p&gt;

&lt;p&gt;Finally, we have that the version to be used of java is 17.&lt;/p&gt;

&lt;p&gt;In the right part of the screen we can inform &lt;em&gt;Initializr&lt;/em&gt; which dependencies we would like to have in our project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spring Boot DevTools&lt;/strong&gt;: we have access to some important developer tools, one of which is &lt;strong&gt;LiveReload&lt;/strong&gt; which checks if a modification has been made to the project to restart the server automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lombok&lt;/strong&gt;: we can insert some annotations into our classes to replace the manual insertion of &lt;em&gt;getters&lt;/em&gt;, &lt;em&gt;setters&lt;/em&gt; and &lt;em&gt;constructors&lt;/em&gt;. Thus increasing developer productivity and decreasing the amount of code to be written in the class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SpringWeb&lt;/strong&gt;: it is one of the most important dependencies, from which we can create web services. With this dependency we can have access to the servlet-based implementation, RESTful services and many other features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By clicking on the &lt;strong&gt;Explore&lt;/strong&gt; button you will have access to the file that will be generated containing your application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpx7lwa85g7wub28q14bx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpx7lwa85g7wub28q14bx.png" alt="Image description" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;em&gt;pom.xml&lt;/em&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;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"&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.0.2&amp;lt;/version&amp;gt;
        &amp;lt;relativePath/&amp;gt; &amp;lt;!-- lookup parent from repository --&amp;gt;
    &amp;lt;/parent&amp;gt;
    &amp;lt;groupId&amp;gt;com.simplelibrary&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;simplelibraryAPI&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;name&amp;gt;simplelibraryAPI&amp;lt;/name&amp;gt;
    &amp;lt;description&amp;gt;A simple library to practice&amp;lt;/description&amp;gt;
    &amp;lt;properties&amp;gt;
        &amp;lt;java.version&amp;gt;17&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-devtools&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
            &amp;lt;optional&amp;gt;true&amp;lt;/optional&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
            &amp;lt;optional&amp;gt;true&amp;lt;/optional&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;excludes&amp;gt;
                        &amp;lt;exclude&amp;gt;
                            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
                            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
                        &amp;lt;/exclude&amp;gt;
                    &amp;lt;/excludes&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;

&amp;lt;/project&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By clicking on &lt;strong&gt;Generate&lt;/strong&gt; all the files needed for the application will be compressed and downloaded to your machine. From now on you can open the folder in any &lt;strong&gt;IDE&lt;/strong&gt; of your choice. In this tutorial I will be using &lt;strong&gt;IntelliJ&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 02 - Checking the project structure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When opening the project we can see the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦 simplelibraryAPI
├─ src
│  ├─ main
│  │  ├─ java
│  │  │  └─ com
│  │  │     └─ simplelibrary
│  │  │        └─ simplelibraryAPI
│  │  │           └─ SimplelibraryApiApplication.java
│  │  └─ resources
│  │     ├─ db
│  │     │  └─ migration
│  │     ├─ static
│  │     ├─ templates
│  │     └─ application.properties
│  └─ test
│     └─ java
│        └─ com
│           └─ simplelibrary
│              └─ simplelibraryAPIs
│                 └─ SimplelibraryApiApplicationTests.java
├─ .mvn
├─ .gitignore
├─ mvnw
├─ mvnw.cmd
└─ pom.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the basic structure of a Spring Boot project, throughout the parts of this tutorial we will be adding new folders to keep the project more organized.&lt;/p&gt;

&lt;p&gt;From the SimplelibraryApiApplication.java file our application will be initialized, inside this class there is the &lt;code&gt;main&lt;/code&gt; method that will call the &lt;code&gt;run&lt;/code&gt; method of the &lt;em&gt;SpringApplication&lt;/em&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.simplelibrary.simplelibraryAPI;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SimplelibraryApiApplication {

  public static void main(String[] args) {
    SpringApplication.run(SimplelibraryApiApplication.class, args);
  }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;@SpringBootApplication&lt;/code&gt; annotation. It is important to inform Spring that this is the main class of our application and that our server will be initialized from there.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;application.properties&lt;/code&gt; file will contain some important properties for our system. We will understand better about it later on, especially when we are going to configure the database.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 03 - Running the project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After executing the previous steps, your code is ready to run. Using the IDE of your choice, when starting the server you will have the following result in the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9p27lyqhklnirk8x5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp9p27lyqhklnirk8x5s.png" alt="Spring Boot logo" width="394" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbfsr5lorew78zh13z1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbfsr5lorew78zh13z1s.png" alt="Server startup" width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the server is running at address: &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, when making a request to this URL, you will find the following response from the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
    "timestamp": "2023-01-31T18:08:42.607+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out that so far we have not mapped any route to the source url ("/"). Therefore, we need to perform the mapping, but we will see this in part 02 of our tutorial!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What we learned in this tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So far, you've seen how to create the initial project in Spring Boot, using &lt;em&gt;Spring Initializr&lt;/em&gt;. In addition to seeing a little about its structure. In &lt;a href="https://dev.to/franciscotis/creating-a-rest-api-using-spring-boot-tests-documentation-part-02-1a4i"&gt;part 02&lt;/a&gt; we will carry out the actual implementation of our API, performing the configuration with the database and coding the access routes.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>website</category>
    </item>
  </channel>
</rss>
