DEV Community

Cover image for Quando usar Jakarta Validation
Uiratan Cavalcante
Uiratan Cavalcante

Posted on

Quando usar Jakarta Validation

As anotações de validação do Jakarta Validation (Bean Validation) (@NotBlank, @Size, @Email, etc.) fazem mais sentido quando queremos validar dados fora da entidade, ou seja, antes mesmo de criar um objeto de domínio. Isso geralmente acontece em camadas externas da aplicação, como:

  • Entrada de dados via API (DTOs no Controller)
  • Formulários em aplicações web
  • Importação de dados de fontes externas

📌 Quando usar as anotações de validação?

1️⃣ Validação de entrada em APIs (DTOs no Controller) ✅

Essa é a melhor prática para evitar que dados inválidos cheguem à camada de domínio.

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public class AutorRequest {
    @NotBlank(message = "O nome é obrigatório")
    private String nome;

    @NotBlank(message = "O email é obrigatório")
    @Email(message = "Formato de email inválido")
    private String email;

    @NotBlank(message = "A descrição é obrigatória")
    @Size(max = 400, message = "A descrição não pode passar de 400 caracteres")
    private String descricao;

    public Autor toModel() {
        return new Autor(nome, email, descricao); // Criação segura, pois os dados já foram validados
    }
}
Enter fullscreen mode Exit fullscreen mode

E no Controller, usamos @Valid para garantir que os dados recebidos estejam corretos:

import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/autores")
public class AutorController {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void cadastrarAutor(@RequestBody @Valid AutorRequest autorRequest) {
        Autor autor = autorRequest.toModel();
        System.out.println("Autor cadastrado: " + autor.getNome());
    }
}
Enter fullscreen mode Exit fullscreen mode

Vantagem: A validação ocorre antes de criar o objeto Autor, evitando que ele seja construído em estado inconsistente.


2️⃣ Validação de formulários em aplicações web ✅

Se estivermos lidando com uma aplicação web (exemplo: Spring MVC com Thymeleaf), podemos validar os dados de um formulário automaticamente.

@Controller
@RequestMapping("/autores")
public class AutorController {

    @PostMapping
    public String cadastrarAutor(@ModelAttribute @Valid AutorRequest autorRequest, BindingResult result) {
        if (result.hasErrors()) {
            return "formulario"; // Retorna o formulário com erros
        }

        Autor autor = autorRequest.toModel();
        System.out.println("Autor cadastrado: " + autor.getNome());
        return "redirect:/sucesso";
    }
}
Enter fullscreen mode Exit fullscreen mode

Aqui, o BindingResult armazena os erros e pode ser usado para exibir mensagens ao usuário.


3️⃣ Validação automática em métodos de serviços com @Validated

Se quisermos validar parâmetros de um método de serviço, podemos usar @Validated diretamente:

import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotBlank;

@Service
@Validated
public class AutorService {

    public void criarAutor(@NotBlank String nome) {
        System.out.println("Criando autor: " + nome);
    }
}
Enter fullscreen mode Exit fullscreen mode

Se nome for nulo ou vazio, uma ConstraintViolationException será lançada automaticamente.


🚀 Quando NÃO faz sentido usar as anotações de validação?

🔴 Dentro do construtor de uma entidade de domínio → Porque o Jakarta Validation não impede diretamente a criação de um objeto inválido.

🔴 Se você precisar de validação imediata e rápida → Aqui faz mais sentido usar Assert do Spring (org.springframework.util.Assert).

Exemplo usando Assert no construtor da entidade:

import org.springframework.util.Assert;
import java.time.Instant;

public class Autor {

    private final String nome;
    private final String email;
    private final String descricao;
    private final Instant instanteCriacao;

    public Autor(String nome, String email, String descricao) {
        Assert.hasText(nome, "O nome é obrigatório");
        Assert.hasText(email, "O email é obrigatório");
        Assert.hasText(descricao, "A descrição é obrigatória");
        Assert.isTrue(descricao.length() <= 400, "A descrição não pode passar de 400 caracteres");

        this.nome = nome;
        this.email = email;
        this.descricao = descricao;
        this.instanteCriacao = Instant.now();
    }
}
Enter fullscreen mode Exit fullscreen mode

Aqui o erro ocorre imediatamente se o nome, e-mail ou descrição forem inválidos.


🎯 Conclusão

Situação Melhor abordagem
Evitar dados inválidos antes da criação do objeto Jakarta Validation (@NotBlank, @Valid) no DTO
Evitar objetos inconsistentes no momento da criação Spring Assert no construtor
Validar dados recebidos via API DTO + @Valid no Controller
Validar parâmetros de métodos em services @Validated no Service

Se a validação deve ocorrer antes da criação do objeto, use DTOs e @Valid.

Se a validação deve ocorrer no momento da criação do objeto, use Assert do Spring.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay