I am creating a websocket server that interfaces with a web service endpoint on one side and another which receives web socket connection requests from multiple clients. Here are two approaches that I found:
- Implement a web socket configurer and web socket handler as such:
Configurer
@Configuration
@EnableWebSocket
public class TestConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(testHandler(), "/testHandler")
.addInterceptors(new HttpSessionHandshakeInterceptor())
.withSockJS();
}
@Bean
public WebSocketHandler testHandler() {
return new TestHandler();
}
Handler
public class TestHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//Take request params and check if a current subscription to external webservice exists, if yes then directly add this session to a map cache repository with the subscription id as key
//If it is a new request then add session to a map cache repository and make new subscription to the external webservice
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
}
Configure a message broker endpoint to be subscribed to called /subscribe
public class TestWebSocketConfig implement WebSocketMessageBrokerConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> arg0) {} @Override public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> arg0) {} @Override public void configureClientInboundChannel(ChannelRegistration arg0) { System.out.println(""); } @Override public void configureClientOutboundChannel(ChannelRegistration arg0) { } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { } @Override public boolean configureMessageConverters(List<MessageConverter> arg0) { return true; } @Override public void configureWebSocketTransport(WebSocketTransportRegistration arg0) {} @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/subscribe").withSockJS(); }
Create controller where websocket clients can communicate with
@Controller
public class SubscriptionController {
@Autowired
private SimpMessagingTemplate template;
@MessageMapping("/subscribe1")
@SendTo("/subscribe")
public void addSubscription(String message) {
System.out.println("hi");
}
Here is my question, am I misunderstanding somewhere where these two methods I speak of meant to be combined together? I was using a tomcat implementation of websocket before which matches method 1 which gives me easy direct control over sessions as I would like to be able to reuse web service subscriptions to avoid duplicate request from distinct clients and also a single requests may map to more than one subscription requests to the external webservice. Yet it seems method 2 would push all data requests to the same "/subscribe" endpoint and all connected clients would be receiving the same data, which is not what I am trying to accomplish. It also seems like the message broker api is limited as it does not allow me access to the subscribed sessions where I can control which sessions the receiving data will be sent to. I realized I had to switch to spring websocket as I needed built in browser compatibility fallback offered by SockJS and automatic heartbeat function offered by Stomp.js.