spring-bootstompspring-websocketspring-scheduled

How can I get STOMP Connected Sessions List?


This is my WebSocketConfiguration Code

@EnableWebSocketMessageBroker
@Configuration
@RequiredArgsConstructor
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/my-chat").setAllowedOriginPatterns("*");
    }
    
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/pub");
        registry.enableSimpleBroker("/sub");
    }

}

And I connect STOMP Connection . Url is "ws://localhost:8080/my-chat", Connection-Type : STOMP, Subscription URL: "sub/hello".

I already checked connection in Spring Output terminal.

 [MessageBroker-8] o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[2 current WS(2)-HttpStream(0)-HttpPoll(0), 3 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(1)-CONNECTED(1)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 9, active threads = 0, queued tasks = 0, completed tasks = 9], outboundChannel[pool size = 2, active threads = 0, queued tasks = 0, completed tasks = 2], sockJsScheduler[pool size = 8, active threads = 1, queued tasks = 1, completed tasks = 60]

But , when I can't get connected session numbers in Spring code. This is my code.

@Autowired
private SimpUserRegistry simpUserRegistry;

@Scheduled(fixedRate = 1000)
public void getConnectedUserSessions() {
    System.out.println(simpUserRegistry.getUserCount());
}

It always print 0. How can I get connected stomp session?

I try stomp connection with apic chrome extensions. stomp connected But I can't get connect session user in spring code.


Solution

  • As described here, only authenticated users are added to the registry.

    My workaround is to implement ChannelInterceptor and count it manually:

    @Component
    public class WebSocketMetricLogger implements ChannelInterceptor {
        private final Set<String> connectedSessionIds;
    
        public WebSocketMetricLogger() {
            this.connectedSessionIds = Collections.synchronizedSet(new HashSet<>());
        }
    
        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            var accessor = StompHeaderAccessor.wrap(message);
            var command = accessor.getCommand();
            var sessionId = accessor.getSessionId();
    
            if (command == null || sessionId == null) {
                return message;
            }
    
            if (command == StompCommand.CONNECT) {
                connectedSessionIds.add(sessionId);
            } else if (command == StompCommand.DISCONNECT) {
                connectedSessionIds.remove(sessionId);
            }
    
            return message;
        }
    }
    
    @Configuration
    @EnableWebSocketMessageBroker
    public class DefaultWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
        private final WebSocketMetricLogger webSocketMetricLogger;
    
        @Autowired
        public DefaultWebSocketMessageBrokerConfigurer(WebSocketMetricLogger webSocketMetricLogger) {
            this.webSocketMetricLogger = webSocketMetricLogger;
        }
    
        ...
    
        @Override
        public void configureClientInboundChannel(ChannelRegistration registration) {
            registration.interceptors(webSocketMetricLogger);
        }
    }
    

    Note that to avoid duplicate DISCONNECT events, record session IDs instead of session count.