Spring STOMP over WebSockets not scheduling heartbeats

jordan.baucke picture jordan.baucke · Aug 30, 2016 · Viewed 10.1k times · Source

We have a Spring over WebSockets connection that we're passing a CONNECT frame:

CONNECT\naccept-version:1.2\nheart-beat:10000,10000\n\n\u0000

Which the handler acknowledges, starts a new session, and than returns:

CONNECTED
version:1.2
heart-beat:0,0

However, we want the heart-beats so we can keep the WebSocket open. We're not using SockJS.

I stepped through the Spring Message Handler:

StompHeaderAccessor [headers={simpMessageType=CONNECT, stompCommand=CONNECT, nativeHeaders={accept-version=[1.2], heart-beat=[5000,0]}, simpSessionAttributes={}, simpHeartbeat=[J@5eba717, simpSessionId=46e855c9}]

After it gets the heart-beat (native header), it sets what looks like a memory address simpHeartbeat=[J@5eba717, simpSessionId=46e855c9}]

Of note, after the broker authenticates:

Processing CONNECT session=46e855c9 (the sessionId here is different than simpSessionId)?

When running earlier TRACE debugging I saw a notice "Scheduling heartbeat..." or something to that effect...though I'm not seeing it now?

Any idea what's going on?

Thanks

I have found the explanation in the documentation:

SockJS Task Scheduler stats from thread pool of the SockJS task scheduler which is used to send heartbeats. Note that when heartbeats are negotiated on the STOMP level the SockJS heartbeats are disabled.

Are SockJS heartbeats different than STOMP heart-beats?

Answer

artemisian picture artemisian · Feb 17, 2017

Starting Spring 4.2 you can have full control, from the server side, of the heartbeat negotiation outcome using Stomp over SockJS with the built-in SimpleBroker:

public class WebSocketConfigurer extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
        te.setPoolSize(1);
        te.setThreadNamePrefix("wss-heartbeat-thread-");
        te.initialize();

        config.enableSimpleBroker("/")
                /**
                 * Configure the value for the heartbeat settings. The first number
                 * represents how often the server will write or send a heartbeat.
                 * The second is how often the client should write. 0 means no heartbeats.
                 * <p>By default this is set to "0, 0" unless the {@link #setTaskScheduler
                 * taskScheduler} in which case the default becomes "10000,10000"
                 * (in milliseconds).
                 * @since 4.2
                 */
                .setHeartbeatValue(new long[]{heartbeatServer, heartbeatClient})
                .setTaskScheduler(te);
    }

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