Skip to content

rcsim/tech-challenge

Repository files navigation

tech-challenge

Repositório para o Tech Challenge - Grupo 30

1.1- Relatório Técnico - Grupo 30 - Fase 1

Inicialmente foram definidas as versões que seriam utilizadas no projeto:

  • Maven
  • Java 11
  • Spring Boot 2.7.12

Também realizamos a definição das bibliotecas que seriam utilizadas:

  • Spring Web
  • Lombok
  • H2 Database

Quanto à versão utilizada do Java, decidimos utilizar a versão 11 por entender que hoje esta versão é mais utilizada no mercado e também consideramos a mais estável.

Optamos por utilizar um banco de dados em memória, apesar de não ser requisito, por entendermos que facilitaria a evolução do projeto na próxima etapa sem adicionar complexidade.

Também optamos pelo Spring Starter Validation para validar os dados de entrada.

Essas tecnologias e ferramentas contribuíram para o desenvolvimento eficiente e robusto do sistema, que em conjunto com reuniões semanais e distribuição de tarefas para cada integrante do grupo, possibilitou atingirmos os objetivos propostos no desafio.

A principal dificultade encontrada foi a necessidade de se realizar algumas refatorações afim de padronizar o código das 3 APIs, já que estavam significativamente diferentes em seu formato devido as preferências individuais de cada desenvolverdor.

1.2- Relatório Técnico - Grupo 30 - Fase 2

No início da fase 02 decidimos atualizar a versão do Java e Spring Boot para termos a possibilidade de utilizarmos novas funcionalidades da linguagem:

  • Java 17
  • Spring Boot 3.1.2

Além das bibliotecas já utilizadas na fase 1, adicionamos também as bibliotecas abaixo:

  • PostgreSQL
  • SpringDoc OpenAPI Starter WebMVC UI

Na fase 1 utilizamos um banco de dados em memória (H2 Database), nesta fase adicionamos a possibilidade de conectar a aplicação a um banco de dados real utilizando a biblioteca do PostgreSQL. A configuração para a aplicação conectar-se no H2 ou PostgreSQL deve ser feita no arquivo application.properties, onde deve ser definido qual profile a aplicação vai rodar, test para rodar o banco em memória H2 ou dev para rodar o banco PostgreSQL:

Configuração do H2:

# Dados de conexão com o banco H2
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
# H2 Client
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# JPA, SQL
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.defer-datasource-initialization=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Configuração do PostgreSQL:

# Dados de conexão com o banco PostgreSQL
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/techchallenge_db
spring.datasource.username=compose-postgres
spring.datasource.password=compose-postgres

Nesta fase adicionamos a possibilidade de geração automática da documentação através da biblioteca SpringDoc OpenAPI, a documentação pode ser acessada enquanto a aplicação estiver rodando em http://localhost:8080/swagger-ui/index.html#/:

image image image

Docker

Nesta fase foi adicionado a possibilidade de utilização de containers através do Docker-Compose. Criamos um container para aplicação e outro para o banco de dados e uma rede no modo bridge para ter acesso ao containers via localhost:

version: "3"
services:
db:
image: postgres
volumes:
- ./01-schema.sql:/docker-entrypoint-initdb.d/01-schema.sql
- ./02-seed.sql:/docker-entrypoint-initdb.d/02-seed.sql
environment:
- POSTGRES_USER=compose-postgres
- POSTGRES_PASSWORD=compose-postgres
ports:
- "5432:5432"
networks:
- my-networks
app:
depends_on:
- db
build: .
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/techchallenge_db
- SPRING_DATASOURCE_USERNAME=compose-postgres
- SPRING_DATASOURCE_PASSWORD=compose-postgres
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
- SPRING_PROFILES_ACTIVE=dev
ports:
- "8080:8080"
networks:
- my-networks
networks:
my-networks:
driver: bridge

Também adicionamos o arquivo Dockerfile que gerencia o processo de build da aplicação através do Maven e JDK, já inicializando a aplicação:

FROM maven:latest AS MAVEN_BUILD
COPY ./ ./
RUN mvn clean package
FROM openjdk:17-alpine AS builder
COPY --from=MAVEN_BUILD target/*.jar application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM openjdk:17-alpine
EXPOSE 8080
COPY --from=builder dependencies/ ./
COPY --from=builder snapshot-dependencies/ ./
COPY --from=builder spring-boot-loader/ ./
COPY --from=builder application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

Para criação dos container, compilar e rodar a applicação é necessário apenas o comando:

docker-compose up -d

image

Banco de Dados

Ao utilizarmos um container para o PostgreSQL, foi necessário a criação de dois arquivos, uma para configuração do schema e outro para seed de alguns dados para facilitar os testes:

DROP TABLE IF EXISTS tb_address CASCADE;
DROP TABLE IF EXISTS tb_appliance CASCADE;
DROP TABLE IF EXISTS tb_dependent CASCADE;
DROP TABLE IF EXISTS tb_dependent_appliance CASCADE;
CREATE DATABASE techchallenge_db;
\c techchallenge_db;
CREATE TABLE "tb_address" (
"id" SERIAL PRIMARY KEY,
"street" TEXT NOT NULL,
"number" VARCHAR(255) NOT NULL,
"district" VARCHAR(255) NOT NULL,
"city" VARCHAR(255) NOT NULL,
"state" VARCHAR(255) NOT NULL,
"user_id" BIGINT NOT NULL
);
CREATE TABLE "tb_appliance" (
"id" SERIAL PRIMARY KEY,
"name" VARCHAR(255) NOT NULL,
"model" VARCHAR(255) NOT NULL,
"power" VARCHAR(255) NOT NULL,
"manufacturer" VARCHAR(255) NOT NULL,
"user_id" BIGINT NOT NULL,
"address_id" BIGINT NOT NULL,
FOREIGN KEY (address_id) REFERENCES tb_address(id)
);
CREATE TABLE "tb_dependent" (
"id" SERIAL PRIMARY KEY,
"name" VARCHAR(255) NOT NULL,
"date_of_birth" VARCHAR(255) NOT NULL,
"gender" VARCHAR(255) NOT NULL,
"parentage" VARCHAR(255) NOT NULL,
"user_id" BIGINT NOT NULL,
"address_id" BIGINT NOT NULL,
FOREIGN KEY (address_id) REFERENCES tb_address(id)
);
CREATE TABLE "tb_dependent_appliance" (
"appliance_id" BIGINT NOT NULL,
"dependent_id" BIGINT NOT NULL,
PRIMARY KEY("appliance_id", "dependent_id"),
FOREIGN KEY ("appliance_id") REFERENCES "tb_appliance"("id"),
FOREIGN KEY ("dependent_id") REFERENCES "tb_dependent"("id")
);

\c techchallenge_db;
--Data generated by https://www.4devs.com.br/
-- Address data
INSERT INTO "tb_address"("street", "number", "district", "city", "state", "user_id")
VALUES ('Rua Presidente Juscelino Kubitschek', '1', 'Jardim Analândia', 'Itapecerica da Serra', 'SP', 1);
INSERT INTO "tb_address"("street", "number", "district", "city", "state", "user_id")
VALUES ('Rua Francisca Marinho', '1', 'Jardim Planalto', 'São Paulo', 'SP', 1);
INSERT INTO "tb_address"("street", "number", "district", "city", "state", "user_id")
VALUES ('Rua Santa Catarina', '1', 'Bom Pastor', 'Varginha', 'MG', 1);
-- Appliance data
INSERT INTO "tb_appliance"("name", "model", "power", "manufacturer", "user_id", "address_id")
VALUES ('TV Sala', 'Samsung Smart TV 55" OLED 4K 55S90C 2023', '40W', 'Samsung', 1, 1);
INSERT INTO "tb_appliance"("name", "model", "power", "manufacturer", "user_id", "address_id")
VALUES ('Torradeira', 'Torradeira Oster Inox Simple Life', '750W', 'Oster', 1, 1);
INSERT INTO "tb_appliance"("name", "model", "power", "manufacturer", "user_id", "address_id")
VALUES ('Aspirador', 'Aspirador de Pó Vertical Electrolux Ergorapido', '300W', 'Electrolux', 1, 1);
-- Dependent data
SET datestyle = dmy;
INSERT INTO "tb_dependent"("name", "date_of_birth", "gender", "parentage", "user_id", "address_id")
VALUES ('Henrique Hugo Matheus Freitas', '1977-01-02', 'Masculino', 'Filho', 1, 1);
INSERT INTO "tb_dependent"("name", "date_of_birth", "gender", "parentage", "user_id", "address_id")
VALUES ('Luiza Tatiane Brenda Cavalcanti', '1960-04-04', 'Feminino', 'Tia', 1, 1);
INSERT INTO "tb_dependent"("name", "date_of_birth", "gender", "parentage", "user_id", "address_id")
VALUES ('Fábio Marcelo Thomas Ferreira', '1950-01-24', 'Masculino', 'Avô', 1, 1);
INSERT INTO "tb_dependent_appliance"("appliance_id", "dependent_id")
VALUES (1, 1);
Os dados de seeding são fictícios e foram gerados em https://www.4devs.com.br/

As relações entre as entidades foram mapeadas conforme a seguir:

image

2- Documentação API

Opção 1: É possível verificar a documentação da API e exemplos via Postman em https://documenter.getpostman.com/view/17475893/2s9Y5eLyN7.

image

Opção 2: Rodar a aplicação e acessar http://localhost:8080/swagger-ui/index.html#/

Opção 3: Verificar o documentação abaixo:

---- DEPENDENTES ----

URL: http://localhost:8080/dependent

  • Endpoint: /dependent/{id}
  • Método: DELETE
  • Descrição: Remove um dependente do banco de dados.
  • Resposta:
    • 200: Dependente removido com sucesso.
    • 404: Dependente não encontrado.

  • Endpoint: /dependent
  • Método: GET
  • Descrição: Recupera todos os dependentes do banco de dados.
  • Resposta:
    • 200: Lista de dependentes registrados no sistema. Retorna uma lista vazia se não houver dependentes.

  • Endpoint: /dependent/{id}
  • Método: GET
  • Descrição: Recupera um dependente por ID do banco de dados.
  • Resposta:
    • 200: Retorna o dependente correspondente ao ID fornecido e registrado no sistema.
    • 404: Dependente não encontrado.

  • Endpoint: /dependent/{id}/appliances
  • Método: GET
  • Descrição: Recupera uma lista de eletrodomésticos associados a um dependente.
  • Resposta:
    • 200: Lista de eletrodomésticos registrados no sistema e associados a um dependente. Retorna uma lista vazia se não houver eletrodomésticos.
    • 404: Dependente não encontrado.

  • Endpoint: /dependent
  • Método: POST
  • Descrição: Adiciona um dependente ao banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do dependente em formato JSON.
  • Resposta:
    • 201: Dependente adicionado.
    • 422: O parâmetro não pode ser nulo.
    • 400: Requisição incorreta.
    • 404: Não é possível registrar em um endereço inexistente.

  • Endpoint: /dependent/{id}
  • Método: PUT
  • Descrição: Atualiza o registro de um dependente no banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do dependente em formato JSON.
  • Resposta:
    • 200: Dependente atualizado.
    • 422: O parâmetro não pode ser nulo.
    • 400: Requisição incorreta.
    • 404: Dependente não encontrado.

---- ENDEREÇOS ----

URL: http://localhost:8080/address

  • Endpoint: /address/{id}
  • Método: DELETE
  • Descrição: Remove um endereço do banco de dados.
  • Resposta:
    • 200: Endereço removido com sucesso.
    • 404: Endereço não encontrado.

  • Endpoint: /address
  • Método: GET
  • Descrição: Recupera todos os endereços do banco de dados.
  • Resposta:
    • 200: Lista de endereços registrados no sistema. Retorna uma lista vazia se não houver endereços.

  • Endpoint: /address/{id}
  • Método: GET
  • Descrição: Recupera um endereço por ID do banco de dados.
  • Resposta:
    • 200: Retorna o endereço correspondente ao ID fornecido e registrado no sistema.
    • 404: Endereço não encontrado.

  • Endpoint: /address/{id}/appliances
  • Método: GET
  • Descrição: Recupera uma lista de eletrodomésticos associados a um endereço.
  • Resposta:
    • 200: Lista de eletrodomésticos registrados no sistema e associados a um endereço. Retorna uma lista vazia se não houver eletrodomésticos.

  • Endpoint: /address/{id}/dependents
  • Método: GET
  • Descrição: Recupera uma lista de dependentes associados a um endereço.
  • Resposta:
    • 200: Lista de dependentes registrados no sistema e associados a um endereço. Retorna uma lista vazia se não houver dependentes.
    • 404: Endereço não encontrado.

  • Endpoint: /address
  • Método: POST
  • Descrição: Adiciona um endereço ao banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do endereço em formato JSON.
  • Resposta:
    • 201: Endereço adicionado.
    • 422: O parâmetro não pode ser nulo.
    • 400: Requisição incorreta.

  • Endpoint: /address/{id}
  • Método: PUT
  • Descrição: Atualiza o registro de um endereço no banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do endereço em formato JSON.
  • Resposta:
    • 200: Endereço atualizado.
    • 422: O parâmetro não pode ser nulo.
    • 404: Endereço não encontrado.
    • 400: Requisição incorreta.

---- ELETRODOMÉSTICOS ----

URL: http://localhost:8080/appliance

  • Endpoint: /appliance/{id}
  • Método: DELETE
  • Descrição: Remove um eletrodoméstico do banco de dados.
  • Resposta:
    • 200: Eletrodoméstico removido com sucesso.
    • 404: Eletrodoméstico não encontrado.

  • Endpoint: /appliance
  • Método: GET
  • Descrição: Recupera todos os eletrodomésticos do banco de dados.
  • Resposta:
    • 200: Lista de eletrodomésticos registrados no sistema. Retorna uma lista vazia se não houver eletrodomésticos.

  • Endpoint: /appliance/{id}
  • Método: GET
  • Descrição: Recupera um eletrodoméstico por ID do banco de dados.
  • Resposta:
    • 200: Retorna o eletrodoméstico correspondente ao ID fornecido e registrado no sistema.
    • 404: Eletrodoméstico não encontrado.

  • Endpoint: /appliance/{id}/dependent
  • Método: GET
  • Descrição: Recupera uma lista de dependentes associados a um eletrodoméstico.
  • Resposta:
    • 200: Lista de dependentes registrados no sistema e associados a um eletrodoméstico. Retorna uma lista vazia se não houver dependentes.
    • 404: Eletrodoméstico não encontrado.

  • Endpoint: /appliance
  • Método: POST
  • Descrição: Adiciona um eletrodoméstico ao banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do eletrodoméstico em formato JSON.
  • Resposta:
    • 201: Eletrodoméstico adicionado.
    • 422: O parâmetro não pode ser nulo.
    • 400: Requisição incorreta.
    • 404: Não é possível registrar em um endereço inexistente.

  • Endpoint: /appliance/{id}
  • Método: PUT
  • Descrição: Atualiza o registro de um eletrodoméstico no banco de dados. Todos os parâmetros são obrigatórios.
  • Corpo da Requisição: Dados do eletrodoméstico em formato JSON.
  • Resposta:
    • 200: Eletrodoméstico atualizado.
    • 422: O parâmetro não pode ser nulo.
    • 404: Eletrodoméstico não encontrado.
    • 400: Requisição incorreta.

About

Repositório para o Tech Challenge - Grupo 30

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published