2

This is the code of servlet which handles errors at the web server:

public class GeneralErrorServlet extends HttpServlet {

  protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String referer = request.getHeader("Referer");
    String url = String.valueOf(request.getAttribute("javax.servlet.error.request_uri"));
    String queryString = request.getQueryString();
    String statusCode = String.valueOf(request.getAttribute("javax.servlet.error.status_code"));
    String message = String.valueOf(request.getAttribute("javax.servlet.error.message"));
    Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
    if (referer != null && !"null".equals(referer) && !referer.contains("googleads.g.doubleclick.net/pagead")) {
      Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
          "GENERAL ERROR MESSAGE: requestUrl= {0}, referer:{1}, statusCode={2}, message = {3}", new Object[]{url, referer, statusCode, message});
    } else {
      Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
          "GENERAL ERROR MESSAGE: requestUrl= {0} , statusCode={1}, message = {2}", new Object[]{url, statusCode, message});
    }
    if (throwable != null) {
      Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "ERROR CAUSE:" + throwable.getMessage(), throwable);
    }
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    // rest omitted since the previous line creates problems

The problem is that I see frequently in my server.logs in a production environment that response stream has already been used but I cannot reproduce it in localhost (error message usually works). Any idea what to do around that problem?

This is the example of what I see frequently in a production log:

Servlet.service() for servlet GeneralErrorServlet threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
        at org.apache.catalina.connector.Response.getWriter(Response.java:777)
        at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:224)
        at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:152)
        at common.GeneralErrorServlet.processRequest(GeneralErrorServlet.java:48)
        at common.GeneralErrorServlet.doGet(GeneralErrorServlet.java:110)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
        at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:875)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:739)
        at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:695)
        at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:626)

FYI, This is how is this error servlet mapped:

<servlet-mapping>
    <servlet-name>GeneralErrorServlet</servlet-name>
    <url-pattern>/common/general_error</url-pattern>
</servlet-mapping>


<error-page>
    <error-code>404</error-code>
    <location>/common/general_error</location>
</error-page>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/common/general_error</location>
</error-page>

I know this question is long, but I don't know to explain it better and shorter at the moment.

Mladen Adamovic
  • 3,071
  • 2
  • 29
  • 44
  • Did you try some of these? I think the problem is really with lines you omitted in your question which are keeping your response stream open for a while. http://stackoverflow.com/questions/21039471/spring-getoutputstream-has-already-been-called-for-this-response – kosa Jul 13 '16 at 16:31
  • ommitted lines are just bunch of non-blocking prints like `out.println("");` which doesn't access the DB or any remote service – Mladen Adamovic Jul 13 '16 at 16:46
  • 1
    do you have any filters defined in this server which get access to `ServletRequest` and `ServerResponse` objects? – diginoise Jul 13 '16 at 16:49
  • Do you have any flush statements at end? are there any redirects or statements related to how you are moving to next view? – kosa Jul 13 '16 at 17:12
  • @diginoise I have only ExpiresFilter enabled for js, png, jpg and css files. – Mladen Adamovic Jul 14 '16 at 10:52
  • @Nambari flush statements at the end of what? I have some servlets which do redirects – Mladen Adamovic Jul 14 '16 at 10:54
  • @MladenAdamovic could you show your other servlet methods which call `processRequest()` - perhaps you do some writing to the output stream already. You also mention that the traffic can get redirected by other servlets. Could they be writing to the `OutputStream` of the response? – diginoise Jul 14 '16 at 11:01
  • @diginoise it could be the case that servlets which caused error page to trigger actually did write to the response. I don't understand than examples like this: http://www.avajava.com/tutorials/lessons/how-do-i-create-a-jsp-error-page-to-handle-exceptions.html the internet is full of them . What I could do is try to catch Exceptions generated by GeneralErrorServlet to prevent GeneralErrorServlet retriggering or triggering on itself. I just don't understand why it then doesn't retrigger infinitely. I'll test new version of that servlet which catch that exception. – Mladen Adamovic Jul 14 '16 at 12:22

0 Answers0