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

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

问题描述

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

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.)

每当我的应用程序中发生 NPE 时,我的 customnavhandler 断点都会被命中并执行 NavigationHandler 代码,但不知何故没有发生重定向到错误页面,请求的页面仍然部分呈现.知道这里有什么问题吗?一个信息是我故意在请求的页面上抛出一个 NPE(这是在 NPE 之后部分渲染的)

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)

我的 faces-config.xml 条目

My faces-config.xml entry

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

我的自定义导航处理器

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

}

我的自定义Navhandler工厂

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

  }

}

推荐答案

很可能是因为当前请求是 ajax(异步)请求.您拥有的异常处理程序专为常规(同步)请求而设计.

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.

出现ajax异常时,正确的改变视图的方法如下:

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

然而,这有点幼稚.如果在呈现 ajax 响应的过程中抛出 ajax 异常,这将不起作用.

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

我建议不要重新发明轮子.JSF 实用程序库 OmniFaces 有一个完整的工作解决方案 FullAjaxExceptionHandler.你可以找到完整的源代码 这里和展示示例这里.它利用了 web.xml 中的标准 servlet API 声明.通过这种方式,错误页面也可以重用于同步请求,借助 FacesExceptionFilter,同样由 OmniFaces 提供.

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.

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

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