Desenvolver uma API para uma loja digital de games, permitindo cadastrar jogos e clientes, registrar compras e consultar informações da loja.
Estrutura, regras e requisitos do projeto
Desenvolver uma API para uma loja digital de games, permitindo cadastrar jogos e clientes, registrar compras e consultar informações da loja.
O objetivo é consolidar os principais conceitos estudados no curso utilizando um projeto pequeno e organizado, agora aplicado em uma API REST.
A proposta não é construir uma Steam completa. O desafio deve permanecer simples, com poucas entidades e regras de negócio claras.
O projeto deverá utilizar:
Spring Boot e a criação da API REST representam um pequeno passo além do conteúdo principal do curso. Não é necessário utilizar Spring Security, autenticação, paginação, arquitetura hexagonal, mensageria, Docker ou outros recursos avançados.
O projeto deverá utilizar JPA diretamente desde o início. Não é necessário criar uma versão anterior utilizando JDBC.
Uma loja digital deseja criar uma API simples para controlar seus jogos, clientes e compras.
A loja precisa conseguir:
Os dados deverão ser armazenados em um banco PostgreSQL utilizando JPA/Hibernate.
Cada jogo deverá possuir, no mínimo:
id titulo genero preco dataCadastro
O gênero deverá ser representado por um enum.
Exemplo:
ACAO AVENTURA RPG ESTRATEGIA ESPORTE CORRIDA
Você pode adicionar outros gêneros.
Cada cliente deverá possuir:
id nome email dataCadastro
Cada compra deverá possuir:
id cliente jogo dataCompra valorPago
Uma compra relaciona:
Cliente → Compra ← Jogo
Utilize os relacionamentos JPA adequados.
Ao realizar uma compra:
O valor da compra deve ficar armazenado na própria compra.
Isso significa que, se o preço do jogo mudar posteriormente, uma compra antiga continuará mostrando o valor pago no momento em que foi realizada.
A aplicação não utilizará menu no terminal.
As funcionalidades serão acessadas através de endpoints HTTP.
POST /jogos
GET /jogos
GET /jogos/{id}
Caso o jogo não exista, a aplicação deverá informar o erro adequadamente.
GET /jogos/busca?titulo=...
A busca poderá utilizar Optional para representar a possibilidade de o jogo não ser encontrado.
GET /jogos/genero/{genero}
GET /jogos/ordenados-por-preco
Do menor para o maior preço.
GET /jogos/mais-caro
GET /jogos/cadastrados-no-ano-atual
POST /clientes
GET /clientes
GET /clientes/{id}
GET /clientes/{id}/compras
GET /clientes/{id}/total-gasto
O resultado deve considerar o campo valorPago de cada compra.
POST /compras
Uma requisição poderá informar, por exemplo:
{ "clienteId": 1, "jogoId": 3 }
A aplicação deverá validar as regras antes de salvar a compra.
GET /compras
Além das operações principais, crie algumas consultas simples utilizando os recursos estudados durante o curso.
GET /relatorios/generos
Retorne apenas os gêneros que possuem jogos cadastrados.
Utilize um Set para representar valores sem repetição.
GET /relatorios/vendas-por-genero
Exemplo de resultado:
{ "RPG": 8, "ACAO": 5, "ESPORTE": 3 }
Um Map pode ser utilizado para representar essa informação.
Utilize Streams nas funcionalidades em que fizer sentido.
Alguns exemplos do próprio desafio:
Não é necessário transformar toda operação em Stream.
O objetivo é utilizá-las quando tornarem o código mais claro.
Utilize Optional principalmente nas operações de busca.
Exemplo:
buscar jogo por ID buscar cliente por ID buscar jogo pelo título
Quando o valor não existir, trate a situação adequadamente em vez de espalhar verificações de null pelo projeto.
Utilize as classes modernas de data do Java.
Sugestão:
LocalDate → cadastro de jogo e cliente LocalDateTime → realização da compra
Também deverá existir pelo menos uma consulta relacionada a datas:
Listar jogos cadastrados no ano atual.
Crie exceções para situações importantes da regra de negócio.
Exemplos:
JogoNaoEncontradoException ClienteNaoEncontradoException EmailJaCadastradoException JogoJaCompradoException PrecoInvalidoException
Não é necessário criar dezenas de exceções.
Crie apenas aquelas que ajudam a representar erros reais da aplicação.
As três classes principais deverão ser persistidas utilizando JPA:
Jogo Cliente Compra
Utilize:
@EntityA entidade Compra deverá possuir relacionamento com Cliente e Jogo.
Não é necessário criar relacionamentos bidirecionais se eles não forem necessários para resolver o desafio.
Utilize Spring Data JPA para acesso aos dados.
Exemplo conceitual:
JpaRepository<Jogo, Long> JpaRepository<Cliente, Long> JpaRepository<Compra, Long>
Aqui os Generics estudados no curso aparecem naturalmente através de tipos como:
List<Jogo> Optional<Jogo> Set<Genero> Map<Genero, Long> JpaRepository<Jogo, Long>
Não é necessário criar um repository genérico próprio.
Uma possível organização é:
src/main/java └── ... ├── controller ├── entity ├── enums ├── exception ├── repository └── service
Responsabilidades sugeridas:
Recebe as requisições HTTP e devolve as respostas.
Contém as regras de negócio.
Realiza o acesso aos dados através do JPA.
Representa os dados persistidos no banco.
Evite colocar todas as regras dentro dos Controllers.
A API deverá possuir documentação através do Swagger.
Utilize o springdoc-openapi.
Ao executar o projeto, o aluno deverá conseguir abrir o Swagger UI e testar os endpoints da aplicação.
O Swagger deverá permitir visualizar e executar, pelo menos:
Não é necessário criar uma configuração avançada do OpenAPI.
A documentação automática dos endpoints já é suficiente para o desafio.
O projeto deverá ser criado e executado utilizando Maven.
O pom.xml deverá conter apenas as dependências necessárias ao projeto, como:
Spring Web Spring Data JPA PostgreSQL Driver springdoc-openapi Spring Boot Test
Não utilize arquivos .jar adicionados manualmente ao projeto.
Crie testes unitários para algumas das principais regras de negócio.
Não é necessário testar todos os métodos do projeto.
Crie pelo menos 5 testes.
Alguns exemplos:
Dado um jogo com preço negativo Quando tentar cadastrá-lo Então uma exceção deverá ser lançada
Dado um cliente já cadastrado Quando outro cliente utilizar o mesmo e-mail Então o cadastro deverá ser rejeitado
Dado um ID de cliente inexistente Quando tentar realizar uma compra Então uma exceção deverá ser lançada
Dado um cliente que já possui determinado jogo Quando tentar comprá-lo novamente Então a compra deverá ser rejeitada
Dado um cliente com várias compras Quando consultar o total gasto Então a soma dos valores pagos deverá estar correta
Os testes devem focar principalmente na camada de serviço e nas regras de negócio.
Durante o desafio você terá oportunidade de utilizar, de forma natural:
List;Set;Map;equals, hashCode e toString;Optional;LocalDate;LocalDateTime;Além disso, o projeto introduz:
Para manter o desafio dentro do nível do curso, não é necessário implementar:
Esses recursos podem ser estudados posteriormente.
Caso finalize o desafio principal, escolha algumas funcionalidades extras.
Não é necessário implementar todas.
Mostre os três jogos com maior quantidade de compras.
Descubra qual cliente possui o maior valor total em compras.
Calcule o valor médio das compras realizadas na loja.
Crie um record para representar um resumo de compra.
Exemplo conceitual:
ResumoCompra( nomeCliente, tituloJogo, valorPago, dataCompra )
Ao final do desafio, deverá existir uma API capaz de executar o seguinte fluxo:
Cadastrar cliente ↓ Cadastrar jogo ↓ Realizar compra ↓ Salvar utilizando JPA ↓ Consultar compras ↓
O desafio não busca reproduzir uma plataforma real de venda de jogos.
O objetivo é construir uma aplicação pequena, organizada e completa o suficiente para consolidar os conceitos vistos no curso, utilizando Spring Boot como próximo passo na evolução do projeto.
Lembre-se que o intuito de um desafio é te impulsionar, por isso, dependendo do desafio, pode ser que você precise ir além do que foi discutido em sala de aula. Mas isso não é algo ruim: ter autonomia para buscar informações extras é uma habilidade muito valiosa e vai ser ótimo pra você treinar ela aqui com a gente!
E lembre-se: tenha calma! Enfrentar desafios faz parte do seu processo de aprendizado!
Após concluir o desafio, você deve enviar a URL do seu código no Github.
Além disso, que tal fazer um post no LinkedIn compartilhando o seu aprendizado e contando como foi a experiência?
É uma excelente forma de demonstrar seus conhecimentos e atrair novas oportunidades!
Obs: Se você se sentir à vontade, pode postar um print do resultado final e nos marcar! Vai ser incrível acompanhar a sua evolução! 💜
Desenvolver uma API para uma loja digital de games, permitindo cadastrar jogos e clientes, registrar compras e consultar informações da loja.
O objetivo é consolidar os principais conceitos estudados no curso utilizando um projeto pequeno e organizado, agora aplicado em uma API REST.
A proposta não é construir uma Steam completa. O desafio deve permanecer simples, com poucas entidades e regras de negócio claras.
O projeto deverá utilizar:
Spring Boot e a criação da API REST representam um pequeno passo além do conteúdo principal do curso. Não é necessário utilizar Spring Security, autenticação, paginação, arquitetura hexagonal, mensageria, Docker ou outros recursos avançados.
O projeto deverá utilizar JPA diretamente desde o início. Não é necessário criar uma versão anterior utilizando JDBC.
Uma loja digital deseja criar uma API simples para controlar seus jogos, clientes e compras.
A loja precisa conseguir:
Os dados deverão ser armazenados em um banco PostgreSQL utilizando JPA/Hibernate.
Cada jogo deverá possuir, no mínimo:
id titulo genero preco dataCadastro
O gênero deverá ser representado por um enum.
Exemplo:
ACAO AVENTURA RPG ESTRATEGIA ESPORTE CORRIDA
Você pode adicionar outros gêneros.
Cada cliente deverá possuir:
id nome email dataCadastro
Cada compra deverá possuir:
id cliente jogo dataCompra valorPago
Uma compra relaciona:
Cliente → Compra ← Jogo
Utilize os relacionamentos JPA adequados.
Ao realizar uma compra:
O valor da compra deve ficar armazenado na própria compra.
Isso significa que, se o preço do jogo mudar posteriormente, uma compra antiga continuará mostrando o valor pago no momento em que foi realizada.
A aplicação não utilizará menu no terminal.
As funcionalidades serão acessadas através de endpoints HTTP.
POST /jogos
GET /jogos
GET /jogos/{id}
Caso o jogo não exista, a aplicação deverá informar o erro adequadamente.
GET /jogos/busca?titulo=...
A busca poderá utilizar Optional para representar a possibilidade de o jogo não ser encontrado.
GET /jogos/genero/{genero}
GET /jogos/ordenados-por-preco
Do menor para o maior preço.
GET /jogos/mais-caro
GET /jogos/cadastrados-no-ano-atual
POST /clientes
GET /clientes
GET /clientes/{id}
GET /clientes/{id}/compras
GET /clientes/{id}/total-gasto
O resultado deve considerar o campo valorPago de cada compra.
POST /compras
Uma requisição poderá informar, por exemplo:
{ "clienteId": 1, "jogoId": 3 }
A aplicação deverá validar as regras antes de salvar a compra.
GET /compras
Além das operações principais, crie algumas consultas simples utilizando os recursos estudados durante o curso.
GET /relatorios/generos
Retorne apenas os gêneros que possuem jogos cadastrados.
Utilize um Set para representar valores sem repetição.
GET /relatorios/vendas-por-genero
Exemplo de resultado:
{ "RPG": 8, "ACAO": 5, "ESPORTE": 3 }
Um Map pode ser utilizado para representar essa informação.
Utilize Streams nas funcionalidades em que fizer sentido.
Alguns exemplos do próprio desafio:
Não é necessário transformar toda operação em Stream.
O objetivo é utilizá-las quando tornarem o código mais claro.
Utilize Optional principalmente nas operações de busca.
Exemplo:
buscar jogo por ID buscar cliente por ID buscar jogo pelo título
Quando o valor não existir, trate a situação adequadamente em vez de espalhar verificações de null pelo projeto.
Utilize as classes modernas de data do Java.
Sugestão:
LocalDate → cadastro de jogo e cliente LocalDateTime → realização da compra
Também deverá existir pelo menos uma consulta relacionada a datas:
Listar jogos cadastrados no ano atual.
Crie exceções para situações importantes da regra de negócio.
Exemplos:
JogoNaoEncontradoException ClienteNaoEncontradoException EmailJaCadastradoException JogoJaCompradoException PrecoInvalidoException
Não é necessário criar dezenas de exceções.
Crie apenas aquelas que ajudam a representar erros reais da aplicação.
As três classes principais deverão ser persistidas utilizando JPA:
Jogo Cliente Compra
Utilize:
@EntityA entidade Compra deverá possuir relacionamento com Cliente e Jogo.
Não é necessário criar relacionamentos bidirecionais se eles não forem necessários para resolver o desafio.
Utilize Spring Data JPA para acesso aos dados.
Exemplo conceitual:
JpaRepository<Jogo, Long> JpaRepository<Cliente, Long> JpaRepository<Compra, Long>
Aqui os Generics estudados no curso aparecem naturalmente através de tipos como:
List<Jogo> Optional<Jogo> Set<Genero> Map<Genero, Long> JpaRepository<Jogo, Long>
Não é necessário criar um repository genérico próprio.
Uma possível organização é:
src/main/java └── ... ├── controller ├── entity ├── enums ├── exception ├── repository └── service
Responsabilidades sugeridas:
Recebe as requisições HTTP e devolve as respostas.
Contém as regras de negócio.
Realiza o acesso aos dados através do JPA.
Representa os dados persistidos no banco.
Evite colocar todas as regras dentro dos Controllers.
A API deverá possuir documentação através do Swagger.
Utilize o springdoc-openapi.
Ao executar o projeto, o aluno deverá conseguir abrir o Swagger UI e testar os endpoints da aplicação.
O Swagger deverá permitir visualizar e executar, pelo menos:
Não é necessário criar uma configuração avançada do OpenAPI.
A documentação automática dos endpoints já é suficiente para o desafio.
O projeto deverá ser criado e executado utilizando Maven.
O pom.xml deverá conter apenas as dependências necessárias ao projeto, como:
Spring Web Spring Data JPA PostgreSQL Driver springdoc-openapi Spring Boot Test
Não utilize arquivos .jar adicionados manualmente ao projeto.
Crie testes unitários para algumas das principais regras de negócio.
Não é necessário testar todos os métodos do projeto.
Crie pelo menos 5 testes.
Alguns exemplos:
Dado um jogo com preço negativo Quando tentar cadastrá-lo Então uma exceção deverá ser lançada
Dado um cliente já cadastrado Quando outro cliente utilizar o mesmo e-mail Então o cadastro deverá ser rejeitado
Dado um ID de cliente inexistente Quando tentar realizar uma compra Então uma exceção deverá ser lançada
Dado um cliente que já possui determinado jogo Quando tentar comprá-lo novamente Então a compra deverá ser rejeitada
Dado um cliente com várias compras Quando consultar o total gasto Então a soma dos valores pagos deverá estar correta
Os testes devem focar principalmente na camada de serviço e nas regras de negócio.
Durante o desafio você terá oportunidade de utilizar, de forma natural:
List;Set;Map;equals, hashCode e toString;Optional;LocalDate;LocalDateTime;Além disso, o projeto introduz:
Para manter o desafio dentro do nível do curso, não é necessário implementar:
Esses recursos podem ser estudados posteriormente.
Caso finalize o desafio principal, escolha algumas funcionalidades extras.
Não é necessário implementar todas.
Mostre os três jogos com maior quantidade de compras.
Descubra qual cliente possui o maior valor total em compras.
Calcule o valor médio das compras realizadas na loja.
Crie um record para representar um resumo de compra.
Exemplo conceitual:
ResumoCompra( nomeCliente, tituloJogo, valorPago, dataCompra )
Ao final do desafio, deverá existir uma API capaz de executar o seguinte fluxo:
Cadastrar cliente ↓ Cadastrar jogo ↓ Realizar compra ↓ Salvar utilizando JPA ↓ Consultar compras ↓
O desafio não busca reproduzir uma plataforma real de venda de jogos.
O objetivo é construir uma aplicação pequena, organizada e completa o suficiente para consolidar os conceitos vistos no curso, utilizando Spring Boot como próximo passo na evolução do projeto.
Lembre-se que o intuito de um desafio é te impulsionar, por isso, dependendo do desafio, pode ser que você precise ir além do que foi discutido em sala de aula. Mas isso não é algo ruim: ter autonomia para buscar informações extras é uma habilidade muito valiosa e vai ser ótimo pra você treinar ela aqui com a gente!
E lembre-se: tenha calma! Enfrentar desafios faz parte do seu processo de aprendizado!
Após concluir o desafio, você deve enviar a URL do seu código no Github.
Além disso, que tal fazer um post no LinkedIn compartilhando o seu aprendizado e contando como foi a experiência?
É uma excelente forma de demonstrar seus conhecimentos e atrair novas oportunidades!
Obs: Se você se sentir à vontade, pode postar um print do resultado final e nos marcar! Vai ser incrível acompanhar a sua evolução! 💜