Uma característica comum em todos programas de computador é a necessidade de tratar exceções. Em Java as exceções são tratadas por um mecanismo de lançamento de exceções quando o erro é identificado. Spring Boot oferece diversas maneiras de tratar exceções. Uma forma simples e poderosa que usaremos aqui neste tutorial é a anotação @ControllerAdvice.

Esta anotação facilita nossa vida para lidar com todos os tipos de exceções em um local central em nossa aplicação. A facilidade está em não precisar capturar exceções em cada método ou classe separadamente, bastando apenas lançar a exceção no método e, em seguida, ela será capturada na classe central de tratamento de exceções anotada por @ControllerAdvice.

Considere o seguinte método de uma classe da camada de serviço

public Participante findById(Integer id) {
                return repository.findById(id)
                                 .orElseThrow(
                       () -> new ParticipanteNaoEncontradoException(id));
}

Caso o método findById não encontre o registro indentificado pelo parâmetro id, precisamos informar que o registro não foi encontrado. Então lançamos uma exceção chamada ParticipanteNaoEncontradoException, definida na classe abaixo.

public class ParticipanteNaoEncontradoException extends RuntimeException {

        public ParticipanteNaoEncontradoException(Integer id) {
                super("Participante não encontrado. ID = " + id);
        }
}

Quando o banco de dados não encontrar um determinado participante, o sistema lança a exceção ParticipanteNaoEncontradoException que tem no seu construtor um parâmetro para receber o id do registro buscado e assim você pode criar uma mensagem que será usada na resposta à requisição do cliente.

A classe que será criada para fazer o papel de central de tratamento de exceções deverá ser anotada com a anotação @ControllerAdvice. Nesta classe vamos usar as seguintes anotações em seus métodos:

Classe @ControllerAdvice

@ControllerAdvice
public class Exemplo{

        @ResponseBody
        @ExceptionHandler(ParticipanteNaoEncontradoException.class)
        @ResponseStatus(HttpStatus.NOT_FOUND)
        String participanteNaoEncontrado(ParticipanteNaoEncontradoException ex) {
                return ex.getMessage();
        }
        
        @ResponseBody
        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        String campoVazio(MethodArgumentNotValidException ex) {
                return ex.getLocalizedMessage();
        }
        
        @ResponseBody
        @ExceptionHandler(ErradoException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        String erro(ErradoException ex) {
                return ex.getLocalizedMessage();
        }
}

Código completo da aplicação