I use Spring's WebSocketConnectionManager to work with WebSockets. Sometimes the connection closes and I have to reconnect. But I didn't find any proper solution to do that. Can I use WebSocketConnectionManager for restore (reconnect to) session? In the sources I see, that connection establishes by the following code:
@Override
protected void openConnection() {
if (logger.isInfoEnabled()) {
logger.info("Connecting to WebSocket at " + getUri());
}
ListenableFuture<WebSocketSession> future =
this.client.doHandshake(this.webSocketHandler, this.headers, getUri());
future.addCallback(new ListenableFutureCallback<WebSocketSession>() {
@Override
public void onSuccess(@Nullable WebSocketSession result) {
webSocketSession = result;
logger.info("Successfully connected");
}
@Override
public void onFailure(Throwable ex) {
logger.error("Failed to connect", ex);
}
});
}
And I'm using this Manager when my spring boot application start by:
WebSocketConnectionManager connectionManager = new WebSocketConnectionManager(
new StandardWebSocketClient(), webSocketHandler, "wss://localhost:8080/ws/");
connectionManager.start();
But what I have to do when connection closes? I tried to copy a piece of code from openConnection(), and use it for update the session directly in webSocketHandler, and it works. But it looks like dirty workaround.
Does anybody know how to do it correctly? Thank you.
In one of my projects, I came around similar situation. So, I resorted on using start() and stop() method with access to WebSocketManager as a bean in a connection manager class. I'd created a sample project for websocketserver and websocketclient sometime back. Just added reconnect feature to it.
Also, I was not reconnecting on every connection close. Only on close status 1006(Abnormal Closure), 1011(Internal Error) and 1012(Service Restart).
The project can be directly downloaded and run.
I don't think you need to copy the openConnection
function directly in webSocketHandler
. You should be able to re-use the openConnection
function and capture the afterConnectionClose
event from inside of WebSocketConnectionManager.
I think you are on the right track. Unfortunately, I don't think this is a dirty workaround due to the fact that nothing exists inside of WebSocketConnectionManager to handle WebSocket "on close" events.
In the docs for WebSocketConnectionManager I see this excerpt:
A WebSocket connection manager that is given a URI, a WebSocketClient, and a WebSocketHandler, connects to a WebSocket server through ConnectionManagerSupport.start() and ConnectionManagerSupport.stop() methods. If ConnectionManagerSupport.setAutoStartup(boolean) is set to true this will be done automatically when the Spring ApplicationContext is refreshed.
The equivalent of JavaScript's WebSocket onClose
for Spring's WebSocketConnectionManager seems to be afterConnectionClosed
which you can find in the docs for WebSocketHandler. Indeed, the docs on afterConnectionClosed
say:
afterConnectionClosed
- Invoked after the WebSocket connection has been closed by either side, or after a transport error has occurred. Although the session may technically still be open, depending on the underlying implementation, sending messages at this point is discouraged and most likely will not succeed.
Therefore, I think your Spring code needs to include something like the pseudo-code below:
afterConnectionClosed(WebSocketSession result, CloseStatus closeStatus) {
// Spring code here to delay retry for re-connecting to WebSocket.
openConnection()
};
The JavaScript equivalent would be:
ws.onclose = function(){
// Try to reconnect in 5 seconds
setTimeout(function(){start(websocketServerLocation)}, 5000);
};
Hopefully someone with Spring experience can come along and edit this post and point out where I am correct and where I am mistaken. I don't use Spring but I have some WebSocket experience. In JavaScript I use reconnecting-websocket so my gut tells me you'll essentially need to implement this functionality in Spring if it does not already exist. Or as this answer suggests for JavaScript, you need to capture the onClose
event from the WebSocket and reconnect.
Interestingly there are some methods named onClose
in the Spring repo so perhaps this question needs revisiting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With