IllegalStateException: Cannot call sendError() after the response has been

I am running Vaadin 7.2.4 on Tomcat 7.0.42 on Java 1.7.0_51 and if I leave my logged in browser session activate longer than the session timeout, I sometimes get a “Session Expired” message, but lately I’m getting “Communication problem” instead with this stack trace:


Jul 17, 2014 1:31:32 PM org.apache.catalina.core.StandardWrapperValve invoke

SEVERE: Servlet.service() for servlet [OpenESignFormsVaadin7Application]
in context with path
[/open-eSignFormsVaadin7] threw exception
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:451)
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:120)
at com.vaadin.server.communication.HeartbeatHandler.handleSessionExpired(HeartbeatHandler.java:91)
at com.vaadin.server.VaadinService.handleSessionExpired(VaadinService.java:1514)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1415)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:237)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

My web.xml has settings like the following (push is currently disabled because it’s just not working for us yet):

[size=2]
[font=courier new]

heartbeatInterval
300

  <init-param>
      <description>Want idle sessions to expire, after 3 missed heartbeats, since heartbeat will otherwise keep alive as long as the browser is open</description>
      <param-name>closeIdleSessions</param-name>
      <param-value>true</param-value> <!-- Default: false -->
  </init-param>
  <!-- disabled, automatic, manual -->
  <init-param>
    <param-name>pushmode</param-name>
    <param-value>disabled</param-value>
 </init-param>
   <!-- Using long-polling since push still not quite right in Vaadin 7.2 -->
   <!-- websocket, streaming, long-polling -->
  <init-param>
    <param-name>transport</param-name>
    <param-value>long-polling</param-value>
 </init-param>
<async-supported>true</async-supported> <!-- Enable if using PUSH -->

[/font]
[/size]

I believe that this may be referenced by
ticket 14811
, but it would be nice if this exception could be suppressed.

Unlike the ticket, we are running Tomcat 8.0.15, no Apache proxy, on Vaadin 7.3.6.

While not positive, it seems we can reproduce it by having an active user session, and then restart Tomcat, and then leave the browser page open but no longer interact. It appears that the browser HEARTBEAT messages to the defunct session results in the sendError() exceptions. Again, all code is in Tomcat/Vaadin, not our code, so it’s something we can fix. Because our heartbeat is set at 300, we tend to get an exception per such defunct browser frequently and it makes it harder for us to detect real issues.

Here’s the Tomcat access log showing the request coming in:

xx.xx.148.213 - - [09/Dec/2014:11:19:07 -0800]
 "POST /webapp/ui/HEARTBEAT/?v-uiId=0 HTTP/1.1" 500 4425 13 Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; BOIE8;ENUSMSCOM)

Note that an error 500 is sent back, so not sure why the client browser continues to send heartbeats without itself saying it’s gone.

Here’s the related exception:

Dec 09, 2014 11:19:07 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [OpenESignFormsVaadin7Application]
 in context with path 
[/webapp] threw exception
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
        at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:462)
        at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:120)
        at com.vaadin.server.communication.HeartbeatHandler.handleSessionExpired(HeartbeatHandler.java:91)
        at com.vaadin.server.VaadinService.handleSessionExpired(VaadinService.java:1515)
        at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1416)
        at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:305)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
        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:613)
        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)