5

I'm using Tomcat 8.5.23 in production with Servlets (with Spring autowiring capabilities if relevant) response.getWriter() return null in production

It happens also when calling chain.doFilter(req, res); in custom filter:

public class MyFilter implements Filter {
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        chain.doFilter(req, res);
  }
  public void init(FilterConfig filterConfig) {}
  public void destroy() {}
}

Exception:

Request processing failed; nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause
java.lang.IllegalStateException: getWriter() has already been called for this response
        at org.apache.catalina.connector.Response.getOutputStream(Response.java:591)
        at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:194)
        at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:89)
        at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:106)
        at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:41)
        at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:247)
        at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:203)
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)

I tried adding HttpServletResponseWrapper but it didn't worked

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • The `HttpServletResponse` as implemented in tomcat cannot return null. There are two cases: 1. `getOutputStream()` was called -> it will throw `IllegalStateException`, 2. the inner writer is null: it will create a new `CoyoteWriter`. Must probably some of the filters are wrapping the response object and do not handle some case correctly. Just step through the filter chain with a debugger. Definitely not a tomcat issue. – Svetlin Zarev Jun 05 '19 at 13:15
  • @SvetlinZarev the problem it happens only few times, and currently can't be reproduced – Ori Marko Jun 05 '19 at 13:17

1 Answers1

1

Your filter code looks OK, the problem is elsewhere. A comment already mentioned that getWriter() cannot return null. Have a look at the code where this seems to occur. Chances are that the code tries to assign the writer to a variable, but catches and ignores that exception. After the point where the exception gets ignored, somebody tries to use the variable, but it contains null because the assignment didn't take place.

One common case where these "already called" errors may happen is in error handling. A servlet started to send a response, therefore called getWriter(). Then it runs into an error, and the error handling tries to write an error response, therefore calls getWriter() again. You cannot reproduce the problem because that error situation occurs randomly.

Roland Weber
  • 3,395
  • 12
  • 26