How to get sockJS sessionId in Spring’s WebSocketStompClient?

Brief. You want to compose a simple client which receives messages from the server side with STOMP over websockets. Most probably you will face the issue: the default sessionId retrieved from the Session doesn’t match the one assigned by sock.js. We need to go deeper.



We are going to use Reflection to access private fields and private classes.

 
import org.springframework.messaging.simp.stomp.*;
import org.springframework.messaging.tcp.TcpConnection;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.socket.sockjs.client.WebSocketClientSockJsSession;
<br>import java.lang.reflect.Field;import java.lang.reflect.Type;
import java.util.HashMap;
public class MyStompSessionHandler extends StompSessionHandlerAdapter {
    private Logger logger = LoggerFactory.getLogger(MyStompSessionHandler.class);
    @Override
    public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
        // we need another sessionId!
        System.out.println("New session established : " + session.getSessionId());
        DefaultStompSession defaultStompSession =
                (DefaultStompSession) session;
        Field fieldConnection = ReflectionUtils.findField(DefaultStompSession.class, "connection");
        fieldConnection.setAccessible(true);
        String sockjsSessionId = "";
        try {
            TcpConnection<byte[]>; connection = (TcpConnection<byte[]>;) fieldConnection.get(defaultStompSession);
            try {
                Class adapter = Class.forName("org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter");
                Field fieldSession = ReflectionUtils.findField(adapter, "session");
                fieldSession.setAccessible(true);
                WebSocketClientSockJsSession sockjsSession = (WebSocketClientSockJsSession) fieldSession.get(connection);
                sockjsSessionId = sockjsSession.getId();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (StringUtils.isBlank(sockjsSessionId)) {
            throw new IllegalStateException("couldn't extract sock.js session id");
        }
        String subscribeLink = "/topic/auth-user" + sockjsSessionId;
        session.subscribe(subscribeLink, this);
        System.out.println("Subscribed to " + subscribeLink);
        String sendLink = "/app/user";
        session.send(sendLink, getSampleMessage());
        System.out.println("Message sent to websocket server");
 
    } //... other overriden methods aren't so interesting 
}

An instance of MyStompSessionHandler is supposed to be passed into connect method:

stompClient.connect(URL, new MyStompSessionHandler());
You can leave a response, or trackback from your own site.

Leave a Reply