Introducao ao ProblemaExistem ocasioes que temos que fazer validacoes de entidades, e no caso de inconsistencias nas entradas informados pelo usuario, interromper o fluxo e mostrar uma mensagem alertando sobre o erro. E o caso de o usuario tentar inserir um produto com o mesmo nome de outro ja cadastrado, e isso nao esteja de acordo com as regras de negocio. Em geral, a solucao na camada de servico para esse tipo de situacao e lancar Excecoes de Negocio na camada de servico. Em aplicacoes MVC utilizando JSF, na classe controladora (BackingBean) geralmente temos que tratar excecoes de negocio ocasionalmente lancadas pelo Servico. Ex: ..BackingBean......public String inserir(){ //metodo de acao do backing bean, acionado na fase invoke application do ciclo de vida JSF try{ this.servico.inserir(entidade); // chamada ao metodo de servico return "sucesso"; // "sucesso" e a pagina de retorno no caso de sucesso }catch(NegocioException e){ // Considere que NegocioException e apenas uma RuntimeException utilizada pela camada de servico para lancar excecoes de negocio String msgFormatada = getMensagem(e.getMessage()); // A mensagem de erro e informada ao lancar o NegocioException, considere que o getMensagem e um metodo que obtem uma mensagem de um arquivo de propriedades a partir de uma chave FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN, msgFormatada, msgFormatada); FacesContext.getCurrentInstance().addMessage(null, facesMessage); return null; } }.....BackingBean.. Mas esse tratamento, muito rotineiro e trivial, deve ser feito para todo metodo do BackingBean. Deveria ter uma forma de automatizar isso e deixar o codigo acima bem mais simples e legivel. No Struts podemos implementar org.apache.struts.action.ExceptionHandler e interceptar as excecoes fazendo o tratamento. SolucaoEis aqui a solucao!!! Voce nao percebe mas o JSF encapsula o servlet e atraves das fases do ciclo de vida, executa uma serie de tarefas antes de evocar seu metodo deixando seu backing bean naquele estado perfeito, com todos campos carregados, convertidos e validados. A solucao esta exatamente em incluir o tratamento nesse momento em que o JSF evoca seu metodo. Para isso precisamos fazer 2 coisas, implementar ActionListener e declarar que o ActionListener utilizado pela aplicacao sera o que voce definiu. 1. Implementar ActionListener: /** * NegocioExceptionListener * * Descricao: Listener que processa eventos da fase do ciclo de vida que invoca * os metodos de acao, geralmente Invoke Application. Sobrescreve o metodo * {@link ActionListenerImpl#processAction(ActionEvent)} apenas para fazer o * tratamento de excecoes de negocio. * * * @see ActionListener * @see ActionListenerImpl * @author marcos.oliveira * @version 1.0 */ public class NegocioExceptionListener extends ActionListenerImpl implements ActionListener { /** * Tenta executar seguir o fluxo normal, chamando o metodo da superclasse e * caso ocorra uma excecao de Negocio, e adicionada uma mensagem de alerta e * a fase Render Response e acionada. * * @param e * Utilizado na superclasse. * @see com.sun.faces.application.ActionListenerImpl#processAction(javax.faces.event.ActionEvent) */ @Override public void processAction(ActionEvent arg0) { try { super.processAction(arg0); } catch (Exception e) { // Necessario utilizar Exception pois sua // excecao pode ter sido encapsulada em outras Throwable exception = e; do { if (exception instanceof NegocioException) { String msgFormatada = getMensagem(e.getMessage()); /* * A mensagem de erro e informada ao lancar o * NegocioException, considere