-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
We used WebSockets within Spring Boot 2.3.5 using a simple message broker. After the update to Spring Boot 2.4 / Spring Framework 5.3, we noticed that our web socket mechanism is not working anymore. We use the following web socket config:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket");
registry.addEndpoint("/websocket").setAllowedOrigins("http://localhost:8080").withSockJS();
}
@Bean(name = "websocketLocaleResolver")
public SessionLocaleResolver websocketLocaleResolver() {
SessionLocaleResolver websocketLocaleResolver = new SessionLocaleResolver();
websocketLocaleResolver.setDefaultLocale(Locale.GERMANY);
return websocketLocaleResolver;
}
}A look at the DefaultSubscriptionRegistry shows that there changed a lot comparing to Spring Boot 2.3.5. We could nail down the issue because we saw that even though our web socket subscription was successful within the DefaultSubscriptionRegistry, the method this.subscriptionRegistry.findSubscriptions(message) within the SimpleBrokerMessageHandler always returns an empty map (in contrast to Spring Boot 2.3).
protected void sendMessageToSubscribers(@Nullable String destination, Message<?> message) {
MultiValueMap<String,String> subscriptions = this.subscriptionRegistry.findSubscriptions(message);
...When rolling back to Spring 2.3.5, the same web socket business logic works fine with the old implementations of DefaultSubscriptionRegistry and SimpleBrokerMessageHandler.
We also noticed that with Spring Boot 2.3.5 the DestinationCache returns a map including a SessionId and SubscriptionId (expected behavior). Using Spring Boot 2.4.0, the returned LinkedMultiValueMap sessionIdToSubscriptionIds is always empty.
public LinkedMultiValueMap<String, String> getSubscriptions(String destination) {
LinkedMultiValueMap<String, String> sessionIdToSubscriptionIds = this.destinationCache.get(destination);
if (sessionIdToSubscriptionIds == null) {
sessionIdToSubscriptionIds = this.destinationCache.computeIfAbsent(destination, _destination -> {
LinkedMultiValueMap<String, String> matches = computeMatchingSubscriptions(destination);
// Update queue first, so that cacheSize <= queue.size(
this.cacheEvictionPolicy.add(destination);
this.cacheSize.incrementAndGet();
return matches;
});
ensureCacheLimit();
}
return sessionIdToSubscriptionIds;
}