1. ホーム
  2. servlets

[解決済み] [Solved] java.lang.IllegalStateException: レスポンスがコミットされた後では(forward | sendRedirect | create session)できません。

2022-02-14 05:01:03

質問事項

このメソッドは

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);
    }

解決方法は?

スタートアップにありがちな誤解は、「Scala」の呼び出しは、「Scala」ではなく「Scala」であると考えることです。 forward() , sendRedirect() または sendError() は魔法のようにメソッドブロックを終了して "jump" するので、コードの残骸を無視することができます。例えば

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

このように、実はそうではないのです。これらは確かに他のJavaのメソッドと違った振る舞いをすることはありません( System#exit() もちろんです)。このとき someCondition は、上記の例では true を呼び出していることになります。 forward() の後に sendRedirect() または sendError() が同じリクエスト/レスポンスにある場合、その確率は 大きい という例外が発生します。

java.lang.IllegalStateException: レスポンスがコミットされた後は転送できません

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

java.lang.IllegalStateException: レスポンスがコミットされた後に sendRedirect() をコールできない

この問題を解決するには、以下のいずれかの方法を取る必要があります。 return; ステートメントの後に

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

... あるいは、elseブロックを導入する。

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

コードの中にある根本的な原因を突き止めるには、まず最初に forward() , sendRedirect() または sendError() メソッドブロックを終了したり、コードの残りをスキップしたりすることなく これは、特定のコード行の前にある同じサーブレット内だけでなく、 特定のサーブレットの前に呼び出されたサーブレットやフィルタ内でも可能です。

の場合 sendError() レスポンス・ステータスを設定することが唯一の目的である場合には setStatus() の代わりに


もう一つの原因として考えられるのは、サーブレットがレスポンスに書き込む際に forward() が呼び出されるか、まったく同じメソッドで呼び出されたことがあります。

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

レスポンスバッファーのサイズは、ほとんどのサーバーでデフォルトが2KBなので、2KB以上書き込むと、コミットされ forward() も同じように失敗します。

<ブロッククオート

java.lang.IllegalStateException: レスポンスがコミットされた後では転送できません

解決策は明らかです。サーブレットでレスポンスに書き込まないようにすればいいのです。それはJSPの責任です。次のようにリクエスト属性を設定するだけです。 request.setAttribute("data", "some string") で、それをJSPで次のように表示します。 ${data} . 参照 サーブレットウィキのページ を使えば、サーブレットの正しい使い方を知ることができます。


もう一つの原因として考えられるのは、サーブレットがファイルのダウンロードをレスポンスに書き込んだ後、例えば forward() が呼び出されます。

protected void doXxx() {
    out.write(bytes);
    // ... 
    forward(); // Fail!
}

これは技術的に不可能です。を削除する必要があります。 forward() の呼び出しがあります。エンドユーザは現在開いているページに留まることになります。ファイルダウンロード後に実際にページを変更するつもりであれば、ファイルダウンロードのロジックをターゲットページのページロードに移動する必要があります。


さらにもう一つの原因として考えられるのは 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のコードを書かないことです。それは、ServletやFilterのような通常のJavaクラスの責任です。以下も参照してください。 サーブレットウィキページ を使えば、サーブレットの正しい使い方を知ることができます。


こちらもご覧ください。


関連性のないもの は、あなたの具体的な問題に、あなたのJDBCコードは、リソースをリークしている。それも解決してください。ヒントとしては JDBCで接続、ステートメント、結果セットを閉じる頻度はどのくらいがよいですか?