简化,我的错误处理程序如下所示:
@Override
public void handle() throws FacesException {
Iterator<ExceptionQueuedEvent> unhandledExceptionQueuedEvents = getUnhandledExceptionQueuedEvents().iterator();
FacesContext context = FacesContext.getCurrentInstance();
if (unhandledExceptionQueuedEvents.hasNext()) {
Throwable exception = unhandledExceptionQueuedEvents.next().getContext().getException();
unhandledExceptionQueuedEvents.remove();
context.getExternalContext().dispatch("/error.jsf");
}
while (unhandledExceptionQueuedEvents.hasNext()) {
unhandledExceptionQueuedEvents.next();
unhandledExceptionQueuedEvents.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
简化的template.xhtml
<html>
<f:view>
<h:head>
<!-- some stuff here -->
</h:head>
<h:body>
<div id="menu"><!-- menu content --></div>
<div id="content">
<ui:insert name="body"></ui:insert>
</div>
</h:body>
</f:view>
</html>
Run Code Online (Sandbox Code Playgroud)
error.xhtml
<html>
<ui:composition template="/template.xhtml">
<ui:define name="body">
ERROR
</ui:define>
</ui:composition>
</html>
Run Code Online (Sandbox Code Playgroud)
但是当渲染error.jsf时,使用ui:composition进行模板化是非常错误的.JSF将template.xhtml渲染到它周围,然后再开始渲染模板.结果是一个页面,菜单呈现两次,所有资源再次包含在页面中间.它的开头看起来像这样:
<div id="menu></div>
<div<?xml version="1.0" encoding="UTF-8" ?="">
<!-- Page included once more -->
Run Code Online (Sandbox Code Playgroud)
接下来是服务器上的无限循环,导致数百万个日志行一遍又一遍地包含以下位
at com.xdin.competence.web.error.ErrorHandler.handleException(ErrorHandler.java:123) [:]
at com.xdin.competence.web.error.ErrorHandler.handle(ErrorHandler.java:108) [:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:115) [:2.0.3-]
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:107) [:2.0.3-]
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114) [:2.0.3-]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308) [:2.0.3-]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) [:6.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) [:6.0.0.Final]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:734) [:6.0.0.Final]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:541) [:6.0.0.Final]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:479) [:6.0.0.Final]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:407) [:6.0.0.Final]
at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:542) [:2.0.3-]
at javax.faces.context.ExternalContextWrapper.dispatch(ExternalContextWrapper.java:89) [:2.0.3-]
at org.jboss.seam.faces.environment.org$jboss$weld$bean-jboss$classloader:id="vfs:$$$C:$JBoss$jboss-6$0$0$Final$server$career$deploy$career-portal$war"-ManagedBean-class_org$jboss$seam$faces$environment$SeamExternalContext_$$_WeldClientProxy.dispatch(org$jboss$weld$bean-jboss$classloader:id="vfs:$$$C:$JBoss$jboss-6$0$0$Final$server$career$deploy$career-portal$war"-ManagedBean-class_org$jboss$seam$faces$environment$SeamExternalContext_$$_WeldClientProxy.java) [:3.0.1.Final]
Run Code Online (Sandbox Code Playgroud)
知道原因可能是什么吗?
您不应该使用ExternalContext#dispatch()
渲染JSF视图.它应该仅用于转发到非JSF资源.您应该通过设置所需的JSF视图FacesContext#setViewRoot()
并让JSF呈现它.
ViewHandler viewHandler = context.getApplication().getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, viewId);
context.setViewRoot(viewRoot);
context.renderResponse();
Run Code Online (Sandbox Code Playgroud)
或者,如果您当前已经坐在渲染响应中,那么让JSF重新渲染它为时已晚.您需要手动构建和呈现新视图.在这种情况下,将最后一行替换为:
ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(context, viewId);
vdl.buildView(context, viewRoot);
context.getApplication().publishEvent(context, PreRenderViewEvent.class, viewRoot);
vdl.renderView(context, viewRoot);
context.responseComplete();
Run Code Online (Sandbox Code Playgroud)
请注意,如果响应已提交,则反过来也会太晚.您可能也想事先检查一下.
您可能会发现在源代码中的OmniFacesFullAjaxExceptionHandler
有助于获得一些见解.
归档时间: |
|
查看次数: |
4626 次 |
最近记录: |