我的用例如下:已经向用户显示了一个JSF2页面。该页面包含一个启用ajax的按钮:
<p:commandButton value="#{msgs.reset}" process="@this"
actionListener="#{reworkSearchMB.clearReworkSearch()}" tabindex="13"
update="mainpanel messages" global="false"
disabled="#{!userMB.hasAccessToViewRework() and !userMB.hasAccessToCreateOrUpdateRework()}"
/>
所以,当页面显示在屏幕上时,用户等待了很长时间会话过期。之后,用户按ajax启用按钮。
我想要发生的是:将用户重定向到登录屏幕。
所以,遵循Jim Driscoll的建议http://weblogs.java.net/blog/2009/05/14/redirecting-jsf-20-ajax-request,我创建了一个连接到RESTORE_VIEW阶段的PhaseListener,用于检查是否会话已经过期,如果是,将重定向到登录页面:
ExternalContext ectx = ctx.getExternalContext();
String newUrl =
ectx.encodeActionURL(ctx.getApplication().getViewHandler().getActionURL(ctx,
"/login.xhtml"));
try {
ectx.redirect(newUrl); // calls responseComplete() according to JavaDocs
} catch (IOException ex) {
throw new FacesException(ex);
}
当监听beforePhase (RESTORE_VIEW)时,我得到一个NullPointerException:
SEVERE: java.lang.NullPointerException
at com.sun.faces.context.PartialViewContextImpl.createPartialResponseWriter(PartialViewContextImpl.java:434) ~[jsf-impl.jar:2.1.0-FCS]
at com.sun.faces.context.PartialViewContextImpl.access$300(PartialViewContextImpl.java:71) ~[jsf-impl.jar:2.1.0-FCS]
at com.sun.faces.context.PartialViewContextImpl$DelayedInitPartialResponseWriter.getWrapped(PartialViewContextImpl.java:575) ~[jsf-impl.jar:2.1.0-FCS]
at javax.faces.context.PartialResponseWriter.startDocument(PartialResponseWriter.java:115) ~[jsf-api.jar:2.1.0-FCS]
at org.primefaces.context.PrimePartialResponseWriter.startDocument(PrimePartialResponseWriter.java:103) ~[primefaces-2.2.1.jar:na]
at com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:572) ~[jsf-impl.jar:2.1.0-FCS]
at com.argushealth.rework.phaselistener.SecurityPhaseListener.doRedirect(SecurityPhaseListener.java:80) ~[SecurityPhaseListener.class:na]
at com.argushealth.rework.phaselistener.SecurityPhaseListener.beforePhase(SecurityPhaseListener.java:42) ~[SecurityPhaseListener.class:na]
at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228) ~[jsf-impl.jar:2.1.0-FCS]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99) ~[jsf-impl.jar:2.1.0-FCS]
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:113) [jsf-impl.jar:2.1.0-FCS]
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl.jar:2.1.0-FCS]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:409) [jsf-api.jar:2.1.0-FCS]
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:787) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:649) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:483) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:454) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:350) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:300) [web-core.jar:3.1]
at com.argushealth.enterprise.security.web.spring.exception.AbstractExceptionHandler.handleException(AbstractExceptionHandler.java:44) [enterprise-security-web-spring-1.0.4.jar:na]
at com.argushealth.enterprise.security.web.spring.ui.ExceptionHandlingFilter.doFilterHttp(ExceptionHandlingFilter.java:57) [enterprise-security-web-spring-1.0.4.jar:na]
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) [spring-security-core-2.0.3.jar:2.0.3]
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:371) [spring-security-core-2.0.3.jar:2.0.3]
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:174) [spring-security-core-2.0.3.jar:2.0.3]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236) [spring-2.5.5.jar:2.5.5]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) [spring-2.5.5.jar:2.5.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) [web-core.jar:3.1]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) [web-core.jar:3.1]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) [web-core.jar:3.1]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) [web-core.jar:3.1]
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) [web-core.jar:3.1]
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) [web-core.jar:3.1]
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) [web-glue.jar:3.1]
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) [web-glue.jar:3.1]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) [web-core.jar:3.1]
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326) [web-core.jar:3.1]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227) [web-core.jar:3.1]
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170) [kernel.jar:3.1]
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822) [grizzly-http.jar:1.9.31]
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719) [grizzly-http.jar:1.9.31]
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013) [grizzly-http.jar:1.9.31]
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) [grizzly-http.jar:1.9.31]
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) [grizzly-http.jar:1.9.31]
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.ContextTask.run(ContextTask.java:71) [grizzly-framework.jar:1.9.31]
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) [grizzly-utils.jar:1.9.31]
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) [grizzly-utils.jar:1.9.31]
at java.lang.Thread.run(Thread.java:619) [na:1.6.0_20]
谢谢你,米格尔平,这很有帮助。我读了你提供的文章,并试图修复这个bug。但是当我写下面的代码时,我遇到了另一个问题:
// workaround for PrimeFaces
new RequestContextImpl(ec);
if (ec.getRequestParameterMap().containsKey(Constants.PARTIAL_PROCESS_PARAM)
&& !ec.getRequestParameterMap().get(Constants.PARTIAL_PROCESS_PARAM).equals("@all")) {
fc.setViewRoot(new PartialViewRoot(new UIViewRoot()));
}
有编译错误,因为我找不到类RequestContextImpl和PartialViewRoot在我的primefaces jar文件。我使用的是primefaces-2.2.1。我发现这两个类在以前的一些版本中存在,但在2.2.x中不存在。我将2.0.0版本的两个类复制到我自己的项目中,但它仍然不起作用。什么好主意吗?
NPE
是PrimeFaces中已知的bug。请看这篇文章:http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=2335
尝试设置视图
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "");
facesContext.setViewRoot(view);