2

I am using Spring 4 + Websockets + Stomp JS library. I could not find any way to setup websocket ping/pong mechanism (heartbeat).

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" ...">

<websocket:message-broker>
    <websocket:stomp-endpoint path="/cors/auth/clientEndpoint">
        <websocket:handshake-handler ref="myHandshakeHandler" />
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/queue, /topic" />
    <websocket:client-inbound-channel>
        <websocket:interceptors>
            <bean class="com.mycompany.myproject.utils.messaging.MyInboundChannelInterception"></bean>
        </websocket:interceptors>
    </websocket:client-inbound-channel>
</websocket:message-broker>

<bean id="myHandshakeHandler" class="com.mycompany.myproject.utils.security.MyHandshakeHandler" />

<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
    <property name="maxSessionIdleTimeout" value="120000" />
</bean>

As result, I am implementing my own mechanism of ping/pong messages.

One of the tasks here - to implement server side closure of the websocket in case if no ping message during more than 10s from client.

And no way to do this using Spring Websockets!

Maybe somebody can tell me how to access Session object of the user or to close those Session via Spring Websockets?

Seems Spring is very limited here.

walv
  • 2,680
  • 3
  • 31
  • 36

3 Answers3

5

I'm surprised spring doc doesn't mention how to config server ping...It seems that spring expects us to read code instead of read doc..

after some time searching on net and reading source code, I realize it's already supported, but not documented at a noticeable place like spring websocket doc.

I'm using spring 4.3.3, and here is how to config server ping without using sockJS:

@Configuration
@EnableWebSocketMessageBroker
public class StompOverWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

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

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/app");
        ThreadPoolTaskScheduler pingScheduler = new ThreadPoolTaskScheduler();
        pingScheduler.initialize();
        registry.enableSimpleBroker("/topic")
            .setHeartbeatValue(new long[]{20000, 0}).setTaskScheduler(pingScheduler);
    }
....
}

and should make sure that you correctly set web socket session timeout, it should be greater than ping interval, like this:

<bean id="servletServerContainerFactoryBean" class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
    <property name="maxSessionIdleTimeout" value="30000"/>
</bean>
Smittey
  • 2,475
  • 10
  • 28
  • 35
bulletProofCat
  • 915
  • 8
  • 8
4

In this case, configuring SockJS in your app could go a long way:

<websocket:stomp-endpoint path="/cors/auth/clientEndpoint">
  <websocket:handshake-handler ref="myHandshakeHandler" />
  <websocket:sockjs/>
</websocket:stomp-endpoint>

This will give you:

If you want to actually close a session from STOMP endpoints, then I suggest you to vote/follow the SPR-12288 JIRA issue.

Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
  • Brian, thank you for response. Is it not possible to achieve heartbeat management without sockJs? My application is designed for modern browsers which definitely support websockets. As result, sockJs is useless in my case because I don't need websocket emulation/fallback. – walv Oct 02 '14 at 14:40
  • 1
    You could manually set this up and check how it's done in the framework (we're using TaskSchedulers to send heartbeats periodically). SockJS won't slow you down here, it'll select the best transport available (websocket) if possible. Don't forget that even if you clients support websockets, the network (HTTP proxies and others) may not be happy with persistent connections like websockets. – Brian Clozel Oct 02 '14 at 18:49
  • Ok, got it. Thanks! Not sure about this statement: " Don't forget that even if you clients support websockets, the network (HTTP proxies and others) may not be happy with persistent connections like websockets.". Any official proof for that? Why is it heavy? – walv Oct 03 '14 at 10:18
  • See Spring documentation: http://docs.spring.io/spring-framework/docs/4.1.1.RELEASE/spring-framework-reference/html/websocket.html#websocket-into-fallback-options - basically with SockJS, if websocket works it's just plain websocket; so you don't really lose anything, it's not heavier or less performant anyway. – Brian Clozel Oct 03 '14 at 12:24
  • @BrianClozel https://jira.spring.io/browse/SPR-12288 said the Spring has supported close websocket from the server side. But I can't find the document. Can you help me? – Haozhe Xie May 22 '15 at 03:12
  • @BrianClozel how to send heartbeat using TaskScheduler? can you give an example? please – zhaozhi Jan 26 '16 at 07:56
0

To access websocket session you can use the following approach: https://stackoverflow.com/a/32270216/2982835

Community
  • 1
  • 1
isaranchuk
  • 362
  • 3
  • 13