emhk.

Tratamento de Erros em Controllers com Spring

21 de Aug, 2023Emanoel Henrick

Tratar os erros é uma das etapas mais importantes do projeto, nenhuma aplicação é a prova de falhas e algumas podem ser vitais. No Spring podemos tratar exceptions que são capturadas e entregam uma mensagem personalizada para o client de forma muito fácil. Podemos criar um método dentro da classe do Controller para devolver erros anotando com @ExceptionHandler(X) onde X é o .class do erro que será lançado:

@ExceptionHandler(NotFoundException.class) public ResponseEntity<?> handleNotFound(Exception ex, WebRequest req) { }

Quando anotado, o método receberá na chamada a exception que foi lançada e um objeto de requisição, sendo possível verificar os erros da aplicação e do client. Existindo apenas dentro da classe do Controller, apenas esse Controller vai tratar com esse método específico. Para ampliar o tratamento de erros para toda a aplicação podemos anotar uma classe com @ControllerAdvice e criar nossos métodos de tratamento da mesma forma que anteriormente:

@ControllerAdvice public class ApiExceptionHandlers { @ExceptionHandler(NotFoundException.class) public ResponseEntity<?> handleNotFound(Exception ex, WebRequest req) { } }

Dessa forma, se algo da aplicação inteira, que um Controller chama, lançar uma exception e ela estiver sendo tratada nessa classe, o Spring vai capturar e devolver corretamente para o client. Estendendo essa classe de ResponseEntityExceptionHandler, o Advice vai implementar alguns handlers já definidos pelo Spring por padrão.

Padronizando a resposta de todos os erros

A classe ResponseEntityExceptionHandler possui o método chamado HandleExceptionInternal, ele é responsável pela resposta dos erros e pode ser facilmente sobrescrito. Ele recebe alguns parâmetros para a construção das respostas como Exception, Body, Headers, Status e Request:

@Override protected ResponseEntity<Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request ) { // Implementação }

Dessa forma, em um método de erro podemos retornar a chamada desse método passando os dados necessários como o Body da resposta. Fazendo isso em todos os métodos, torna a aplicação mais estável e padronizada, facilitando o consumo da Api.