title: AlreadyCommittedException: Response already committed after doing buildPage but before writing response from PageInfo (HippoCMS)
body: <p>We serve our CMS (Hippo) content using a REST endpoints, and I noticed strange behavior that happens intermittently: </p>
  
  <p>Time and again, when invoking an end point (e.g., <a href="http://site.name/api/articles/" rel="nofollow">http://site.name/api/articles/</a>) for the first time after a period of inactivity or server restart, it throws the following exception. If the page is refreshed second time, it all works.</p>
  
  <pre><code>Throwable thrown during doFilter on request with URI: /site/fr-ca/api/articles/ and Query: nullResponse already committed after doing buildPage but before writing response from PageInfo.
  [INFO] [talledLocalContainer] net.sf.ehcache.constructs.web.AlreadyCommittedException: Response already committed after doing buildPage but before writing response from PageInfo.
  [INFO] [talledLocalContainer]   at net.sf.ehcache.constructs.web.filter.CachingFilter.doFilter(CachingFilter.java:220)
  [INFO] [talledLocalContainer]   at net.sf.ehcache.constructs.web.filter.Filter.doFilter(Filter.java:86)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
  [INFO] [talledLocalContainer]   at org.hippoecm.hst.container.XSSUrlFilter.doFilter(XSSUrlFilter.java:52)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
  [INFO] [talledLocalContainer]   at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
  [INFO] [talledLocalContainer]   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:106)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
  [INFO] [talledLocalContainer]   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:142)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
  [INFO] [talledLocalContainer]   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
  [INFO] [talledLocalContainer]   at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617)
  [INFO] [talledLocalContainer]   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
  [INFO] [talledLocalContainer]   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
  [INFO] [talledLocalContainer]   at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
  [INFO] [talledLocalContainer]   at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
  [INFO] [talledLocalContainer]   at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
  [INFO] [talledLocalContainer]   at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
  [INFO] [talledLocalContainer]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  [INFO] [talledLocalContainer]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  [INFO] [talledLocalContainer]   at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  [INFO] [talledLocalContainer]   at java.lang.Thread.run(Thread.java:745)
  </code></pre>
  
  <p>where the culprit code is given below:</p>
  
  <pre><code>protected void doFilter(final HttpServletRequest request,
          final HttpServletResponse response, final FilterChain chain)
          throws AlreadyGzippedException, AlreadyCommittedException,
          FilterNonReentrantException, LockTimeoutException, Exception {
      if (response.isCommitted()) {
          throw new AlreadyCommittedException(
                  "Response already committed before doing buildPage.");
      }
      logRequestHeaders(request);
      PageInfo pageInfo = buildPageInfo(request, response, chain);
  
      if (pageInfo.isOk()) {
          if (response.isCommitted()) {
              throw new AlreadyCommittedException(
                      "Response already committed after doing buildPage"
                              + " but before writing response from PageInfo.");
          }
          writeResponse(request, response, pageInfo);
      }
  }
  </code></pre>
  
  <p>Line 220 is the one that throws <code>AlreadyCommittedException()</code> inside the <code>if(response.isCommitted()) {}</code>, </p>
  
  <p>which makes me think the server thinks at this point the response is already committed. I have checked my code and I can confirm I do not do any "in-between" commits or writing to the servlet's output stream.</p>
  
  <p>But what's most annoying, it only happens on the first page call, and if I refresh the page the problem is gone.</p>
  
  <p>Additional detail: we have a caching filter that caches a page and invokes the CacheFilter:</p>
  
  <pre><code>public class WaPageCache extends SimpleCachingHeadersPageCachingFilter {
  
      @Override
      protected String calculateKey(HttpServletRequest httpRequest) {
          String simpleKey = super.calculateKey(httpRequest);
          final String requestURI = httpRequest.getRequestURI();
          final String key = requestURI.contains("/binaries/content") ? simpleKey : simpleKey + httpRequest.getHeader("Cookie");
          return key;
      }
  
      @Override
      protected CacheManager getCacheManager() {
          ClassLoader standardClassloader = Thread.currentThread().getContextClassLoader();
          URL url = null;
          if (standardClassloader != null) {
              url = standardClassloader.getResource("ehcache-web-caching.xml");
          }
          return CacheManager.create(url);
      }
  }
  </code></pre>
  
  <p>Has anyone else fought similar problem and what are the possible causes/solutions/hints on solution?</p>