ADF Faces JSF 1.2中托管bean构造函数的导航

4
从托管bean的构造函数中导航到另一个页面/视图是否可能?如果发生任何异常,我希望进行重定向。我尝试了许多方法:

尝试1:

getFacesContext().responseComplete();
getFacesContext().getApplication().getNavigationHandler().handleNavigation(getFacesContext(), null, "gotoPartError");    
getFacesContext().renderResponse();

Try-2:

getServletResponse().sendRedirect("partError.jspx")

尝试-3:

getFacesContext().responseComplete();    
getFacesContext().getExternalContext().redirect(getServletRequest().getContextPath() + "/pages/partError.jspx");

尝试-4:

RequestDispatcher dispatcher = getServletRequest().getRequestDispatcher("partError.jspx");
dispatcher.forward(getServletRequest(), getServletResponse());

尝试-5:

FacesContext context = getFacesContext();
UIViewRoot newPage = context.getApplication().getViewHandler().createView(context, "/partError.jspx");
context.setViewRoot(newPage);
context.renderResponse();

尝试-6:

ControllerContext.getInstance().getCurrentViewPort().setViewId("partError");

尝试7:

Exception Handler in adfc-config.xml

尝试-8:

Custom service handler defined in /.adf/META-INF/services/oracle.adf.view.rich.context.Exceptionhandler which extends oracle.adf.view.rich.context.Exceptionhandler

Try-9:

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窗口中打开错误页面,但我真的不喜欢这种方法。
在这方面的任何指针都将非常有帮助。
1个回答

5
如果了解问题的原因,解决问题就更容易。一个好的异常基本上已经说明了问题的原因。
仔细看:
java.lang.IllegalStateException: Cannot forward after response has been committed
响应已提交。这是一个不可逆转的点。也许你没有理解响应已提交意味着什么(这也导致你没有理解异常本身)。
默认情况下,HTTP响应会被写入一个缓冲区,该缓冲区根据服务器配置每个 ~2KB 刷新一次。刷新响应缓冲区将导致实际从服务器发送写入的字节到客户端。一旦第一次发生这种情况,响应被认为是已提交的。这是一个不可逆转的点。如果服务器实际上需要在之后更改响应,则无法从客户端中取回已写入的字节。
如果您有可能需要更改响应的代码,则应在提交响应之前调用它。
在您的特定情况下,托管的bean 显然是在生成HTML输出期间JSF渲染响应阶段中构建的。已经向客户端发送了部分生成的HTML输出(因此,响应已提交)。您显然相对较晚地引用了请求范围的bean,或者响应缓冲区相对较小,或者HTML 相对较大,这会导致在 开始之前已经刷新。
您真的需要在渲染响应阶段之前调用代码。在JSF 1.2中,您可以使用 来实现此目的。
例如:
<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是可行的,但非常笨拙。


谢谢您的解释。我一定会尝试这个解决方案。目前我发现在ADF Faces中有另一种更适用的方法,即使用任务流。非常感谢您的帮助。我也会发布我找到的解决方案。 - Tapas Bose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接