是否可以从托管bean的构造函数导航到另一个页面/视图?如果发生任何异常,我想要这个重定向。我尝试了很多方法:
getFacesContext().responseComplete();
getFacesContext().getApplication().getNavigationHandler().handleNavigation(getFacesContext(), null, "gotoPartError");
getFacesContext().renderResponse();
getServletResponse().sendRedirect("partError.jspx")
getFacesContext().responseComplete();
getFacesContext().getExternalContext().redirect(getServletRequest().getContextPath() + "/pages/partError.jspx");
RequestDispatcher dispatcher = getServletRequest().getRequestDispatcher("partError.jspx");
dispatcher.forward(getServletRequest(), getServletResponse());
FacesContext context = getFacesContext();
UIViewRoot newPage = context.getApplication().getViewHandler().createView(context, "/partError.jspx");
context.setViewRoot(newPage);
context.renderResponse();
ControllerContext.getInstance().getCurrentViewPort().setViewId("partError");
Exception Handler in adfc-config.xml
Custom service handler defined in /.adf/META-INF/services/oracle.adf.view.rich.context.Exceptionhandler which extends oracle.adf.view.rich.context.Exceptionhandler
By extending JSF Life Cycle
他们都没有奏效。对于我收到的所有案件
java.lang.IllegalStateException: Cannot forward after response has been committed
在JSF 1.2中真的不可能吗?当我使用ADF 11.1.1.6.0,它使用JSF 1.2时,上面的一些“尝试”包含ADF Faces方式。
无论如何,我需要JSF 1.2或ADF Faces来导航到错误页面。我获得成功的唯一方法是使用从后端执行的javascript,以便在出现错误时在_self
窗口中打开错误页面,但我真的不喜欢它。
此问题中的任何指针都非常有用。
答案 0 :(得分:5)
如果理解问题的原因,解决问题会更容易。一个很好的例外基本上已经说明了问题原因的一切。
仔细观察:
java.lang.IllegalStateException:在提交响应后无法转发
已经提交了回复。这是一个不归路。也许您无法理解提交响应意味着什么(其结果是您也无法理解异常本身)。
默认情况下,HTTP响应被写入缓冲区,每隔~2KB刷新一次,具体取决于服务器配置。刷新响应缓冲区会导致写入的字节实际从服务器发送到客户端。一旦第一次发生这种情况,就会认为响应已提交。这是一个不归路。如果服务器实际上需要在之后更改响应,则服务器无法从客户端返回已写入的字节。
如果您有一些可能需要更改响应的代码,那么您应该在提交响应之前 之前调用它。
在您的特定情况下,在生成HTML输出期间,托管bean显然是在JSF呈现响应阶段中构建的。已生成的HTML输出的一部分已发送到客户端(因此,响应已提交)。您显然在JSF页面中相对较晚地引用了请求范围的bean,或者响应缓冲区相对较小,或者HTML <head>
相对较大,导致在<body>
启动之前已经刷新,等等
您确实需要在渲染响应阶段之前调用代码 。在JSF 1.2中,您可以使用<f:view beforePhase>
来实现此目的。
E.g。
<f:view beforePhase="#{bean.navigate}">
与
public void navigate(PhaseEvent event) {
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
// Do here your job which should run right before the RENDER_RESPONSE.
}
}
然后你的Try-1和Try-3会有效(不过你可以将这些responseComplete()
和renderResponse()
行留下来,它们已被隐含地处理过了。)
Try-2和Try-4很差。您应该避免在辅助bean中导入javax.servlet.*
。 Try-5很笨拙。 Try-6,Try-7和Try-8超出了我的范围。 Try-9是可行的,但非常笨拙。