Exception Handling com Spring

Gustavo Navarro
Prolog App
Published in
3 min readJul 5, 2021

Exceptions ocorrem em todo projeto e lidar com elas é necessário e inevitável. Contudo, nem sempre essas exceptions são algo ruim. No geral, precisamos conseguir prever os possíveis erros e, com isso, utilizá-los para prover respostas indicativas e legíveis para os clients que requisitam em nossa API.

Para quem utiliza o Spring, tem a sorte de o próprio framework prover uma forma de lidar de forma simples com essa situação, e, neste artigo, focaremos em exemplificar como conseguimos lidar com exceptions utilizando o Spring e suas ferramentas.

Criando o DTO padrão do projeto para mapear as exceptions

Para podermos tornar nosso json de retorno em caso de exceptions legível e utilizável para o client que requisita, precisamos padronizar e modelar um objeto com as informações sobre a nossa exception. Aqui pro artigo, criei um DTO bem semelhante ao que usamos aqui na empresa, mas um pouco mais simplificado:

Este DTO contém as informações principais que serão necessárias ao client:

  • statusCode: o http code resultante.
  • message: uma mensagem que pode ser usada para exibir para o usuário.
  • debugMessage: uma mensagem para auxiliar desenvolvedores a entender mais a fundo qual o problema. Por aqui, utilizamos a mensagem que vem nas exceptions das libs que usamos.

Por padrão, este será sempre o objeto que retornaremos para o client. Dessa forma ele já sabe o que esperar e quando receber, vai saber como usar. Além disso, caso venha a receber algo diferente disso, ele conseguirá identificar que algum problema não previsto está ocorrendo.

Usando exceptions customizadas

Todas as RuntimeExpcetion’s não precisam de um try catch e nem um throws na declaração do método. Dessa forma, conseguimos criar exceptions customizadas que estendem a RuntimeException e utilizá-las para lançar erros durante o fluxo do nosso código.

Para demonstração, foi criada uma exception de exemplo que será mapeada e lançada durante o fluxo de código para demonstração:

Tudo pronto, vamos ao mapeamento!

Já temos nossa exception customizada e também já temos um DTO de retorno. Agora precisamos apenas mapear o que ocorrerá quando a exception ExampleErrorException for lançada e pronto!

Para tanto, criaremos uma classe anotada com @RequestControllerAdvice, do Spring. Abaixo da classe explicarei o uso de cada anotação.

  • @RestControllerAdvice: a anotação indica que esta é uma classe de mapeamento de erros.
  • @ExceptionHandler: a anotação indica com qual exception o método em questão irá lidar. No parâmetro da declaração dessa anotação sempre informaremos a classe em si.
  • @ResponseStatus: aqui indicamos qual será o http status code que será retornada ao client.

O retorno de cada método de mapeamento deverá ser a classe que será transformada em Json. No nosso caso, criamos uma padrão (ApiError). Então, quando a exception ExampleErrorException for lançada, cairemos diretamente no método handleExampleErrorException e o retorno dele será transformado em json e enviado ao client.

Na nossa classe, mapeamos apenas a ExampleErrorException, mas inúmeras exceptions podem ser mapeadas, bastando apenas declarar mais um método com as anotações necessárias.

Testando e vendo o resultado

Para testar o mapeamento realizado, foi criado um controller e um service de exemplo:

Service:

Fazendo um GET usando o postman na url http://localhost:8080/medium-article/example, obtemos o seguinte json no retorno:

Por fim…

Essa é apenas uma das formas de lidar com exceptions. Como é feito na sua empresa? Por quais situações já acabou passando? Conta pra gente que com certeza temos algo a aprender juntos!

Neste link é possível acessar o projeto de exemplo completo e funcional.

--

--