【问题标题】:Navigation from managed bean constructor in ADF Faces JSF 1.2从 ADF Faces JSF 1.2 中的托管 bean 构造函数导航
【发布时间】:2013-07-04 18:42:43
【问题描述】:

是否可以从托管 bean 的构造函数导航到另一个页面/视图?如果发生任何异常,我想要此重定向。我尝试了很多方法:

试一试:

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

尝试 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 窗口中打开错误页面,但我不太喜欢它。

在这件事上的任何指针都会非常有帮助。

【问题讨论】:

    标签: jsf exception-handling navigation oracle-adf jsf-1.2


    【解决方案1】:

    如果了解问题的原因,则更容易解决问题。一个好的例外基本上已经说明了问题的原因。

    仔细看:

    java.lang.IllegalStateException: 响应提交后无法转发

    响应已提交。这是一个不归路。可能你没有理解响应已经提交意味着什么(这导致你也没有理解异常本身)。

    默认情况下,HTTP 响应会写入缓冲区,该缓冲区每 ~2KB 刷新一次,具体取决于服务器配置。响应缓冲区的刷新导致写入的字节实际从服务器发送到客户端。一旦第一次发生这种情况,则认为响应已提交。这是一个不归路。服务器不能从客户端取回已经写入的字节,以防服务器实际上需要在之后更改响应。

    如果您有一些代码可能需要更改响应,那么您应该在响应提交之前调用它。

    在您的特定情况下,托管 bean 显然是在生成 HTML 输出期间的 JSF 呈现响应阶段中间构造的。生成的 HTML 输出的一部分已经发送到客户端(因此,响应已提交)。您显然在 JSF 页面中相对较晚地引用了请求范围的 bean,或者响应缓冲区相对较小,或者 HTML <head> 相对较大,这导致在 <body> 开始之前已经刷新,等等。

    您确实需要在渲染响应阶段之前调用代码。在 JSF 1.2 中,您可以为此使用 <f:view beforePhase>

    例如

    <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 的方法,即使用任务流。我真的很感谢你的帮助。我还将发布我找到的解决方案。
    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2012-12-18
    • 2017-10-19
    相关资源
    最近更新 更多