- Cannot forward after response has been committed in servlet filter [duplicate]
- java.lang.IllegalStateException: Cannot (forward | sendRedirect | create session) after response has been committed
- 9 Answers 9
- forward / sendRedirect / sendError do NOT exit the method!
- Do not write any string before forward / sendRedirect / sendError
- Do not write any file before forward / sendRedirect / sendError
- Do not call forward / sendRedirect / sendError in JSP
- See also:
- java.lang.IllegalStateException: Cannot forward after response has been committed in servlet [duplicate]
Cannot forward after response has been committed in servlet filter [duplicate]
I am trying to catch exception in servlet filter and the forward to an error page. But when I catched the exception in filter and using request.getRequestDispatcher(«/error.html»).forward(request, response); to forward to the error page it is throwing me the error saying Cannot forward after response has been committed . Code:
public class TestFilter implements Filter < private String encoding = null; public void destroy() < encoding = null; >@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException < // TODO Auto-generated method stub try < chain.doFilter(request, response); double value = 1/0;// to make an exception >catch (Exception e) < // TODO Auto-generated catch block e.printStackTrace(); request.getRequestDispatcher("/error.html").forward(request, response); >> @Override public void init(FilterConfig arg0) throws ServletException < // TODO Auto-generated method stub >>
java.lang.ArithmeticException: / by zero at com.baoming.filter.TestFilter.doFilter(TestFilter.java:27) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Jan 26, 2017 3:01:54 下午 org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [springmvc] in context with path [/Monitor] threw exception java.lang.IllegalStateException: Cannot forward after response has been committed at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:328) at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318) at com.baoming.filter.TestFilter.doFilter(TestFilter.java:31) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
I made the ArithmeticException to specify the problem. If I move the code double value = 1/0; before chain.doFilter(request, response); ,it will not throw Cannot forward after response has been committed exception. I don’t know how to fix the problem. If an exception occurs after chain.doFilter(request, response); , how can I catch it and forward to another page?
java.lang.IllegalStateException: Cannot (forward | sendRedirect | create session) after response has been committed
Its difficult to see like this, but it seems you’ve already send some output before your forward. Could you please print the full code and check if you don’t have any filter in place ?
9 Answers 9
forward / sendRedirect / sendError do NOT exit the method!
A common misunderstanding among starters is that they think that the call of a forward() , sendRedirect() , or sendError() method would magically exit and «jump» out of the method block, hereby ignoring the remnant of the code. For example in a servlet:
protected void doXxx(. ) < if (someCondition) < response.sendRedirect(. ); >dispatcher.forward(. ); // This is STILL invoked when someCondition is true! >
public void doFilter(. ) < if (someCondition) < response.sendRedirect(. ); >chain.doFilter(. ); // This is STILL invoked when someCondition is true! >
This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of System#exit() of course). When the someCondition in above example is true and you’re thus calling forward() or doFilter() after sendRedirect() or sendError() on the same request/response, then the chance is big that you will get the exception:
java.lang.IllegalStateException: Cannot forward after response has been committed
This also applies to the inverse condition. If the if statement calls a forward() and you’re afterwards calling sendRedirect() or sendError() , then below exception can be thrown:
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
To fix this, you need either to add a return; statement afterwards
protected void doXxx(. ) < if (someCondition) < response.sendRedirect(. ); return; >dispatcher.forward(. ); >
. or to introduce an else block.
protected void doXxx(. ) < if (someCondition) < response.sendRedirect(. ); >else < dispatcher.forward(. ); >>
To naildown the root cause in your code, just search for any line which calls a forward() , sendRedirect() or sendError() 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, use setStatus() instead.
Do not write any string before forward / sendRedirect / sendError
Another 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.
protected void doXxx() < out.write("some html
"); // . dispatcher.forward(); // Fail! >
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:
java.lang.IllegalStateException: Cannot forward after response has been committed
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 $ . See also our Servlets wiki page to learn how to use Servlets the right way.
Do not write any file before forward / sendRedirect / sendError
Another 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 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 / sendError in JSP
Yet another probable cause is that the forward() , sendRedirect() or sendError() methods are invoked via Java code embedded in a JSP file in form of old fashioned way , 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(» . 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?
java.lang.IllegalStateException: Cannot forward after response has been committed in servlet [duplicate]
In my project, I prohibit a user every page only if he is already logged on. That is why I wrote the below code. When I type in browser, for example, http://localhost:8080/JSP1/Students, I come to the login.jsp page. But after I input the loginid and password, only blank page http://localhost:8080/JSP1/Logged appears and GlassFish says there is an exception in
if (userPath.equals("/Students")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Students.jsp"); requestDispatcher.forward(request, response); >java.lang.IllegalStateException: PWC1227: Cannot forward after response has been committed
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < HttpSession ses = request.getSession(); String login = (String)ses.getAttribute("login"); String password = (String)ses.getAttribute("password"); if ((login==null)|(password==null))< RequestDispatcher requestDispatcher = request.getRequestDispatcher("/login.jsp"); requestDispatcher.forward(request, response); >//Now we think that we are successfully logged in String userPath = request.getServletPath(); // System.out.println(userPath); if (userPath.equals("/Login")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/login.jsp"); requestDispatcher.forward(request, response); >if (userPath.equals("/Students")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Students.jsp"); requestDispatcher.forward(request, response); >if (userPath.equals("/Student")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Student.jspx"); requestDispatcher.forward(request, response); >if (userPath.equals("/StudentEdit")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/StudentEdit.jsp"); requestDispatcher.forward(request, response); >> @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException < // processRequest(request, response); PrintWriter out = response.getWriter(); String userPath = request.getServletPath(); System.out.println(userPath); if (request.getRequestURI().equals("/Logged"))< String Login = request.getParameter("login"); String Password = request.getParameter("password"); request.getSession().setAttribute("login", Login); request.getSession().setAttribute("password", Password); RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Students.jsp"); requestDispatcher.forward(request, response); >if (userPath.equals("/addStudent")) < // System.out.println(request.getContextPath()); String Name = request.getParameter("name"); String Surname = request.getParameter("surname"); String Login = request.getParameter("login"); String Password = request.getParameter("password"); Student student = new Student(Name,Surname,Login,Password); if (student != null) < dao.insertStudent(student); >else < System.out.println("Not valid parameter. "); >RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Students.jsp"); requestDispatcher.forward(request, response); > if (request.getRequestURI().equals("/Edit")) < System.out.println("We work with students. "); String delete = request.getParameter("Add_new_student"); if (delete != null)< RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Student.jspx"); requestDispatcher.forward(request, response); >Enumeration parameters = request.getParameterNames(); while (parameters.hasMoreElements()) < String parameterName = (String) parameters.nextElement(); String parameterValue = request.getParameter(parameterName); String norder = parameterName.substring(parameterName.indexOf("_")+1); ArrayListcurStudents = dao.getAllStudents(); int norderint = Integer.parseInt(norder); Student studentToWork = curStudents.get(norderint); String actionToDo = parameterName.substring(0, parameterName.indexOf("_")); if (actionToDo.equals("Edit")) < RequestDispatcher requestDispatcher = request.getRequestDispatcher("/StudentEdit.jsp"); ServletContext cont = request.getServletContext(); cont.setAttribute("studentToEdit", studentToWork); requestDispatcher.forward(request, response); >else < boolean attemp = dao.deleteStudent(studentToWork); if (attemp)< RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Students.jsp"); requestDispatcher.forward(request, response); >else < out.println("Unsuccessfull attemp to delete a Student"); >> > > if (userPath.equals("/EditStudent"))< System.out.println("We work with StudentEdit!"); Student studentToEdit = (Student)request.getSession().getAttribute("studentToEdit"); String newName = request.getParameter("name"); String newSurname = request.getParameter("surname"); String newLogin = request.getParameter("login"); String newPassword = request.getParameter("password"); Student newStudent = new Student(newName, newSurname,newLogin,newPassword); boolean update = dao.updateStudent(studentToEdit, newStudent); if (update)< out.println("You have successfully edited a Student=" + studentToEdit.toString() + " to Student="+ newStudent.toString()); > else < out.println("
Unsuccessful attempt to edit!
" ); > > >