Search code examples
javaspringwebsocketspring-websocketstomp

Spring STOMP WebSocket session disconnect handler / reconnection handling


In my application I'm using STOMP over WebSocket for communication between microservices, I'm trying to implement session disconnect event listener to reestablish connection between microservices. According to Spring's documentation SessionDisconnectEvent should be published when a STOMP session ends. That's how I've tried to catch the event:

@Component
public class SessionDisconnectListener implements ApplicationListener<SessionDisconnectEvent> {
    @EventListener
    @Override
    public void onApplicationEvent(SessionDisconnectEvent  applicationEvent) {
        System.out.println("SESSION " + applicationEvent.getSessionId() + " DISCONNECTED");
    }
}

I can see in my application that the session status changes from connected to disconnected but unfortunately this method is newer invoked. How can I properly catch session disconnect event?


Solution

  • You can implement a disconnect handler in your StompSessionHandlerAdapter. In the adapter you need to implement handleTransportError(session, exception), all connection failure events will go through this method and you should implement your disconnect handler there. You can determine whether connection has been lost based on the passed exception or by checking the connection status of your session, I personally prefer latter.

    AtomicBoolean reconnecting = new AtomicBoolean();
    
    @public void handleTransportError(StompSession session, Throwable exception) {
        If (!session.isConnected()) {
            If (reconnecting.compareAndSet(false, true)) {  //Ensures that only one thread tries to reconnect
                try {
                    reestablishConnection();
                } finally {
                    reconnecting.set(false);
                }
            }
        } else {} //Log exception here
    } 
    private void reestablishConnection() {
        boolean disconnected = true;
        while (disconnected) {
            try {
                TimeUnit.SECONDS.sleep(sleepTime); //Specify here for how long do you want to wait between each reconnect attempt
            } catch (Exception e) {}  //If an exception happens here then the service is most likely being shut down
            try {
                stompClient.connect(url, this).get();
                disconnected = false;
            } catch (Exception e) {} //Add logging etc. here    
        }
    }