4

マネージド Bean のコンストラクターから別のページ/ビューに移動することは可能ですか? 例外が発生した場合は、このリダイレクトが必要です。私は多くの方法を試しました:

トライ-1:

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

トライ-9:

By extending JSF Life Cycle

それらのどれも機能しませんでした。私が受け取ったすべてのケースについて

java.lang.IllegalStateException: Cannot forward after response has been committed

JSF 1.2では本当に不可能ですか? JSF 1.2を使用するADF 11.1.1.6.0を使用しているため、上記の「試行」の一部にはADF Facesの方法が含まれています。

とにかく、エラーページに移動するには、JSF 1.2またはADF Facesが必要です。私が成功した唯一の方法は、バックエンドから実行された javascript を使用して、エラーの場合にウィンドウでエラーページを開くこと_selfですが、私はそれがあまり好きではありません。

この問題に関するポインタは非常に役立ちます。

4

1 に答える 1

5

問題の原因が分かれば、問題を解決しやすくなります。適切な例外は、基本的に、問題の原因に関するすべてをすでに伝えています。

よく見てください:

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 は貧弱です。javax.servlet.*バッキング Bean にインポートを含めないようにする必要があります。Try-5 は不器用です。Try-6、Try-7、Try-8 は私の範囲外です。Try-9 は実行可能ですが、非常に不器用です。

于 2013-07-07T17:20:20.993 に答える