Sunday, July 4, 2021

How to fix java.lang.IllegalStateException: getWriter() has already been called for this response [Solution]

This error comes when a Servlet calls the getOutputStream() method on the response object for writing something after calling the include() method. Suppose a Servlet calls the include() method to load the response of a JSP. Since JSP has already written the response on it hence again opening OutputStream on the response object is illegal, you get the java.lang.IllegalStateException: getWriter() has already been called for this response error. This error also comes when you try to include the response of another Servlet and then tries to write something on the output stream again. In short, your Servlet should never write anything on the response object after calling the include() method. 

Here is the detailed stack trace of exception :
java.lang.IllegalStateException: getWriter() has already been called for this response
org.apache.catalina.connector.Response.getOutputStream(Response.java:580)
org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:183)
HelloServlet.doGet(HelloServlet.java:20)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:723)

This a perfect beginner error who tries to learn Servlet and JSP by trial and error. If you know the correct way to use the include() and forward() method then you won't face this type of problem. That again highlights the importance of learning new technology from a good book like Head First Servlet and JSP. The book will no doubt teach you the basics, which is quite important in the long journey of learning new features every day.

How to solve java.lang.IllegalStateException: getWriter() has already been called for this response



java.lang.IllegalStateException: getWriter() has already been called for this response Solution

If you look at the error carefully, you can see it pointing to HelloServlet.doGet() method at line 20, let's see the HelloServlet class to find out what's happening at line 20.

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
       throws ServletException, IOException {
        String userAgent = req.getHeader("user-agent");
        String clientBrowser = "Not known!";
        if (userAgent != null)
            clientBrowser = userAgent;
        req.setAttribute("client.browser", clientBrowser);
        req.getRequestDispatcher("/hello.jsp").include(req, resp);
        resp.getOutputStream().println("This is written from Servlet");
    }

}

You can see that at line 20 we are calling the getOutputStream() after calling the include() method of RequestDispather, this is causing the problem. Remove this line and your program will run fine. The bottom line is you should try to write anything on the output stream of Servlet after calling the include() and forward() method because the response is already committed.


No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.