JSF 2全局异常处理,导航到错误页面没有发生 [英] JSF 2 Global exception handling, navigation to error page not happening
问题描述
我正在开发一个基于 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屋!