In some application setups, the WebSocket server does not transmit the disconnect message to the client, so that the client has no idea that the established connection has been terminated.
This issue arises when the application uses SimpleBrokerMessageHandler and the error handler is set to the instance of StompSubProtocolErrorHandler or an extended class that does not override the handleErrorMessageToClient method.
The commit fixes disconnect message population so that java.lang.IllegalArgumentException: No StompHeaderAccessor
exception is not thrown in the handleErrorMessageToClient method in StompSubProtocolErrorHandler class.
A reproducible example for the case is available here: - https://github.com/alexjansons/spring-sandbox/blob/main/web-socket/disconnect-error/src/main/java/com/example/websocket/disconnecterror/Application.java - https://github.com/alexjansons/spring-sandbox/blob/main/web-socket/disconnect-error/src/test/java/com/example/websocket/disconnecterror/ApplicationTests.java
The issue arises when the client fails to send heartbeats for specific period, causing the server to terminate the session by invoking the handleDisconnect
method in the SimpleBrokerMessageHandler.HeartbeatTask
class. This issue was discovered in spring-websocket-5.3.13 but still persists in the latest code base.
If the error handler is not set, then there is no problem as the message is delivered to the client in this scenario. A reproducible example that illustrates this is the DisconnectWithoutErrorHandler.test
found at https://github.com/alexjansons/spring-sandbox/blob/main/web-socket/disconnect-error/src/test/java/com/example/websocket/disconnecterror/ApplicationTests.java#L97.
However if the error handler is set to StompSubProtocolErrorHandler
class instance or the instance of extended class given that the latter does not implement it's own handleErrorMessageToClient
method, the disconnect message transmission process faces the IllegalArgumentException
exception in the aforementioned method. The exception is caught and then silently ignored in SubProtocolWebSocketHandler.handleMessage
method, which results in no message being sent to the client. This case is covered in DisconnectWithErrorHandler.test
at https://github.com/alexjansons/spring-sandbox/blob/main/web-socket/disconnect-error/src/test/java/com/example/websocket/disconnecterror/ApplicationTests.java#L83.
A workaround for this issue is to extend the StompSubProtocolErrorHandler
class for the error handler and re-implement the method handleErrorMessageToClient
so that it does not generate an exception. An example of this workaround can be found at https://github.com/alexjansons/spring-sandbox/blob/main/web-socket/disconnect-error/src/main/java/com/example/websocket/disconnecterror/Application.java#L24.