Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Path Parameters in WebSocketConfigurer addHandler in Spring

  • I am using "TextWebSocketHandler" for websockets and "WebSocketConfigurer" to configure the websocket.
  • I have a scenario where different instances of the handler needs to be gererated.

For example: if I am doing auction for some items, then I need to generate seperate WebSocketHandler instances for each auctionId. Could we attach "auctionId" as path parameter to the url so that different instance gets generated for different auction?

Or Is there any other way to achieve this?

This is how I am adding the handler:

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(websocketTestHandler(), "/websocket-test");
}
like image 878
androlinux Avatar asked Dec 02 '22 10:12

androlinux


1 Answers

If you want to use a TextWebSocketHandler, you could pass the auction id as part of the URL path. You'll have to copy the path to the WebSocket session during handshake (this is the only place where you'll get access to the ServerHttpRequest as the handshake is an http request) and then retrieve the attribute from your handler.

Here's the implementation:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(auctionHandler(), "/auction/*")
                .addInterceptors(auctionInterceptor());
    }

    @Bean
    public HandshakeInterceptor auctionInterceptor() {
        return new HandshakeInterceptor() {
            public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                  WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {

                // Get the URI segment corresponding to the auction id during handshake
                String path = request.getURI().getPath();
                String auctionId = path.substring(path.lastIndexOf('/') + 1);

                // This will be added to the websocket session
                attributes.put("auctionId", auctionId);
                return true;
            }

            public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, 
                    WebSocketHandler wsHandler, Exception exception) {
                // Nothing to do after handshake
            }
        };
    }

    @Bean
    public WebSocketHandler auctionHandler() {
        return new TextWebSocketHandler() {
            public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
                // Retrieve the auction id from the websocket session (copied during the handshake)
                String auctionId = (String) session.getAttributes().get("auctionId");

                // Your business logic...
            }
        };
    }
 }

Client:

new WebSocket('ws://localhost:8080/auction/1');

Even if this is a working solution, I would recommend you taking a look at STOMP over WebSockets, it will give you more flexibility.

like image 110
Sergi Almar Avatar answered Feb 07 '23 09:02

Sergi Almar