web-dev-qa-db-ja.com

java.lang.IllegalStateException:応答がコミットされた後(転送| sendRedirect |セッションの作成)できません

このメソッドはスローします

Java.lang.IllegalStateException:応答がコミットされた後に転送できません

そして、私は問題を見つけることができません。助けがありますか?

    int noOfRows = Integer.parseInt(request.getParameter("noOfRows"));
    String chkboxVal = "";
    // String FormatId=null;
    Vector vRow = new Vector();
    Vector vRow1 = new Vector();
    String GroupId = "";
    String GroupDesc = "";
    for (int i = 0; i < noOfRows; i++) {
        if ((request.getParameter("chk_select" + i)) == null) {
            chkboxVal = "notticked";
        } else {
            chkboxVal = request.getParameter("chk_select" + i);
            if (chkboxVal.equals("ticked")) {
                fwdurl = "true";
                Statement st1 = con.createStatement();
                GroupId = request.getParameter("GroupId" + i);
                GroupDesc = request.getParameter("GroupDesc" + i);
                ResultSet rs1 = st1
                        .executeQuery("select FileId,Description from cs2k_Files "
                                + " where FileId like 'M%' and co_code = "
                                + ccode);
                ResultSetMetaData rsm = rs1.getMetaData();
                int cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol1 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol1.addElement(rs1.getObject(j));
                    }
                    vRow.addElement(vCol1);
                }
                rs1 = st1
                        .executeQuery("select FileId,NotAllowed from cs2kGroupSub "
                                + " where FileId like 'M%' and GroupId = '"
                                + GroupId + "'" + " and co_code = " + ccode);
                rsm = rs1.getMetaData();
                cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol2 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol2.addElement(rs1.getObject(j));
                    }
                    vRow1.addElement(vCol2);
                }

                // throw new Exception("test");

                break;
            }
        }
    }
    if (fwdurl.equals("true")) {
        // throw new Exception("test");
        // response.sendRedirect("cs2k_GroupCopiedUpdt.jsp") ;
        request.setAttribute("GroupId", GroupId);
        request.setAttribute("GroupDesc", GroupDesc);
        request.setAttribute("vRow", vRow);
        request.setAttribute("vRow1", vRow1);
        getServletConfig().getServletContext().getRequestDispatcher(
                "/GroupCopiedUpdt.jsp").forward(request, response);
    }
89
sansknwoledge

スターターの間でよくある誤解は、forward()sendRedirect()、またはsendError()の呼び出しが魔法のように終了し、メソッドブロックから「ジャンプ」すると考えることです。コード。例えば:

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!
}

したがって、これは実際には正しくありません。確かに他のJavaメソッドと異なる振る舞いをしません(もちろんSystem#exit()の期待)。上記の例のsomeConditiontrueであり、同じリクエスト/レスポンスでforward()またはsendRedirect()の後にsendError()を呼び出している場合、チャンスはbig例外が発生します:

Java.lang.IllegalStateException:応答がコミットされた後に転送できません

ifステートメントがforward()を呼び出し、その後sendRedirect()またはsendError()を呼び出す場合、以下の例外がスローされます。

Java.lang.IllegalStateException:応答がコミットされた後にsendRedirect()を呼び出すことはできません

これを修正するには、return;ステートメントを後で追加する必要があります

protected void doPost() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();
}

...またはelseブロックを導入します。

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    } else {
        forward();
    }
}

コードの根本原因を特定するには、メソッドブロックを終了したり、コードの残りをスキップしたりせずに、forward()sendRedirect()、またはsendError()を呼び出す行を検索します。これは、特定のコード行の前の同じサーブレット内だけでなく、特定のサーブレットの前に呼び出された任意のサーブレットまたはフィルター内でも可能です。

sendError()の場合、唯一の目的が応答ステータスの設定である場合、代わりにsetStatus()を使用します。


別の原因としては、forward()が呼び出されるか、まったく同じメソッドで呼び出されている間に、サーブレットが応答に書き込むことが考えられます。

protected void doPost() {
    out.write("some string");
    // ... 
    forward(); // Fail!
}

応答バッファのサイズは、ほとんどのサーバーでデフォルトで2KBに設定されています。したがって、2KB以上を書き込むと、コミットされ、forward()は同じように失敗します。

Java.lang.IllegalStateException:応答がコミットされた後に転送できません

解決策は明らかです。サーブレットの応答に書き込まないでください。それがJSPの責任です。 request.setAttribute("data", "some string")のようにリクエスト属性を設定し、${data}のようにJSPで印刷します。 サーブレットwikiページ も参照して、サーブレットを正しい方法で使用する方法を学習してください。


さらに別の考えられる原因は、forward()sendRedirect()、またはsendError()メソッドが、JSPファイルに埋め込まれたJavaコードを介して、昔ながらの方法<% scriptlets %>2001年以降公式に推奨されていません 。例えば:

<!DOCTYPE html>
<html lang="en">
    <head>
        ... 
    </head>
    <body>
        ...

        <% sendRedirect(); %>

        ...
    </body>
</html>

ここでの問題は、JSPがテンプレートテキスト(つまり、HTMLコード)を検出するとすぐにout.write("<!DOCTYPE html> ... etc ...")を介して内部的に即座に書き込むことです。したがって、これは前のセクションで説明したのと本質的に同じ問題です。

解決策は明らかです。JSPファイルにJavaコードを記述しないでください。それは、サーブレットやフィルターなどの通常のJavaクラスの責任です。 サーブレットwikiページ も参照して、サーブレットを正しい方法で使用する方法を学習してください。


こちらもご覧ください:


具体的な問題とは無関係、JDBCコードはリソースをリークしています。それも修正してください。ヒントについては、 JDBCでConnection、Statement、ResultSetをどのくらいの頻度で閉じる必要がありますか も参照してください。

235
BalusC

returnステートメントを追加してもこの例外が発生しますが、このコードの唯一の解決策は次のとおりです。

if(!response.isCommitted())
// Place another redirection
19
user1503117

通常、すでにリダイレクトを行った後にこのエラーが表示され、さらにいくつかのデータを出力ストリームに出力しようとします。過去にこれを見たことがある場合、多くの場合、ページのリダイレクトを試みているフィルターの1つであり、それでもサーブレットに転送されます。サーブレットの問題はすぐにはわかりません。そのため、使用しているフィルターも調べてみてください。

編集:問題の診断に役立つ情報がいくつかあります…

この問題を診断する最初のステップは、例外がどこでスローされているかを正確に確認することです。私たちはそれが線によって投げられていると仮定しています

getServletConfig().getServletContext()
                  .getRequestDispatcher("/GroupCopiedUpdt.jsp")
                  .forward(request, response);

しかし、コードの後半でスローされていることに気付く場合があります。コードは、転送を試みた後に出力ストリームに出力しようとしています。上記の行から来ている場合、この行の前のどこかに次のいずれかがあることを意味します。

  1. 出力ストリームへの出力データ、または
  2. 事前に別のリダイレクトを行いました。

幸運を!

6
Paul Wagland

これは、サーブレットが存在しないリクエストオブジェクトにアクセスしようとしているためです。サーブレットのforwardまたはincludeステートメントは、メソッドブロックの実行を停止しません。他のJavaメソッドと同様に、メソッドブロックの最後または最初のreturnステートメントまで続きます。

この問題を解決する最良の方法は、ロジックに従って動的にページ(要求を転送する場所)を設定するだけです。あれは:

protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
 returnPage="page1.jsp";
}
if(condition2){
   returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}

そして、最後の行で一度だけフォワードを行います...

各forward()の後にreturnステートメントを使用してこの問題を修正するか、if ... elseブロックに各forward()を入れることもできます。

2
Suman Sengupta

私は削除しました

        super.service(req, res);

それから私にとってはうまくいった

2
kartikag01

バンプ...

同じエラーが発生しました。 super.doPost(request, response);メソッドをオーバーライドするときにdoPost()を呼び出し、スーパークラスコンストラクターを明示的に呼び出していることに気付きました

    public ScheduleServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

super.doPost(request, response);ステートメント内からdoPost()をコメントアウトするとすぐに完全に機能しました...

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //super.doPost(request, response);
        // More code here...

}

言うまでもなく、super()のベストプラクティスを読み直す必要があります:p

2
John Rambo

フローの転送またはリダイレクト中にreturnステートメントを追加する必要があります。

例:

forwardindの場合、

    request.getRequestDispatcher("/abs.jsp").forward(request, response);
    return;

リダイレクトする場合、

    response.sendRedirect(roundTripURI);
    return;
1
Ashish Mishra

Return forwardメソッドの後、これを簡単に行うことができます:

return null;

現在のスコープを破壊します。

0
Amir Amiri