java.lang.IllegalStateException:応答がコミットされた後は (転送 | sendRedirect | セッションの作成) できません
-
22-09-2019 - |
質問
このメソッドはスローします
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);
ただし、コードの後半で、転送を試みた後に出力ストリームに出力しようとしているときに、このコードがスローされていることがわかるかもしれません。上記の行から来ている場合は、この行の前のどこかに次のいずれかがあることを意味します。
- データを出力ストリームに出力する、または
- 事前に別のリダイレクトを実行します。
幸運を!
これは..です サーブレットの前方またはステートメントを含めるには、メソッドのブロックの実行を停止しません。それはちょうど、他の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;
これは、現在のスコープを中断します。