Vaadin 7.6/Tomcat 8 - Dirty UI closings

Vaadin UIs are closed when:

  • the user closes the browser window and three heartbeats are missed,
  • the user goes quiet and the idle session is closed after timeout,
  • the user initiaties an explicit UI close (I provide a button for that).

In any of these circumstances, I am getting the following stack trace a small fraction of the time - maybe one in 20 UI closings. The rest are closed without error. So I suspect a race condition between Vaadin’s push, Tomcat and Atmosphere is taking place at UI closing time. The stack trace indicates:

  • Vaadin calls a disconnect method in AtmospherePushConnection
  • Tomcat/atmosphere tries to write a close message to websocket
  • websocket has already closed so the error is thrown.

Something is being done in the wrong order. Any ideas about how UI closing can always be done cleanly?

Java 8, Tomcat 8.0.30, Vaadin 7.6.0, manual push using websocket, Ubuntu 14.04

java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: Unable to write the complete message as the WebSocket connection has been closed
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:282)
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:584)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:488)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:455)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:449)
    at org.atmosphere.container.version.JSR356WebSocket.close(JSR356WebSocket.java:142)
    at org.atmosphere.cpr.AtmosphereResourceImpl.close(AtmosphereResourceImpl.java:860)
    at com.vaadin.server.communication.AtmospherePushConnection.disconnect(AtmospherePushConnection.java:312)
    at com.vaadin.ui.UI.setPushConnection(UI.java:1591)
    at com.vaadin.ui.UI.setSession(UI.java:473)
    at com.vaadin.server.VaadinSession.removeUI(VaadinSession.java:869)
    at com.vaadin.server.VaadinService$1$1.run(VaadinService.java:481)
    at com.vaadin.ui.UI.accessSynchronously(UI.java:1381)
    at com.vaadin.server.VaadinService$1.run(VaadinService.java:469)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.vaadin.server.VaadinService.runPendingAccessTasks(VaadinService.java:1835)
    at com.vaadin.server.VaadinSession.unlock(VaadinSession.java:989)
    at com.vaadin.server.VaadinService.requestEnd(VaadinService.java:1356)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1423)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:364)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    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.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:2437)
    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)
Caused by: java.util.concurrent.ExecutionException: java.io.IOException: Unable to write the complete message as the WebSocket connection has been closed
    at org.apache.tomcat.websocket.FutureToSendHandler.get(FutureToSendHandler.java:102)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:275)
    ... 41 more
Caused by: java.io.IOException: Unable to write the complete message as the WebSocket connection has been closed
    at org.apache.tomcat.websocket.WsSession.registerFuture(WsSession.java:658)
    at org.apache.tomcat.websocket.FutureToSendHandler.get(FutureToSendHandler.java:92)
    ... 42 more

Sounds like https://dev.vaadin.com/ticket/19376, track that

Thanks Artur - I’ll follow 19376’s progress.

On a possibly related note, Tomcat 8.0.31 is due to correct, or possibly work around a
closing error
. One poster to that ticket comented:

“Most Websocket clients are quite polite when closing websockets, they will send a close frame and then wait for the handshake before closing the TCP connection.”

I wonder if Vaadin is being “polite”?

Had the same problem. Tomcat 8.0.37 fixed it for me. Possible earlier versions would too.