Affects: \<5.2.6>


When websocket connection is broken due to network issues, WebSocketConnectionManager does not try to reconnect. I could not could any existing solution to that, not requiring any coding.

To my understanding: it keeps the status "isRunning()==true" and does not bother to look at used WebSocketSession if it still declares "isOpen()==true". It requires either manually do "stop()" and "start()" on WebSocketConnectionManager or refreshing the spring context (if in spring and "autoStartup=true").

In my project I have fixed it by introducing 2 new classes (a new ReconnectingWebSocketConnectionManager with a new decorating ReconnectingWebSocketHandler - see (EDIT: simplified) snippets below).

I was wondering if there is any easier solution?

public class ReconnectingWebSocketConnectionManager extends WebSocketConnectionManager {

    public ReconnectingWebSocketConnectionManager(WebSocketClient client, WebSocketHandler webSocketHandler,
            String uriTemplate, Object... uriVariables) {
        super(client, webSocketHandler, uriTemplate, uriVariables);
    }

    @Override
    protected WebSocketHandler decorateWebSocketHandler(WebSocketHandler handler) {
        return new ReconnectingWebSocketHandler(super.decorateWebSocketHandler(handler), this);
    }
}

public class ReconnectingWebSocketHandler extends WebSocketHandlerDecorator {

    private static final Log logger = LogFactory.getLog(ReconnectingWebSocketHandler.class);

    private ConnectionManagerSupport connectionManager;

    public ReconnectingWebSocketHandler(WebSocketHandler delegate, ConnectionManagerSupport connectionManager) {
        super(delegate);
        this.connectionManager = connectionManager;
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        if (session != null && !session.isOpen()) {
            logger.debug("Reconnecting...");
            this.connectionManager.stop();
            this.connectionManager.start();
            logger.debug("Reconnected...");
        }
    }

}

Comment From: npriebe

Is there any new information on this subject?

Comment From: dwirtz

Hopefully I am joining the correct issue without mixing things up. I also ran into the problem of a missing reconnection mechanism within the websocket connection management in general. Within my company we're using spring-integration-websocket and I first thought that a reconnection should be part in that library. Therefore I opened an issue https://github.com/spring-projects/spring-integration/issues/8835 there, where - from my point of view - is a short but good discussion about where to do reconnection. We compared it to the spring-amqp handling where reconnection management is available and not delegated to the one who is using the library.

Is there any chance to provide a reconnection management within spring-websocket? Unfortunatley I could not find any documentation within ConnectionManagerSupport how to handle connection failures. My expectation in short: The library does reconnection management by itself (at least for the "problems" or usual situations of network failures).

Comment From: rstoyanchev

The main goal of WebSocketConnectionManager is to start and stop the underlying client when the ApplicationContext starts and stops, and to establish the WebSocket connection on start. It does not check indeed if the connection is lost in between.

I think it could be done along these lines:

public class ReconnectingWebSocketConnectionManager extends WebSocketConnectionManager {

    public ReconnectingWebSocketConnectionManager(
            WebSocketClient client, WebSocketHandler handler, String uri, Object... uriVars) {

        super(client, handler, uri, uriVars);
    }

    @Override
    protected WebSocketHandler decorateWebSocketHandler(WebSocketHandler handler) {
        return new CloseNotifyingHandler(super.decorateWebSocketHandler(handler), this::openConnection);
    }


    private static class CloseNotifyingHandler extends WebSocketHandlerDecorator {

        private final Runnable closeTask;

        public CloseNotifyingHandler(WebSocketHandler delegate, Runnable closeTask) {
            super(delegate);
            this.closeTask = closeTask;
        }

        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
            super.afterConnectionClosed(session, closeStatus);
            this.closeTask.run();
        }
    }

}

We could add something to make it more friendly. For example we can detect when the session is closed and allow a subclass to reopen from a protected method. However, it will have to be up to the subclass to decide what to do if the connect/reconnect does not succeed. How many times to keep trying, at what intervals, etc.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.