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

查看:32
本文介绍了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>

我的自定义导航处理程序

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

}

我的 customNavhandler 工厂

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 声明.通过这种方式,错误页面也可用于同步请求,并借助同样由 OmniFaces 提供的 FacesExceptionFilter.

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天全站免登陆