This method throws
java.lang.IllegalStateException: Cannot forward after response has been committed
and I am unable to spot the problem. Any help?
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/sendErrordo NOT exit the method!A common misunderstanding among starters is that they think that the call of a
forward(),sendRedirect(), orsendError()method would magically exit and "jump" out of the method block, hereby ignoring the remnant of the code. For example in a servlet:Or in a filter:
This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of
System#exit()of course). When thesomeConditionin above example istrueand you’re thus callingforward()ordoFilter()aftersendRedirect()orsendError()on the same request/response, then the chance is big that you will get the exception:This also applies to the inverse condition. If the
ifstatement calls aforward()and you’re afterwards callingsendRedirect()orsendError(), then below exception can be thrown:To fix this, you need either to add a
return;statement afterwards… or to introduce an else block.
To naildown the root cause in your code, just search for any line which calls a
forward(),sendRedirect()orsendError()without exiting the method block or skipping the remnant of the code. This can be inside the same servlet before the particular code line, but also in any servlet or filter which was been called before the particular servlet.In case of
sendError(), if your sole purpose is to set the response status, usesetStatus()instead.Do not write any string before
forward/sendRedirect/sendErrorAnother probable cause is that the servlet writes to the response while a
forward()will be called, or has been called in the very same method.The response buffer size defaults in most server to 2KB, so if you write more than 2KB to it, then it will be committed and
forward()will fail the same way:Solution is obvious, just don’t write to the response in the servlet. That’s the responsibility of the JSP. You just set a request attribute like so
request.setAttribute("data", "some string")and then print it in JSP like so${data}. See also our Servlets wiki page to learn how to use Servlets the right way.Do not write any file before
forward/sendRedirect/sendErrorAnother probable cause is that the servlet writes a file download to the response after which e.g. a
forward()is called.This is technically not possible. You need to remove the
forward()call. The enduser will stay on the currently opened page. If you actually intend to change the page after a file download, then you need to move the file download logic to page load of the target page. Basically: first create a temporary file on disk using the way mentioned in this answer How to save generated file temporarily in servlet based web application, then send a redirect with the file name/identifier as request param, and in the target page conditionally print based on the presence of that request param a<script>window.location='...';</script>which immediately downloads the temporary file via one of the ways mentioned in this answer Simplest way to serve static data from outside the application server in a Java web application.Do not call
forward/sendRedirect/sendErrorin JSPYet another probable cause is that the
forward(),sendRedirect()orsendError()methods are invoked via Java code embedded in a JSP file in form of old fashioned way<% scriptlets %>, a practice which was officially discouraged since 2003. For example:The problem here is that JSP internally immediately writes template text (i.e. HTML code) via
out.write("<!DOCTYPE html> ... etc ...")as soon as it’s encountered. This is thus essentially the same problem as explained in previous section.Solution is obvious, just don’t write Java code in a JSP file. That’s the responsibility of a normal Java class such as a Servlet or a Filter. See also our Servlets wiki page to learn how to use Servlets the right way.
See also:
Unrelated to your concrete problem, your JDBC code is leaking resources. Fix that as well. For hints, see also How often should Connection, Statement and ResultSet be closed in JDBC?