Spring Boot Session + STOMP + Websocket + Javaconfig

By Dhiraj Ray, 21 December,2016   2232

In this post, we will be discussing about how to maintain spring session during websocket connection through HandshakeInterceptor.Doing so we can track user session during every websocket request and can utilize this session to track client activities from the server even after the server is connected through websocket protocol.Now let us look into the code how can we maintain spring session during websocket connection using Spring boot.

Background

As we know, before making a websocket connection to a server, client makes a handshake request as an upgrade request and this request is a HTTP request.Hence, to maintain a websocket session, we require to intercept this HTTP request and keep the session id somewhere from where it can be accessed everytime whenever a websocket request is made.Here we will be using STOMP header attributes to track the session.

Environment Setup

1. JDK 8 2. Spring Boot 3. Intellij Idea/ eclipse 4. Maven

Maven Dependencies

There is no any extra maven dependency is required for this case that we used in our previous post of Spring Websocket Integration Example without STOMP.Hence let us ignore it for time being.

Server Side

First of all let us configure our message broker.In WebSocketConfig.java we have defined our STOMP endpoint and message broker. The important thing to notice here is the configuration for handshakeInterceptor.So, whenever any websocket handshake request is received by the server,this class will come into picture.

WebSocketConfig.java
package com.developertack; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic/", "/queue/"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/greeting").addInterceptors(new HttpHandshakeInterceptor()); } }

Now let us define the httpInterceptor.We have overriden beforeHandshake() to intercept the handshake request and set our custom attributes.We are setting our custom attribute sessionId with actual sessionId and this is the same key which we will be using later to track the session from our controller class.

HttpHandshakeInterceptor.java
package com.developertack; import java.util.Map; import javax.servlet.http.HttpSession; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.HandshakeInterceptor; public class HttpHandshakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest.getServletRequest().getSession(); attributes.put("sessionId", session.getId()); } return true; } public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { } }

Following is the listener class which will be executed whenever a STOMP client subscribes for a queue or topic. We are also validating the sessionId which we created during handshake.

SubscribeEventListener.java
package com.developertack; import org.springframework.context.ApplicationListener; import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.stereotype.Component; import org.springframework.web.socket.messaging.SessionSubscribeEvent; @Component public class SubscribeEventListener implements ApplicationListener { @Override public void onApplicationEvent(SessionSubscribeEvent sessionSubscribeEvent) { StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionSubscribeEvent.getMessage()); System.out.println(headerAccessor.getSessionAttributes().get("sessionId").toString()); } }

Now let us define the controller which will intercept the message coming from the stomp client and validate the session using custom attribute sessionId which we set during handshake.This attribute can be accessed from the headerAccessor.

package com.developertack.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageSendingOperations; import org.springframework.stereotype.Controller; @Controller public class WebSocketController { @Autowired private SimpMessageSendingOperations messagingTemplate; @MessageMapping("/message") public void processMessageFromClient(@Payload String message, SimpMessageHeaderAccessor headerAccessor) throws Exception { String sessionId = headerAccessor.getSessionAttributes().get("sessionId").toString(); System.out.println(sessionId); headerAccessor.setSessionId(sessionId); messagingTemplate.convertAndSend("/topic/reply", new Gson().fromJson(message, Map.class).get("name")); } }

Run Application

1. Run Application.java as a java application.

2. Open the browser and hit the URL - http:localhost:8080.

3. Click on connect button to make the socket connection.

4. Enter your name and click send.Following is the result.

web-socket-example

On the server side you can check the console and find the sessionIds are same.

Conclusion

I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Download the source

References

Spring Websocket docs

HandshakeInterceptor

Suggest more topics in suggestion section or write your own article and share with your colleagues.

Is this page helpful to you? Please give us your feedback below. We would love to hear your thoughts on these articles, it will help us improve further our learning process.

Further Reading: