Dev (Back & Front)ARTIGO

Usando SimpleMappingExceptionHandler do Spring

Já falei sobre a anotação @ExceptionHandler do Spring e como você pode usá-la para lidar com erros em um controlador como um controlador de base para dar a você um controle refinado sobre como lidar com erros em seu código. A pergunta para considerar agora é se você quer sempre esse controle refinado, para o qual eu estou supondo que, em determinadas circunstâncias, a resposta será não e, então, acomodar este Spring nos forneceu o SimpleMappingExceptionHandler.

O SimpleMappingExceptionHandler é uma implementação da classe HandlerExceptionResolver do Sprins, que, como já mencionei antes, o Spring usa para gerenciar exceções lançadas pelo seu código. O Spring possui uma limitação (se é que é isso), na medida em que carrega apenas uma implementação HandlerExceptionResolver a qualquer momento. A implementação padrão é AnnotationMethodHandlerExceptionResolver, o que obriga você a fazer uma escolha entre o uso de manipulação de handler fine-grained, tal como fornecido por AnnotationMethodHandlerExceptionResolver e manipulação de handler mais grosseiro fornecido pelo SimpleMappingExceptionHandler.

O cara do Spring tornou bastante simples a adição de um SimpleMappingExceptionHandler para seu aplicativo. Para demonstrar isso, em primeiro lugar, preciso de um controlador flakey que irá lançar uma handler para gente. O código abaixo lança uma IOException quando chamado…

@RequestMapping(value = "/ioexception", method = RequestMethod.GET) public String throwAnIOException(Locale locale, Model model) throws IOException {

logger.info("This will throw an IOException");

boolean throwException = true;

if (throwException) {
throw new IOException("This is my IOException");
}

return "home";
}

… e está garantido para quebrar um webapp.

Se você estivesse com a intenção de manter as coisas super simples, a etapa final seria adicionar o seguinte XML para o arquivo de configuração do Spring:

<beans:bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <beans:property name="exceptionMappings">
   <beans:map>
    <beans:entry key="java.io.IOException" value="io-exception" />
    <beans:entry key="java.lang.Exception" value="generic-error" />
   </beans:map>
  </beans:property>
 </beans:bean>

O XML acima mostra uma definição muito familiar do bean do Spring. O nome dele é “exceptionResolver“, implementado pela classe SimpleMappingExceptionResolver. Essa classe possui uma propriedade map, que é a parte mais interessante dessa definição, já que ela mapeia uma classe de exceção para um nome de exibição. Na amostra, estou mapeando IOException a uma exibição chamada “io-exception” e todas as outras exceções para uma exibição chamada “generic-error’. Note que SimpleMappingExceptionHandler segue o padrão das regras de manipulação de handler do Java, então quando eu digo “todas as outras exceções”, realmente quero dizer todas as exceções, exceto IOException e suas subclasses.

Embora isso encerre as atividades para uma implementação trivial, eu gostaria de acrescentar que prefiro estender o SimpleMappingExceptionHandler para que eu possa adicionar funcionalidades adicionais, tais como um registro de erro específico para a aplicação:

public class SampleExceptionHandler extends SimpleMappingExceptionResolver {

  private static final Logger logger = LoggerFactory.getLogger(SampleExceptionHandler.class);

  /**
   * Log the exception.
   *
   * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest,
   *      javax.servlet.http.HttpServletResponse, java.lang.Object,
   *      java.lang.Exception)
   */
  @Override
  protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
      Exception ex) {
    logger.error("A " + ex.getClass().getSimpleName() + " has occured in the application", ex);

    return super.doResolveException(request, response, handler, ex);
  }

}

Uma vez que tenha escrito o seu próprio handler de exceção, então tudo que você tem que fazer é modificar sua configuração do Spring de modo que ele seja pega por Spring quando o webapp for carregado:

<!-- Definition(s) for the SimpleMappingExceptionResolver -->
 <beans:bean id="exceptionResolver"
 >
  <beans:property name="exceptionMappings">
   <beans:map>
    <beans:entry key="java.io.IOException" value="io-exception" />
    <beans:entry key="java.lang.Exception" value="generic-error" />
   </beans:map>
  </beans:property>
 </beans:bean>

O código para este artigo está disponível aqui.

***

Texto original disponível em http://www.captaindebug.com/2012/02/using-springs-simplemappingexceptionhan.html

 

 

Trabalha na empresa Bet365 desde 2012. É um programador e desenvolvedor Java com certificado em Sun, com considerável experiência em todos os aspectos do ciclo de desenvolvimento em ambientes financeiros. Seus recentes projetos incluem o uso de Java, Spring e Oracle.

Ver perfil