Spring Validation: o que é e vantagens

Neste artigo você vai ver:

Nesse artigo vou abordar o que é o Spring Validation e como ele nos auxilia nas validações da nossa aplicação.

Tem interesse em seguir uma das boas práticas mais utilizadas pelas pessoas desenvolvedoras de software? Então continue lendo!

O que é Spring Validation?

Vocês devem estar se perguntando agora, afinal, o que é o Spring Validation? Bom, a resposta é simples: sempre que estamos realizando o desenvolvimento de alguma aplicação, precisamos que ela nos responda o mais rápido possível caso tenha algum problema com a nossa requisição. Dessa forma, o Spring Validation veio para nos ajudar com essa situação!

Vamos imaginar o seguinte cenário: 

Estamos construindo uma página WEB e ela irá consumir a nossa aplicação. Sendo assim, essa página faz uma requisição para nossa aplicação passando o nome de uma pessoa consumidora com um total de 40 caracteres e, rapidamente, a aplicação retorna uma falha nos informando que o permitido é de 35 caracteres. 

Então, essa validação poderá ser feita utilizando o Spring Validation. No entanto, daqui a pouco a gente chega lá. 

O princípio do Fail Fast

Acredito que não podemos falar de Spring Validation, sem mencionarmos o princípio do Fail Fast. Esse princípio é muito utilizado por devs que dizem que caso tenha algum problema na aplicação, você precisa falhar rápido. Para que a gente consiga deixar de uma forma mais ilustrativa, vamos verificar os seguintes blocos de código.

Cenário 1:

public DetalheProduto salvar(DetalheProdutoDTO detalheProdutoDTO, Long idProduto) {
 DetalheProduto detalheProduto = detalheProdutoDTO.toModel();
 Produto produto = this.produtoRepository.consultar(idProduto);
 
 if (produto == null) {
 throw new ProdutoNaoEncontrado(“Produto não encontrado");
 }

 detalheProduto.setProduto(produto);

 return this.detalheProdutoRepository.salvar(detalheProduto);
}

Em primeiro lugar, este cenário nos possibilita observar que a primeira coisa que estamos fazendo é a realização da conversão da classe DetalheProdutoDTO para DetalheProduto.

Logo em seguida, estamos consultando um Produto pelo seu determinado idProduto e finalmente verificando se o Produto foi, de fato, encontrado.

Esse código funciona? Sim, ele funciona. 

Porém, será que é o mais performático? Não. Como podemos observar, estamos primeiro fazendo a conversão de uma classe e seus vários atributos, para depois disso fazermos a consulta de um Produto que é uma dependência para o DetalheProduto e finalmente settando a sua informação. 

Adiante, vamos ver um segundo cenário, com um código bem parecido com o anterior.

Cenário 2:

public DetalheProduto salvar(DetalheProdutoDTO detalheProdutoDTO, Long idProduto) {
 Produto produto = this.produtoRepository.consultar(idProduto);
 
 if (produto == null) {
 throw new ProdutoNaoEncontrado(“Produto não encontrado");
 }


 DetalheProduto detalheProduto = detalheProdutoDTO.toModel();

 detalheProduto.setProduto(produto);

 return this.detalheProdutoRepository.salvar(detalheProduto);
}

Como podemos ver nesse segundo cenário, a única alteração que realizamos foi de jogar a conversão de DetalheProdutoDTO para DetalheProduto. No entanto, após fazermos a consulta e verificar que de fato aquele Produto existe. Isso é uma forma de aplicarmos o princípio de Fail Fast.

Ifs, Ifs e mais Ifs!!!

Quem nunca precisou inserir alguns Ifs na sua aplicação para poder validar campos obrigatórios e outras informações ao receber uma requisição? Pois então, agora iremos ver a verdadeira vantagem de utilizarmos o Spring Validation. 

Voltando para aquele cenário que conversamos sobre a página WEB, a gente precisava fazer uma verificação se o Nome do Usuário não deveria passar de 35 caracteres. Para isso também iremos precisar validar se o campo também não está nulo, vamos ver como faríamos isso sem o Spring Validation?

public void validar(UsuarioDTO usuario) {
 if (usuario.getNome() == null) {
throw new BadRequestException(“O nome é obrigatório");
 }


 if (usuario.getNome().length() > 35) {
    throw new BadRequestException(“O nome deverá ter no máximo 35 caracteres");
 }


}

Como podemos observar, precisamos utilizar dois Ifs para fazermos essas simples validações. Agora imagina se o nosso formulário fosse ainda maior? Teríamos que colocar IFs, IFs e mais IFs? A resposta é não!

Vamos ver uma simples demonstração do poder do Spring Validation.

Aplicando o Spring Validation

Agora chegou o momento mais esperado, a hora que iremos utilizar o Spring Validation na nossa aplicação!!! 

Para que você possa acompanhar o que iremos fazer nas próximas etapas, adicionaremos algumas dependências no nosso projeto dentro do pom.xml da sua aplicação:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</artifactId> 
</dependency>

Dessa forma, após inserirmos a dependência acima, já estamos preparados para o uso do Spring Validation. Agora para fazermos um comparativo com os Ifs que realizamos anteriormente, vamos criar o mesmo exemplo.

Classe UsuarioDTO:

public class UsuarioDTO {
 @NotBlank(message = “O nome é obrigatório")
 @Length(min = 3, max = 35, message = “O nome deverá ter no máximo {max} caracteres")
 private String nome;
}

Como podemos observar, não precisamos realizar nenhum If na nossa aplicação para verificar se o nome está, de fato, preenchido e se ele está ultrapassando os 35 caracteres.

Isso, simplesmente porque utilizamos duas anotações do Spring Validation: 

@NotBlank que irá verificar se o campo está preenchido como nulo ou vazio. 

@Length que irá validar a quantidade mínima e máxima de caracteres

Como podemos observar, também passamos dentro da nossa mensagem um valor chamado {max}. Dessa forma, estamos referenciando o atributo max da nossa anotação e deixando a mensagem dinâmica.

Contudo, ainda não acabou! Para que de fato essas validações sejam executadas, precisamos utilizar a anotação @Valid que irá executar a validação de todas as anotações da nossa classe. Isso poderá ser visto no exemplo abaixo:

Classe UsuarioController:

public class UsuarioController {
 public UsuarioDTO salvar (@Valid UsuarioDTO usuarioDTO) {
 // Faça alguma coisa...
}
}

Dessa forma todas as validações irão ser executadas! =)

Anotações mais comuns no Spring Validation

Agora vamos citar algumas anotações que são bem comuns de serem vistas em projetos que utilizam o Spring Validation.

@NotNull -> Válida se o campo está nulo.
@NotEmpty -> Válida se o campo está vazio.

@NotBlank -> Válida se o campo está nulo ou vazio.

@Past -> Válida se a data é hoje ou qualquer dia antes de hoje.
@Future -> Válida se a data é hoje ou qualquer dia depois de hoje.
@Length -> Válida o tamanho mínimo e máximo de um campo.
@Max -> Válida o tamanho máximo de um campo.
@Min -> Valida o tamanho mínimo de um campo.

Há várias anotações que vieram para poder facilitar a nossa vida, como, por exemplo, @Cpf.

Além disso, conseguimos definir um GroupSequence para validar qual anotação irá ser executada primeiro.

Utilizando o Group Sequence

Antes de começarmos a falar sobre GroupSequence, gostaria de agradecer ao meu amigo de trabalho Paulo Ricardo. Juntos procuramos e estudamos essa solução para que pudéssemos resolver o nosso problema da melhor forma possível.

Então vou trazer para vocês um cenário real que aconteceu com a gente em um projeto aqui da ZUP.

Nesse projeto, tínhamos uma anotação customizada. Isso mesmo pessoal, além de todas as anotações que o Spring Validation consegue nos propor, também conseguimos criar as nossas próprias anotações.

Inclusive, se você tem interesse que a gente fale sobre Anotações Customizadas, deixe abaixo nos comentários.

Assim, seguindo com a nossa anotação, tínhamos uma anotação chamada @OneOf que validaria se aquele valor pertencia a um determinado grupo de valores, então fizemos a seguinte implementação:

public class ProdutoDTO {
 @NotBlank(message = “A categoria é obrigatória")
 @OneOf(types = {“Limpeza", “Alimentação” })
 private String categoria;
}

Assim, imaginamos que primeiro deveria executar o @NotBlank e logo em seguida deveria executar a anotação @OneOf, só que dessa forma o @NotBlank e a @OneOf iriam executar ao mesmo tempo, dando um NullpointerException na anotação do @OneOf.

Para que pudéssemos resolver esse problema, precisávamos definir um @GroupSequence em cima da nossa classe e utilizarmos o groups, que é um dos parâmetros que podemos passar dentro das nossas anotações, como podemos ver, por exemplo, abaixo:

@GroupSequence({FieldGroup.class, CustomGroup.class, ProdutoDTO.class})
 public class ProdutoDTO {
 @NotBlank(message = “A categoria é obrigatória", groups = FieldGroup.class)
 @OneOf(types = {“Limpeza", “Alimentação” }, groups = CustomGroup.class)
 private String categoria;
}

Como vocês podem ver, a gente precisou criar duas novas classes/interfaces, uma chamada FieldGroup e outra chamada CustomGroup

Sendo assim, conseguimos agrupar as nossas validações em um grupo e executarmos em uma determinada sequência. Isso foi algo muito bacana e me ajudou muito nos projetos que já trabalhei.

Antes de concluirmos, que tal assinar a nossa newsletter e receber conteúdos como esse no seu e-mail? 

Banner com a identidade visual da Zup, nele está escrito Assine nossa Newsletter, os melhores conteúdos sobre carreira e tecnologia no seu e-mail. No final, está um botão com "assinar agora".

Conclusão

Neste artigo falamos sobre o Spring Validation e o seu poder para nos auxiliar nas validações da nossa aplicação. 

Espero que você tenha gostado e qualquer dúvida ou sugestão é só comentar aqui abaixo! =)

Referências:

Elvenite – What is Fail Fast?

Baeldung – Validation in Spring Boot

capa do artigo spring validation
Foto - Gabriel Augusto
Desenvolvedor de software
Desenvolvedor de software apaixonado por novas tecnologias, sempre disposto a estar aprendendo novidades e passar o conhecimento para outras pessoas, através de artigos, conversas do dia a dia e etc. Busco sempre evoluir a minha carreira como desenvolvedor.

Artigos relacionados

Capa do artigo em foto com duas pessoas escrevendo códigos em frente a dois notebooks.
Back-End
Postado em:
Imagem capa do conteúdo sobre Framework NestJS com a foto de uma mulher de cabelos trançados de costas de frente para um computador com códigos.
Back-End
Postado em:
Imagem capa do conteúdo sobre testes unitários, onde uma pessoa branca está em pé, segurando um notebook aberto dentro de um data center.
Back-End
Postado em:

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.