How to handle websocket @OnError

Malt picture Malt · Jan 1, 2015 · Viewed 12.3k times · Source

What's the correct way of handling a websocket error besides logging it?

Regarding onError(), the Endpoint documentation states that:

Developers may implement this method when the web socket session creates some kind of error that is not modeled in the web socket protocol. This may for example be a notification that an incoming message is too big to handle, or that the incoming message could not be encoded.

There are a number of categories of exception that this method is (currently) defined to handle:

  • connection problems, for example, a socket failure that occurs before the web socket connection can be formally closed. These are modeled as SessionExceptions

  • runtime errors thrown by developer created message handlers calls.

  • conversion errors encoding incoming messages before any message handler has been called. These are modeled as DecodeExceptions

Are all of these types of exceptions fatal, causing the websocket to close?

Should the onError() method close the websocket (call Session.close()) if an error occurs?

So far, I assumed that it's my responsibility to cleanly close the session, informing the client about the close reason. This is why my onError() tried invoking session.close() if session.isOpen() returned true, but this caused tomcat (8.0.15) to throw a NullPointerException:

...
Caused by: java.lang.NullPointerException
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:96)
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:444)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:335)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:264)
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:536)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:464)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
    at my.package.MyEndpoint.onWebSocketError(MyEndpoint.java:229)
    ... 18 more

Is this a tomcat bug, a misunderstanding on my part, or both?

Edit: It seems that the Java EE websocket example dukeeetf2 assumes that errors are fatal; and that there's no need to close the session. The errors are logged, and the session is removed:

@OnError
public void error(Session session, Throwable t) {
    /* Remove this connection from the queue */
    queue.remove(session);
    logger.log(Level.INFO, t.toString());
    logger.log(Level.INFO, "Connection error.");
}

Answer

Pavel Bucek picture Pavel Bucek · Jan 2, 2015

@OnError method invocation does not mean that Session will be closed; You can do whatever you want, it depends in the contract specified by your application.

stacktrace from tomcat implementation seems like a bug.

ad dukeeetf2 sample - seems like this code contains other assumptions - Endpoints does not throw an exception, so everything caught here is from underlying WebSocket framework implementation. That does not really mean that there is an "Connection Error"; I would maybe do close right away (if this is how I wan't my application to handle errors); this implementation could result in opened connections without any messages.