Construindo uma API REST com Java, Spring Boot e Hibernate
- #Spring Framework
- #Java
- #Hibernate
1. Analisando o contexto
O objetivo deste artigo está voltado para uma abordagem detalhada, sob o meu ponto de vista, da implementação de um projeto utilizando a linguagem Java com Spring Boot e o Hibernate como stacks de tecnologias fundamentais para uma API REST que controlará a aplicação de vacinas entre a população brasileira. A API contará apenas com: o cadastro de usuários, sendo obrigatórios: nome, e-mail, cpf e data de nascimento dos usuários, com restrição para o e-mail e cpf que precisam ser únicos, e o registro da aplicação de vacinas, sendo obrigatórios: nome da vacina, e-mail do usuário e a data em que foi aplicada. Ou seja, estes serão os únicos endpoints.
Com relação ao status code, a API deve retornar: 201 (Created) informando que a requisição foi bem sucedida e que um novo recurso foi criado, e 400 (Bad Request), indicando que houve algum erro na requisição.
2. Motivação para as tecnologias utilizadas
Além da linguagem Java, que tem sido o meu foco atualmente, selecionei alguns starters do Spring para a construção desta API, como: Spring Boot, Spring Web, Spring Data, PostgreSQL e a biblioteca Lombok.
2.1 Spring Boot
A escolha deste framework foi principalmente pelo poder que ele nos fornece, como: a rápida inicialização do projeto sem a necessidade de configurações de arquivos, possui um servidor de aplicações embutido, acesso a base de dados sem a necessidade de manipulação de grandes configurações.
Toda essa carga de ajustes fica por conta do próprio framework que traz essas funcionalidades auto-configuráveis, já que ele mesmo é quem gerencia as dependências de configuração do projeto se baseando no padrão de projetos de Inversão de Controle e Injeção de Dependência empregados no Spring Framework, e que são suficientes para por a aplicação web rodando. O benefício disso é que todo o processo de desenvolvimento fica bastante produtivo, já que o foco do desenvolvedor passa a ficar nas regras de negócio da aplicação.
2.2 Spring Web
Por tratar-se de uma API com padrão arquitetural REST, escolhi este framework devido ao suporte que ele fornece, tanto para o build de aplicações web quanto ao protocolo HTTP, já que requisições serão feitas para a API, além do Spring MVC que mantém a arquitetura do projeto mais organizada, separando as camadas da aplicação de acordo com a sua funcionalidade.
2.3 Spring Data JPA
Com este framework o acesso aos dados torna-se muito mais simples, através das anotações que fazem o mapeamento das classes Java às entidades do banco de dados, seus relacionamentos e à persistência dos dados. Através da implementação do Hibernate, que se baseia na especificação JPA, é possível utilizar métodos já prontos, seja para efetuar uma consulta, inserção, atualização ou deleção de dados, por exemplo. Além disso, há possibilidade da construção de novos métodos muito facilmente, seja por meio do padrão de nomes pré-estabelecidos do Spring Data ou na elaboração de queries mais específicas.
2.4 PostgreSQL
A opção por este SGBD foi principalmente por estar, atualmente, estudando as suas propriedades, é claro que existem outros como o SQL Server, que já tive uma certa experiência profissional atuando como dba, mas preferi utilizar o PostgresSQL pensando também na implementação do sistema na web através do Heroku, uma plataforma em nuvem que atua como um Pass, permitindo o deploy de aplicações back-end e que também tem sido um dos itens de estudo.
2.5 Lombok
Visando o aumento de produtividade, a adição desta ferramenta no projeto fornece diversos recursos que servem para simplificar a escrita dos códigos, reduzindo assim a necessidade de gerar manualmente (ou com atalhos da IDE) os famosos getters, setters, constructors, equals, build, dentre outros.
As anotações disponibilizadas por esta biblioteca permitem uma série de opções de personalização que se adapta a diversos contextos e padrões de projeto. Isto possibilita ter uma construção de classes mais limpas e de fácil manutenção, seja na refatoração do código, na inclusão de um atributo ou até mesmo na alteração do tipo de um atributo presente, tudo é refletido automaticamente por meio dessas anotações.
3. Estrutura do projeto
Baseado no padrão MVC, a estrutura [1]do projeto foi dividido em camadas, compostas pelos pacotes: entities, dto, repositories, resources e services justamente para separar a responsabilidade de cada uma de maneira que uma camada só tenha conhecimento da outra que a utilize.
Imagem 1 — Estrutura do projeto com Spring Web
O ORM foi definido nas classes que compõem a Model [2] através das anotações do Hibernate com as devidas constraints, como mostra a imagem abaixo:
Imagem 2 — Print da IDE, imagem proprietária.
No dto[3], além das validações necessárias para que o objeto esteja de acordo com o que foi definido, esta classe é a responsável por transportar os dados entre a View e o banco de dados.
Imagem 3 — Print da IDE, imagem proprietária
Nos repositórios[4] estão as interfaces, que necessitam apenas estender a JpaRepository e pronto, ela tem todos os métodos para fazer um CRUD sem nenhuma implementação a ser feita por mim, o Spring Data JPA em tempo de execução fará isso.
Imagem 4 — Print da IDE, autoria própria
Na service[5], faço uso do Lombok com a notação para tornar a classe elegível para um serviço e marco o ponto de injeção no construtor, através da anotação Autowired, para que o Spring Boot, em tempo de execução, promova uma instância desta classe em tempo de execução.
Imagem 5 — Print da IDE, autoria própria
Além disso, utilizo a biblioteca MapStruct [6] para fazer o mapeamento dos DTOs e poder converter em uma Model e vice-versa, ação necessária já que o Spring Data JPA recebe uma entity como parâmetro nos métodos do repositório.
Imagem 6 — Print da IDE, autoria própria
4. Implantação na Nuvem
Para fazer o deploy da aplicação na web escolhi o Heroku. Essas configurações abaixo informam a string de conexão com o banco de dados PostgresSQL provisionado na plataforma.
Imagem 7 — Configuração do arquivo application.properties
5. Testes realizados
Utilizei o Postman como ferramenta para testar as requisições na API disponibilizada no Heroku. As duas primeiras imagens mostram uma requisição bem sucedida, enquanto as outras duas violam a(s) constraint(s) definida(s).
Cadastro de uma pessoa
Registro de aplicação da vacina a uma pessoa
E-mail da pessoa não foi informado
O código fonte desta API encontra-se em: https://github.com/sidneymiranda/api-controle-vacinas
A aplicação no Heroku pode ser acessada aqui -> https://vaccine-control-api.herokuapp.com/