Como fazer API-REST com Spring
Tags: api, beginners, webdev, backend
Published: 2023-12-05 15:39:23


Para podermos fazer esse passo a passo irei usar como base um projeto de TO DO LIST 
	
   - Esta é uma receitinha de bolo para construções de API
   -  é importante dizer que mesmo sendo uma receita de bolo, isso são apenas informações basicas,

#### Controller
First Header |Second Header|  Third Header| Fourth  Header| 
------------ |-------------| -------------| -------------| 
<a href=" " target="blank">@RestController</a><br>|<a href=" " target="blank">@RequestMapping</a><br>|<a href=" " target="blank">@AllArgsConstructor</a><br>|<a href=" " target="blank">@Slf4j</a><br>|

First Header |Second Header|  Third Header| Fourth  Header|
------------ |-------------| -------------| -------------| 
<a href=" " target="blank"> @PostMapping</a><br>|<a href=" " target="blank"> @ApiOperation</a><br>|<a href=" " target="blank">@ResponseStatus</a><br>|<a href=" " target="blank"> @ApiResponses</a><br>|

First Header |Second Header|  Third Header| Fourth  Header|
------------ |-------------| -------------|-------------| 
<a href=" " target="blank"> @GetMapping</a><br>|<a href=" " target="blank">@PathVariable</a><br>|<a href=" " target="blank"> @PutMapping</a><br>|<a href=" " target="blank"> @DeleteMapping</a><br>|


```

@RestController// this is a controller class
@RequestMapping("/api/v1")// base url
@AllArgsConstructor// lombok annotation for constructor
@Slf4j// lombok annotation for logger
public class TaskController {

    TaskService taskService;

   //primeiro ENDPOINT
   @ApiOperation(value = "Create a task")
           @ApiResponses(value = {
                   @ApiResponse(code = 201, message = "Task created"),
                   @ApiResponse(code = 400, message = "Invalid request"),
                   @ApiResponse(code = 500, message = "Internal server error")
           })

    @PostMapping("/tasks")
    @ResponseStatus(HttpStatus.CREATED)
    public Task createTask(@RequestBody Task task)// @RequestBody annotation is used to bind the request body with a method parameter.
    { log.info("Task created[{}]",task);
        return taskService.createTask(task);
    }
    //SEGUNDO ENDPOINT
    @ApiOperation(value = "Get all tasks")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Task found"),
    })

            @GetMapping("/tasks")
    @ResponseStatus(HttpStatus.OK)
    public List<Task> getAllTasks() {
        return taskService.listAllTasks();
    }

    //TERCEIRO ENDPOINT
    @ApiOperation(value = "Get a task by id")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Task found"),
    })

            @GetMapping("/tasks/{id}")// {id} is a path variable
    @ResponseStatus(HttpStatus.OK)// this annotation is used to set the http status code
    public ResponseEntity<Task> getTaskById(@PathVariable (value = "id") Long id)// @PathVariable annotation is used to bind the path variable with a method parameter.
     { log.info("Task found[{}]",id);
        return taskService.findTaskById(id);
    }

    //QUARTO ENDPOINT
    @ApiOperation(value = "Update a task by id")
        @ApiResponses(value = {
                @ApiResponse(code = 200, message = "Task updated"),
        })


            @PutMapping  ("/tasks/{id}")
    @ResponseStatus(HttpStatus.OK)
    public ResponseEntity<Task> UpdateById(@PathVariable (value = "id")Long id, @RequestBody Task task)
    {log.info("Task updated[{}]",id);
        return taskService.updateTaskId(task,id);
    }

    //QUINTO ENDPOINT
    @ApiOperation(value = "Delete a task by id")
        @ApiResponses(value = {
                @ApiResponse(code = 204, message = "Task deleted") })


            @DeleteMapping("/tasks/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public ResponseEntity<Object> DeleteById(@PathVariable (value = "id") Long id)
    {log.info("Task deleted[{}]",id);
        return taskService.deleteById(id);
    }


}

```
#### Model
> Camada de dados 
- Responsavel por onde fica a entidade ( tabela do banco de dados)
- Nome da classe pode ser ou  não criado com o nome do pacote( recomendo que crie com o nome caso ainda esteja aprendendo estrutura de dados e de api)

- @Entity (<a href="https://www.devmedia.com.br/jpa-como-usar-a-anotacao-entity/38410#:~:text=A%20anota%C3%A7%C3%A3o%20%40Entity%20%C3%A9%20utilizada,desse%20tipo%20poder%C3%A3o%20ser%20persistidos." target="blank">Clique aqui para relembrar o que é</a>)
- @Table (<a href="https://www.geeksforgeeks.org/spring-data-jpa-table-annotation/" target="blank">Clique aqui para relembrar o que é</a>)
- @Getter e @Setter (<a href="https://projectlombok.org/features/GetterSetter" target="blank">Clique aqui para relembrar o que é</a>)
- @ToString (<a href="https://www.baeldung.com/lombok-tostring" target="blank">Clique aqui para relembrar o que é</a>)

Catalago


First Header | Second Header| Third Header| Fourth  Header| Fifth Header
------------ | -------------| -------------| -------------| -------------
<a href="https://www.devmedia.com.br/jpa-como-usar-a-anotacao-id/38508" target="blank">@Id</a><br>|<a href="https://www.devmedia.com.br/jpa-como-usar-a-anotacao-generatedvalue/38592" target="blank">@GeneratedValue</a><br>|<a href="https://www.geeksforgeeks.org/spring-data-jpa-column-annotation/" target="blank">@Column</a><br>|<a href="https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp" target="blank">@CreationTimestamp</a><br>|<a href="https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp" target="blank">@UpdateTimestamp</a><br>

```
public class Task { public class Task { ... }: estamos definindo a classe Task, que provavelmente
contém informações sobre uma tarefa no sistema.) 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private  Long id;

    @Column(nullable = false)
    private String title;

    @CreationTimestamp
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private  LocalDateTime updatedAt;

}

```


#### Repository
- Interface 
- taskRepository

First Header |
------------ |
<a href="https://www.gasparbarancelli.com/post/anotacao-repository-em-projetos-spring-entenda-sua-importancia-e-beneficios#:~:text=A%20anota%C3%A7%C3%A3o%20%40Repository%20%C3%A9%20utilizada,%C3%A9%20um%20reposit%C3%B3rio%20de%20dados" target="blank">@Repository</a><br>|
```
@Repository
public interface TaskRepository extends JpaRepository<Task(Model), Long(tipo da chave primaria)> {
}
```


#### Service

First Header | Second Header| Third Header| Fourth  Header|
------------ |------------ |------------ |------------ |
<a href="https://www.geeksforgeeks.org/spring-service-annotation-with-example/" target="blank">@Service</a><br>|<a href="https://projectlombok.org/features/constructor" target="blank">@AllArgsConstructor</a><br>|<a href="https://projectlombok.org/api/lombok/RequiredArgsConstructor" target="blank">@RequiredArgsConstructor</a><br>|<a href="https://www.baeldung.com/spring-autowire" target="blank"> @Autowired</a><br>|


```
@Service
@AllArgsConstructor
public class TaskService {


    private TaskRepository taskRepository;

    public Task(model) createTask(Task(model) task) {
        return taskRepository.save(task);
    }

    public List<Task> listAllTasks() {
        return taskRepository.findAll();
    }

    public ResponseEntity<Task> findTaskById(Long id) {
        return taskRepository.findById(id).map(task -> ResponseEntity.ok().body(task)).orElse(ResponseEntity.notFound().build());
    }

    public ResponseEntity<Task> updateTaskId(Task task, Long id) {
        return taskRepository.findById(id)
                .map(taskToUpdate -> {
                    taskToUpdate.setTitle(task.getTitle());
                    taskToUpdate.setDescription(task.getDescription());
                    taskToUpdate.setDeadLine(task.getDeadLine());
                    Task updated = taskRepository.save(taskToUpdate);
                    return ResponseEntity.ok().body(updated);
                }).orElse(ResponseEntity.notFound().build());
    }

    public ResponseEntity<Object> deleteById (Long id ) {
        return taskRepository.findById(id)
                .map(taskToDelete -> {
                    taskRepository.deleteById(id);
                    return ResponseEntity.noContent().build();
                }).orElse(ResponseEntity.notFound().build());
    }
    }
    

```
Obs: Em diferentes design pattern o Swagger fica na pasta DOCS ou CONFIGURATION, aqui deixarei como DOCS por estar fazendo o projeto