how to capture connection event in my webSocket server with Spring 4?
Asked Answered
M

5

7

I did a simple web socket communication with spring 4,STOMP and sock.js, following this https://github.com/rstoyanchev/spring-websocket-portfolio and this http://assets.spring.io/wp/WebSocketBlogPost.html

well, I want to know if is possible capture connection events like when a new client was connected to my server or when a client was disconnected, is that possible in Spring 4.0.0?

Marable answered 14/2, 2014 at 14:13 Comment(0)
H
7

This an be done with a connection handshake interceptor (HttpSessionHandshakeInterceptor), quoting the documentation:

The easiest way to customize the initial HTTP WebSocket handshake request is through a HandshakeInterceptor, which exposes "before" and "after" the handshake methods.

Hall answered 14/2, 2014 at 17:59 Comment(1)
thanks!! well actually I use, a WebSocketMessageBrokerConfigurer, but using this it works: registry.addEndpoint("/api/v1/ws/pushService").withSockJS().setInterceptors(wsSessionInterceptor);Marable
I
31

Spring WebSocket publishes events when messages are received from the client, if you are using STOMP, these are the events published:

The easiest way to detect connects and disconnects is by implementing an event listener for the mentioned events.

@Component
public class WebSocketEventListener {

    @EventListener
    private void handleSessionConnected(SessionConnectEvent event) {
        ...
    }

    @EventListener
    private void handleSessionDisconnect(SessionDisconnectEvent event) {
        ...
    }
}

Here's a sample implementation that keeps track of connected users: https://github.com/salmar/spring-websocket-chat/blob/master/src/main/java/com/sergialmar/wschat/event/PresenceEventListener.java

Incumbent answered 10/4, 2018 at 13:12 Comment(1)
Where do you store sessionId?Congruence
H
7

This an be done with a connection handshake interceptor (HttpSessionHandshakeInterceptor), quoting the documentation:

The easiest way to customize the initial HTTP WebSocket handshake request is through a HandshakeInterceptor, which exposes "before" and "after" the handshake methods.

Hall answered 14/2, 2014 at 17:59 Comment(1)
thanks!! well actually I use, a WebSocketMessageBrokerConfigurer, but using this it works: registry.addEndpoint("/api/v1/ws/pushService").withSockJS().setInterceptors(wsSessionInterceptor);Marable
O
6

As I understand, the question with DISCONNECT event is not solved in this topic. Handshake interception gives you only connect info but not disconnect.

I have achieved this with the interceptors of inbound channel:

<websocket:message-broker>
    ...
    <websocket:client-inbound-channel>
        <websocket:interceptors>
            <bean class="com......MyChannelInterception"></bean>
        </websocket:interceptors>
    </websocket:client-inbound-channel>
</websocket:message-broker>

...and class...

import java.security.Principal;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.support.ChannelInterceptorAdapter;

public class MyChannelInterception extends ChannelInterceptorAdapter {

private static final Logger LOGGER = LogManager.getLogger(WrcChannelInterception.class);

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {

    MessageHeaders headers = message.getHeaders();
    SimpMessageType type = (SimpMessageType) headers.get("simpMessageType");
    String simpSessionId = (String) headers.get("simpSessionId");

    if (type == SimpMessageType.CONNECT) {
        Principal principal = (Principal) headers.get("simpUser");
        LOGGER.debug("WsSession " + simpSessionId + " is connected for user " + principal.getName());
    } else if (type == SimpMessageType.DISCONNECT) {
        LOGGER.debug("WsSession " + simpSessionId + " is disconnected");
    }
    return message;
}
}

Please note that Principal is available on CONNECT but not on DISCONNECT, however you have sweet Session ID

Orthorhombic answered 16/6, 2014 at 9:41 Comment(3)
how could I get the Principal by sessionID?Askins
@Askins on Connect, you can store in your DB the link between sessionId and Principal and on Disconnect, to retrieve the Principal by Session IDOrthorhombic
How do we identify which client along with endpoint client is disconnected ?Matthieu
H
1

Although original question is about Spring 4 - which is well answered by Sergi. Here is a way to do it in Spring 5 or Spring Boot 2 (which uses Spring 5 under the hood). ApplicationListener needs to be implemented:

@Component
public class WebSocketEventListener implements ApplicationListener<SessionConnectEvent> {
    Logger logger = LoggerFactory.getLogger(WebSocketEventListener.class);

    @Override
    public void onApplicationEvent(SessionConnectEvent event) {
        logger.error("SessionConnectEvent = " + event);
    }
}
Hagar answered 25/9, 2021 at 9:34 Comment(0)
L
0

This code snippet may help you:

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    logger.info("afterConnectionEstablished called");
}
Loring answered 24/3, 2023 at 19:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.