Search code examples
javaspring-bootwebsocketspring-websocket

Detecting connection error and reconnection on Spring WebSocketClient


I am using Spring Framework's WebSocketClient and WebSocketStompClient to consume messages. The setup looks something like this:

    WebSocketClient webSocketClient = new StandardWebSocketClient();
    WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);

    //messageConverter is MappingJackson2MessageConverter
    stompClient.setMessageConverter(messageConverter);
    stompClient.setTaskScheduler(new ConcurrentTaskScheduler());

    WebSocketHttpHeaders httpHeaders = new WebSocketHttpHeaders();
    StompHeaders stompHeaders = new StompHeaders();
    //... populate authentication headers ... 

    stompClient.connect(url, httpHeaders, stompHeaders, this);

The class itself implements StompSessionHandlerAdapter.

I am then overriding the afterConnected() method to subscribe to the required destinations and all works well.

I am also overriding handleException(), and I was expecting that maybe when there is a connection error this would be triggered. I have a warning log inside, so I was expecting this to show something when a connection error occurs.

  @Override
  public void handleException(
      StompSession session,
      StompCommand command,
      StompHeaders headers,
      byte[] payload,
      Throwable exception) {
    logger.warn("Error on websocket session " + session.getSessionId(), exception);
  }

However, when there is a connection drop I see no error. The websocket server is accessible only through the private network, so the way I am trying to simulate it is by disconnecting VPN, at which point messages just stop (no Exception is logged through handleException()). Reconnecting VPN does not resume automatically either.

How can I detect that the websocket server is unavailable and try to reconnect periodically?


Solution

  • So it turns out there is another method, handleTransportError() which gets invoked when the socket connection drops. When I override it and the websocket server becomes unavailable it is correctly getting invoked.

      @Override
      public void handleTransportError(StompSession session, Throwable exception) {
        logger.warn("Error on websocket session " + session.getSessionId(), exception);
    
        // todo: schedule a reconnection attempt
      }
    

    What I ended up doing is keeping a flag to know whether the client was connected or not. If this was the first disconnection it tries to re-establish the connection, otherwise it uses Spring's ThreadPoolTaskScheduler to schedule a reconnection attempt after 5 seconds.