[quote=Leonardo Gaona]Olá pessoal,
Estou desenvolvendo uma aplicação web com JSF 2, Spring e JPA 2 rodando em um Tomcat. Andei dando uma lida sobre tratamento de exceções até que vi o Fault Barrier Pattern. Gostaria da opinião de vocês sobre o modo de tratar as exceções:
A aplicação está divida em 3 camadas: Controllers > Services > DAOs
A idéia é a seguinte: todos os componentes na camada de Serviço e Persistência podem lançar exceções, mas ela seriam apenas capturadas no Controller (para casos em que não há como se recuperar do erro ou nada precise ser realizado). Assim, o Controller apenas loga (se necessário) e exibe uma mensagem de erro ao usuário do front-end.
Exceptions que necessitariam de um código específico (IOExceptions, na qual precisamos fechar ou dar flush em algum buffer ou re-tentar executar uma query durante uma DataAccessException ou NoResultFoundException) seriam tratadas na própria camada, e depois “encapadas” em uma RuntimeException a ser capturada apenas no Controller com a mensagem ao usuário, ou apenas seriam tratadas e o fluxo do programa continuaria normalmente.
Para não repetir uma porrada de try/catchs nos métodos do Controller, estava pensando em utilizar o Strategy Pattern para o tratamento de exceções. Algo mais ou menos assim:
public interface ExceptionHandler<T extends Exception> {
void handle(T e);
}
E no controller eu teria uma fábrica para recuperar a implementação correta de ExceptionHandler, e invocaria apenas handle(). Assim eu conseguiria encapsular os diversos tipos de tratamento de exceção diferentes sem colocar n catchs.
Parece uma má idéia?
Combinar os dois padrões seria algo desnecessário?
Algum de vocês já aplicou algum padrão melhor para exceções? Poderia me mostrar ou sugerir melhorias?
[/quote]
O ExceptionHandler pode tratar todas as exceções. Aquilo que vc chama de factory é na realidade um locator. Pode usar isso, mas é muito mais complexo do que necessário (mas é possivel)
Dê uma olhada em
http://www.javabuilding.com/academy/java-language/excecoes-conceitos.html
http://www.javabuilding.com/academy/java-language/excecoes-boas-praticas.html
Você deve criar uma categoria de exceções para cada camada do seu sistema. As classes publicas da camada, devem controlar as exceções dando sempre try-catch e chamando o exceptionhandler (que pode ser apenas um método dentro da classe ) Se o método pode tratar a exceção, simplesmente o faz e não chamada o exception handler.
Um melhor codigo para o excption handler é assim
protected LayerSpecificException handle(Exception e);
Onde LayerSpecificException é classe de Exceção que é mãe de todas as classes de exceção daquela camada. Por exemplo, na camada de serviço teriamos um ServiceException, no acesso dados um DataAccessException, etc…
Usa assim
public void algumMetodo(String parametros){
try {
// faz algo
} catch (ExceptionQueEuSeiResolver e) {
// faço tratamento e não relanço exceção nenhuma
} catch (Exception e){
// todas as outras
return handleException(e);
}
}
O exception handler funciona assim :
- se a exceção já é uma exceção da camada corrent , simplesmente devolve essa e pronto
- se é possivel converter a exceção recebida numa exceção da hierarquia das exceções da camada, faça isso e retorne.
- se não é possivel analizar a exceção, encapsule ela em uma instancia de LayerSpecificException e retorne.
por exemplo
protected ServiceException handle(Exception e){
if (e instanceof ServiceException ){
return (ServiceException ) e;
}
if (e instanceof XPTOException ){
// por regra de negocio eu sei que XPTOEception significa que não ha comunicaçao com um serviço XPTO que estou usando, então eu
// transformo isso para
return new ExternalServiceComunicationImpossible(e); // repare que mantenho referencia à exceção original. a causa é encapsulada para apecer no stacktrace depois
}
// o resto dou um tratamento apenas de encapsular
return new ServiceException(e);
}
O ExceptionHandler também é um padrão. Vc pode usar o Strategy para implementá-lo, mas normalmente não faz muito sentido ( O que faria sentido seria um Chain of Responsability) e não é muito prático.
Um simples método pode resolver.
E como vc bem disse apenas o ExceptionHandler da camada mais exterior ao sistema é que loga o exception. Esta regra pode ser quebrada se ha comunicação entre nodos. E só na camada de UI que a exceção vira uma mensagem para o usuário. Por causa disso é normal que as exceçtions sejam mais completas com informações não apenas do que de erro mas parâmetros também. I18n pode ser necessário também.