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

StackOverflow https://stackoverflow.com/questions/2123514

質問

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

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);
    }
役に立ちましたか?

解決

初心者の間でよくある誤解は、彼らは、 forward(), sendRedirect(), 、 または sendError() 魔法のように終了してメソッド ブロックから「ジャンプ」し、コードの残りの部分を無視します。例えば:

protected void doPost() {
    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 doPost() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();
}

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

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

コード内の根本原因を特定するには、コードを呼び出す行を検索するだけです。 forward(), sendRedirect() または sendError() メソッド ブロックを終了したり、コードの残りの部分をスキップしたりする必要はありません。これは、同じサーブレット内の特定のコード行の前に存在することもできますが、特定のサーブレットの前に呼び出された任意のサーブレットまたはフィルターにも存在します。

の場合には sendError(), 応答ステータスを設定することだけが目的の場合は、次を使用します。 setStatus() その代わり。


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

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

ほとんどのサーバーの応答バッファ サイズはデフォルトで 2KB なので、2KB を超えるデータを書き込むとコミットされ、 forward() 同じように失敗します:

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

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


さらにもう 1 つの考えられる原因は、 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 を閉じる必要がありますか?

他のヒント

はさえreturn文を追加する唯一の解決策は、このコードであるため、この例外は、起動します

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

通常、このエラーは、リダイレクトをすでに実行し、さらにデータを出力ストリームに出力しようとした後に表示されます。私がこれまでにこれを見たケースでは、ページをリダイレクトしようとしているフィルターの 1 つであることが多く、その後もサーブレットに転送されます。サーブレットに何か問題があることがすぐにはわかりません。そのため、設定されているフィルターも確認してみるとよいでしょう。

編集:問題の診断にさらに役立つものがいくつかあります...

この問題を診断するための最初のステップは、例外がスローされている場所を正確に確認することです。ラインで投げられていると仮定します

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

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

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

幸運を!

サーブレットはもうありませんが存在リクエストオブジェクトにアクセスしようとしているので、

これは..です サーブレットの前方またはステートメントを含めるには、メソッドのブロックの実行を停止しません。それはちょうど、他の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
}

と最後の行で、前方に一度だけ行う...

あなたはまた、各フォワード(後にreturnステートメントを使用してこの問題を解決することができます)、または(各フォワードを置く)場合で... elseブロック

私は削除

        super.service(req, res);

そして、それは私のために罰金を働いていた。

バンプ...

私はちょうど同じエラーが発生しました。私は明示的にスーパークラスのコンストラクタ

を起動するだけでなく、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

あなたは流れを転送またはリダイレクトしている間、あなたはのリターンのステートメントを追加する必要があります。

例:

もしforwardind、

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

リダイレクトする場合は、

    response.sendRedirect(roundTripURI);
    return;

あなたは、単にこれを行うことができ、戻りフォワード方式の後:

return null;

これは、現在のスコープを中断します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top