spring-mvcspring-websocketsockjsstompjs

How to detect that client has disconnected using websocket in spring mvc


I want to be able to detect when the user has lost connection with the server (closed tab, lost internet connection, etc.) I am using stompjs over Sockjs on my client and spring mvc websockets on my server.

How can i detect when the client has lost connection. Here is how i configure my websocket message brocket:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
    @Autowired
    private TaskScheduler scheduler;

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic").setHeartbeatValue(new long[]{10000, 10000}).setTaskScheduler(scheduler);
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/web").setAllowedOrigins("*").withSockJS();
    }
}

And here is my controller class that actualy handles the incoming socket messages:

@RestController
@CrossOrigin
public class WebMessagingController {

    @MessageMapping("/chat/message")
    public void newUserMessage(String json) throws IOException {
        messagesProcessor.processUserMessage(json);
    }
}

I know that if i would have used class that extends from TextWebSocketHandler i would have bean able to override methods that are being called on connection and disconnection of the client, but i don`t think this is going to work with sock-js client. Thank you.


Solution

  • The StompSubProtocolHandler implements afterSessionEnded() which is called from the WebSocketHandler.afterConnectionClosed(). And the former emits an event like this:

    /**
     * Event raised when the session of a WebSocket client using a Simple Messaging
     * Protocol (e.g. STOMP) as the WebSocket sub-protocol is closed.
     *
     * <p>Note that this event may be raised more than once for a single session and
     * therefore event consumers should be idempotent and ignore a duplicate event.
     *
     * @author Rossen Stoyanchev
     * @since 4.0.3
     */
    @SuppressWarnings("serial")
    public class SessionDisconnectEvent extends AbstractSubProtocolEvent {
    

    So, what you need is an ApplicationListener for this SessionDisconnectEvent and all the information is there in the event.