📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Especialização em Backend com Java e Spring Boot. Recomendado revisar antes de começar.

🚀 Projeto Lista de Tarefas (To-Do List)

v2.0`

🗺️ Visão Geral da Arquitetura

Neste projeto, construiremos um sistema completo de “Lista de Tarefas” (To-Do List), demonstrando como diferentes aplicações cliente podem consumir uma única fonte de dados central (API). A arquitetura final será:

Diagrama da Arquitetura

flowchart TD
    subgraph "🎛️ Gerenciamento e Automação"
    Script["🛠️ Painel de Controle<br>(listadetarefas-painel.ps1)"]
    end

    subgraph "📱 Clientes (Frontends)"
    Web["💻 Frontend Web<br>(Angular)"]
    Desktop["🖥️ Frontend Desktop<br>(JavaFX)"]
    Mobile["📱 Frontend Mobile<br>(Android)"]
    end

    subgraph "⚙️ Serviços (Backend)"
    API["🔌 Backend API<br>(Spring Boot)"]
    DB[("🗄️ Banco de Dados<br>Em Memória H2")]
    end

    %% Conexões de Dados
    Web -->|HTTP/JSON| API
    Desktop -->|HTTP/JSON| API
    Mobile -->|HTTP/JSON| API
    API --- DB

    %% Conexões de Gerenciamento
    Script -.->|Gerencia| API
    Script -.->|Gerencia| Web
    Script -.->|Gerencia| Desktop
    Script -.->|Gerencia| Mobile

    %% Estilização
    style Script fill:#f9f,stroke:#333,stroke-width:2px
    style API fill:#dfd,stroke:#333,stroke-width:2px
    style DB fill:#def,stroke:#333,stroke-width:2px
    style Web fill:#ffe,stroke:#333,stroke-width:2px

—–`

⚙️ Módulo 1: A Fundação – Backend com Spring Boot (listadetarefas-api)

Objetivo: Criar o serviço central que irá gerenciar os dados das tarefas, servindo como a única fonte de verdade para todos os clientes.

🛠️ Ferramentas Necessárias

📂 Passo 1: Criação do Projeto

  1. Acesse o Spring Initializr (https://start.spring.io).
  2. Preencha os metadados do projeto:
    • Project: Maven
    • Language: Java
    • Spring Boot: Versão estável mais recente (ex: 3.x.x)
    • Group: br.com.curso
    • Artifact: listadetarefas-api
    • Package name: br.com.curso.listadetarefas.api
  3. Adicione as seguintes dependências (Dependencies):
    • Spring Web, Spring Data JPA, H2 Database, Lombok.
  4. Clique em GENERATE, baixe o projeto, descompacte-o e abra na sua IDE.

Estrutura Inicial de Pastas

Após criar o projeto, sua estrutura de pastas principal será:

listadetarefas-api/
├── src/
│   └── main/
│       ├── java/
│       │   └── br/com/curso/listadetarefas/api/
│       │       └── ListadetarefasApiApplication.java
│       └── resources/
│           └── application.properties
└── pom.xml

⚙️ Passo 2: Configuração do Projeto

Abra o arquivo src/main/resources/application.properties e substitua seu conteúdo por este:

# Permite que o servidor aceite conexões de qualquer endereço de rede da máquina.
server.address=0.0.0.0

# Habilita o console web do H2
spring.h2.console.enabled=true
# Define o caminho para acessar o console
spring.h2.console.path=/h2-console

# Configurações do Datasource para H2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

📝 Passo 3: Modelagem dos Dados

Vamos definir a estrutura da nossa tabela de tarefas.

Diagrama Entidade-Relacionamento (ER)

erDiagram
    TB_TAREFAS {
        BIGINT id PK "Auto-incremento"
        VARCHAR descricao "Descrição da tarefa"
        BOOLEAN concluida "Status de conclusão"
    }
  1. Dentro de src/main/java/br/com/curso/listadetarefas/api, crie um novo pacote chamado tarefa.
  2. Dentro do pacote tarefa, crie a classe Tarefa.java.
// src/main/java/br/com/curso/listadetarefas/api/tarefa/Tarefa.java
package br.com.curso.listadetarefas.api.tarefa;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "tb_tarefas")
public class Tarefa {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String descricao;
    private boolean concluida;
}

Estrutura de Pastas Após a Criação do Modelo

api/
└── src/main/java/br/com/curso/listadetarefas/api/
    ├── tarefa/
    │   └── Tarefa.java  # <- Arquivo criado
    └── ListadetarefasApiApplication.java

🏗️ Passo 4: Construção das Camadas de Serviço

Agora, criaremos as classes que formam a arquitetura da nossa API: Repository (acesso a dados), Service (regras de negócio) e Controller (endpoints HTTP).

Diagrama de Classes

classDiagram
    direction LR
    TarefaController ..> TarefaService : Usa
    TarefaService ..> TarefaRepository : Usa
    TarefaRepository ..> Tarefa : Gerencia

    class TarefaController {
        +List~Tarefa~ listarTarefas()
        +Tarefa criarTarefa(Tarefa tarefa)
        +ResponseEntity~Tarefa~ atualizarTarefa(Long id, Tarefa tarefa)
        +ResponseEntity~Void~ deletarTarefa(Long id)
    }

    class TarefaService {
        +List~Tarefa~ listarTodas()
        +Tarefa criar(Tarefa tarefa)
        +Tarefa atualizar(Long id, Tarefa tarefa)
        +void deletar(Long id)
    }

    class TarefaRepository {
        <<Interface>>
    }

    class Tarefa {
        +Long id
        +String descricao
        +boolean concluida
    }
  1. Dentro do pacote tarefa, crie as seguintes classes e interfaces:

TarefaRepository.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TarefaRepository extends JpaRepository<Tarefa, Long> {
}

TarefaService.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class TarefaService {
    @Autowired
    private TarefaRepository tarefaRepository;

    public List<Tarefa> listarTodas() { return tarefaRepository.findAll(); }
    public Tarefa criar(Tarefa tarefa) { return tarefaRepository.save(tarefa); }
    public Tarefa atualizar(Long id, Tarefa tarefaAtualizada) {
        return tarefaRepository.findById(id)
            .map(tarefaExistente -> {
                tarefaExistente.setDescricao(tarefaAtualizada.getDescricao());
                tarefaExistente.setConcluida(tarefaAtualizada.isConcluida());
                return tarefaRepository.save(tarefaExistente);
            }).orElseThrow(() -> new RuntimeException("Tarefa não encontrada com o id: " + id));
    }
    public void deletar(Long id) {
        if (!tarefaRepository.existsById(id)) {
            throw new RuntimeException("Tarefa não encontrada com o id: " + id);
        }
        tarefaRepository.deleteById(id);
    }
}

TarefaController.java

package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/tarefas")
@CrossOrigin(origins = "*")
public class TarefaController {
    @Autowired
    private TarefaService tarefaService;

    @GetMapping
    public List<Tarefa> listarTarefas() { return tarefaService.listarTodas(); }
    @PostMapping
    public Tarefa criarTarefa(@RequestBody Tarefa tarefa) { return tarefaService.criar(tarefa); }
    @PutMapping("/{id}")
    public ResponseEntity<Tarefa> atualizarTarefa(@PathVariable Long id, @RequestBody Tarefa tarefa) {
        try {
            Tarefa atualizada = tarefaService.atualizar(id, tarefa);
            return ResponseEntity.ok(atualizada);
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deletarTarefa(@PathVariable Long id) {
        try {
            tarefaService.deletar(id);
            return ResponseEntity.noContent().build();
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }
}

Estrutura de Pastas Final do Backend

api/
└── src/main/java/br/com/curso/listadetarefas/api/
    ├── tarefa/
    │   ├── Tarefa.java
    │   ├── TarefaController.java
    │   ├── TarefaRepository.java
    │   └── TarefaService.java
    └── ListadetarefasApiApplication.java

✅ Passo 5: Execução e Teste da API

Diagrama de Casos de Uso da API

flowchart LR
    User(["👤 Usuário<br>(via Cliente)"])
    
    subgraph Sistema_Tarefas ["⚙️ Sistema de Tarefas"]
        UC1(("Listar Tarefas"))
        UC2(("Adicionar Tarefa"))
        UC3(("Atualizar Tarefa"))
        UC4(("Deletar Tarefa"))
    end
    
    User --> UC1
    User --> UC2
    User --> UC3
    User --> UC4

    style User fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style Sistema_Tarefas fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5
  1. Execute a Aplicação:

    • Na sua IDE, execute a classe ListadetarefasApiApplication.java.
    • Ou, via terminal na raiz do projeto: ./mvnw spring-boot:run
  2. Teste com Cliente REST (ex: Postman):

    • Use um cliente REST para fazer requisições para http://localhost:8080/api/tarefas e verifique todas as operações de CRUD (GET, POST, PUT, DELETE) como detalhado no guia anterior.
  3. Teste com o Console H2:

    • Com a API rodando, acesse http://localhost:8080/h2-console no navegador.
    • Use as seguintes credenciais para logar:
      • JDBC URL: jdbc:h2:mem:testdb
      • User Name: sa
      • Password: (em branco)
    • Após criar tarefas via API, execute o comando SQL SELECT * FROM TB_TAREFAS; para ver os dados diretamente no banco.

—`

🚀 Como Executar no Laboratório

1. Abra o terminal na pasta deste projeto

No seu editor/IDE, abra a pasta deste projeto (File > Open Folder) ou navegue via terminal:

cd javaweb_tarefas_01_rest

2. Execute a aplicação e os testes

./mvnw spring-boot:run
./mvnw test

[!TIP] Dica para execução a partir da raiz do repositório: Se você abriu o repositório completo no VS Code, basta navegar até a pasta antes de executar: cd proj_aplicacoes_full_stack/projetos/javaweb_tarefas_01_rest