it-swarm.com.de

JSF 2 Globale Ausnahmebehandlung, Navigation zur Fehlerseite findet nicht statt

Ich entwickle eine JSF 2.0-basierte Webanwendung. Ich versuche, einen globalen Ausnahmebehandler zu implementieren, der den Benutzer bei jedem Auftreten einer Ausnahme auf eine allgemeine Fehlerseite umleitet (z. B. NullPointerException, ServletException, ViewExpiredException usw.).

Immer wenn eine NPE in meiner App auftritt, wird der Haltepunkt Mein customnavhandler getroffen und der NavigationHandler-Code ausgeführt, aber die Umleitung zur Fehlerseite findet nicht statt. Die angeforderte Seite bleibt teilweise gerendert. Irgendeine Idee, was hier falsch sein könnte? Eine Info ist, dass ich eine NPE absichtlich auf die angeforderte Seite werfe (die teilweise nach NPE gerendert wurde)

Mein faces-config.xml Eintrag

<factory>
  <exception-handler-factory>
    com.common.exceptions.CustomExceptionHandlerFactory
  </exception-handler-factory>
</factory>

Mein CustomNavHandler

public class CustomExceptionHandler extends ExceptionHandlerWrapper {

private static final Logger logger = Logger.getLogger("com.gbdreports.common.exception.CustomExceptionHandler");
private final ExceptionHandler wrapped;

public CustomExceptionHandler(ExceptionHandler wrapped) {
    this.wrapped = wrapped;
}

@Override
public ExceptionHandler getWrapped() {
    return this.wrapped;

}
public void handle() throws FacesException {
    final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();         

    while (i.hasNext()) {             
        ExceptionQueuedEvent event = i.next();             
        ExceptionQueuedEventContext context =                    
                (ExceptionQueuedEventContext) event.getSource();               
        // get the exception from context             
        Throwable t = context.getException();               
        final FacesContext fc = FacesContext.getCurrentInstance();   
        final ExternalContext externalContext = fc.getExternalContext();
        final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();            
        final ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) fc.getApplication().getNavigationHandler();               
        //here you do what ever you want with exception             
        try {                   
            //log error ?      
            logger.error("Severe Exception Occured");
            //log.log(Level.SEVERE, "Critical Exception!", t);                   
            //redirect error page                 
            requestMap.put("exceptionMessage", t.getMessage());                 
            nav.performNavigation("/TestPRoject/error.xhtml");                 
            fc.renderResponse();                   
            // remove the comment below if you want to report the error in a jsf error message                 
            //JsfUtil.addErrorMessage(t.getMessage());               
            } 
        finally {                 
            //remove it from queue                 
            i.remove();             }         
        }         
    //parent hanle         
    getWrapped().handle(); 
        }

}

Meine customNavhandler Fabrik

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {


 private ExceptionHandlerFactory parent;

  public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
    this.parent = parent;
  }

  @Override
  public ExceptionHandler getExceptionHandler() {
      return new CustomExceptionHandler (parent.getExceptionHandler());

  }

}
7
user1722908

Dies liegt wahrscheinlich daran, dass es sich bei der aktuellen Anforderung um eine (asynchrone) Ajax-Anforderung handelt. Der Exception-Handler, den Sie dort haben, ist für regelmäßige (synchrone) Anforderungen vorgesehen.

Die richtige Methode zum Ändern der Ansicht im Falle einer Ajax-Ausnahme lautet wie folgt:

String viewId = "/error.xhtml";
ViewHandler viewHandler = context.getApplication().getViewHandler();
context.setViewRoot(viewHandler.createView(context, viewId));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();

Das ist aber etwas naiv. Dies funktioniert nicht, wenn die Ajax-Ausnahme beim Rendern einer Ajax-Antwort ausgelöst wird.

Ich würde vorschlagen, das Rad nicht neu zu erfinden. Die JSF-Hilfsprogrammbibliothek OmniFaces bietet eine vollständige funktionierende Lösung in Bezug auf FullAjaxExceptionHandler . Den vollständigen Quellcode finden Sie hier und das Musterbeispiel hier . Es werden Standard-Servlet-API-<error-page>-Deklarationen in web.xml verwendet. Auf diese Weise können die Fehlerseiten auch für synchrone Anforderungen wiederverwendet werden, mit Hilfe von FacesExceptionFilter, das ebenfalls von OmniFaces bereitgestellt wird.

Siehe auch:

14
BalusC

Eine einheitliche Methode zur Behandlung von Ajax- und Nicht-Ajax-Anforderungen kann zur Vereinfachung des Codes verwendet werden. Anstatt

requestMap.put("exceptionMessage", t.getMessage());                 
nav.performNavigation("/TestPRoject/error.xhtml");                 
fc.renderResponse();

ist genug zu benutzen:

fc.getExternalContext().redirect("/TestPRoject/error.xhtml");
0
Alex Tsurika