JSF 2全局异常处理,导航到错误页面不发生 [英] JSF 2 Global exception handling, navigation to error page not happening

查看:169
本文介绍了JSF 2全局异常处理,导航到错误页面不发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发基于JSF 2.0的Web应用程序。我正在尝试实现一个全局异常处理程序,每当发生异常时,将将用户重定向到通用错误页面(例如NullPointerException,ServletException,ViewExpiredException等)。



每当一个NPE发生在我的应用程序中,我的customnavhandler断点被打,并且NavigationHandler代码被执行,但是以某种方式重定向到错误页面不会发生,所请求的页面保持部分呈现。任何想法在这里可能是错的?一个信息是,我在请求的页面上有意地抛出一个NPE(在NPE之后部分渲染)



我的faces-config.xml条目

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

我的CustomNavHandler

 code> public class CustomExceptionHandler extends ExceptionHandlerWrapper {

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

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();
//从上下文获取异常
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();
//这里你做任何你想要的异常
尝试{
//日志错误?
logger.error(严重异常发生);
//log.log(Level.SEVERE,Critical Exception!,t);
//重定向错误页
requestMap.put(exceptionMessage,t.getMessage());
nav.performNavigation(/ TestPRoject / error.xhtml);
fc.renderResponse();
//如果要在jsf错误消息中报告错误,请删除以下注释
//JsfUtil.addErrorMessage(t.getMessage());
}
finally {
//将其从队列中删除
i.remove(); }
}
// parent hanle
getWrapped()。handle();
}

}

我的customNavhandler工厂

  public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {


private ExceptionHandlerFactory parent;

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

@Override
public ExceptionHandler getExceptionHandler(){
返回新的CustomExceptionHandler(parent.getExceptionHandler());

}

}


解决方案

很可能是因为当前请求是一个ajax(异步)请求。您所在的异常处理程序专为常规(同步)请求而设计。



在ajax异常情况下更改视图的正确方法如下:

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

然而,这是天真的。如果在渲染ajax响应中抛出了ajax异常,这将不起作用。



我建议不要重塑轮子。 JSF实用程序库 OmniFaces 具有完整的工作解决方案,其风格为 FullAjaxExceptionHandler 。您可以找到完整的源代码这里和展示示例 here 。它使用 web.xml 中的标准servlet API < error-page> 声明。这样,错误页面也可以重复使用同步请求,同时也提供了一些OmniFaces提供的 FacesExceptionFilter 的帮助。



< h3>另请参见:


I am developing a JSF 2.0 based web application. I am trying to implement a global exception handler which will redirect the user to a generic error page whenever any exception occurs (e.g. NullPointerException,ServletException,ViewExpiredException etc.)

Whenever a NPE occurs in my app, My customnavhandler breakpoint is hit and NavigationHandler code is executed, but somehow redirection to error page is not happening, the requested page remains partially rendered. Any idea what could be wrong here ? One info is that I am throwing an NPE deliberately on the requested page (which was partiallyu rendered after NPE)

My faces-config.xml entry

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

My 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(); 
        }

}

My customNavhandler factory

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {


 private ExceptionHandlerFactory parent;

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

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

  }

}

解决方案

It's most likely because the current request is an ajax (asynchronous) request. The exception handler which you've there is designed for regular (synchronous) requests.

The proper way to change the view in case of an ajax exception is as follows:

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

This is however somewhat naive. This won't work if the ajax exception is been thrown in midst of rendering of a ajax response.

I'd suggest to not reinvent the wheel. The JSF utility library OmniFaces has a complete working solution in flavor of FullAjaxExceptionHandler. You can find the full source code here and the showcase example here. It makes use of standard servlet API <error-page> declarations in web.xml. This way the error pages are also reusable for synchronous requests, with a little help of FacesExceptionFilter, also provided by OmniFaces.

See also:

这篇关于JSF 2全局异常处理,导航到错误页面不发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆