DEV Community

loading...

Spring - Exception Handler

Wesley Egberto
Computer scientists working with Java and Angular. Always exploring Angular, Java, Python and AI. Passionate about math, physics and AI.
Updated on ・4 min read

Para começar, certifique que tem a dependência no seu POM ou Gradle.

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

Tratamento Padrão

O tratamento de erro padrão do Spring oferece uma forma out-of-the-box que responde dependendo do Content-type.

  • Caso o Content-Type seja text/html o tratamento de erro irá encaminhar o request para uma página de erro White label error page. Caso você adicione um mapping específico para "/error" então o Spring utilizará esse cara ao invés do White label error page.
  • Caso o Cotent-type seja JSON o tratamento de erro retornará um objeto com as seguintes propriedades: error, message, path, status timestamp.

A página de erro pode ser desabilitada ao adicionar a linha abaixo no seu .properties.

server.error.whitelabel.enabled=false

Tratamento Customizado

Spring fornece uma maneira bem simples e limpa que nos permite tratar exceptions que ocorrem durante a execução de um método do nosso controller MVC/REST. Podemos tratar e retornar um JSON ou encaminhar para uma página especifica de erro.

Usando @ResponseStatus

A primeira forma nos permite tratar apenas o retorno do nosso controller. Na nossa exception adicionamos a anotação @ResponseStatus que permite customizar o HTTP status e o header reason do nosso response. O response ainda será retornado utilizando o tratamento padrão (error page ou JSON padrão) caso não tenha sido definido uma págian ou um handler.

@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "We can't handle your request =(")
public class CustomException extends RuntimeException {
}
@RestController
@RequestMapping("/api")
class HelloController {
   @GetMapping("custom")
   public String customResponseFailure() {
      throw new CustomException();
   }
}

Quando uma exception do tipo CustomException for lançada o tratamento padrão de erro do Spring entrará em ação mas utilizará o nosso HTTP status e adicionará o header reason no response.

Usando @ExceptionHandler

A segunda forma mais interessante é criar  um método para tratar exceptions específicas. Esta forma nos permite cria um método para tratar a exception adequadamente e então encaminhar para uma página específica ou retornar uma entidade customizada.

Se anotarmos um método de uma controller então todos as exceptions daquela controller que não tenham sejam anotadas com @ResponseStatus serão tratadas por ela mas caso queiramos criar um handler para todas as controllers precisamos criar  um Advice.

Temos dois tipos de Advice: ControllerAdviceRestControllerAdvice. O ControllerAdvice segue a semântica do @Controller, então no fim do tratamento ele redireciona para a view definida. O RestControllerAdvice segue o @RestController, então retorna seu objeto serializado direto no response.

Controller com @ExceptionHandler

@Controller
@RequestMapping("/web")
public class PageController {
   @GetMapping("customerrorpage")
   public String customErrorPage() {
      throw new NumberFormatException("We can't format your number");
   }

   @ExceptionHandler(NumberFormatException.class)
   public ModelAndView handleNumberFormatException(NumberFormatException nfex) {
      ModelAndView model = new ModelAndView("custom_error");
      model.addObject("errorMessage", nfex.getMessage());
      return model;
   }
}

Classe com ControllerAdvice e RestControllerAdvice

@ControllerAdvice
public class CustomPageExceptionHandler {
   @ExceptionHandler(NumberFormatException.class)
   public ModelAndView handleNumberFormatException(NumberFormatException nfex) {
      ModelAndView model = new ModelAndView("custom_error");
      model.addObject("errorMessage", nfex.getMessage());
      return model;
   }
}

@RestControllerAdvice
public class CustomJsonExceptionHandler {
   // podemos usar também @ResponseStatus
   @ResponseStatus(code =  HttpStatus.BAD_REQUEST)
   @ExceptionHandler(IllegalStateException.class)
   public String handleInvalidStateException(IllegalStateException rex, HttpServletResponse response) {
      System.err.println("Hey dev! We got an illegal state: " + rex.getMessage());
      response.addHeader("Reason", rex.getMessage());
      return "Sorry, we got some problem =(";
   }
}

Para maiores informações acessar links [2] e [3].

Exemplo

Projeto com exemplos: GitHub

Notas:

  • Ao usar Spring Bott com custom error page lembre-se de empacotar com WAR e adicionar deps do tomcat (veja [1])

Links:

  • [1] https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-jsp-limitations
  • [2] https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
  • [3] https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling-custom-error-pages

Discussion (0)