Skip to content

Broken WebSocket subscription using simple message broker  #26118

Closed
@BenS89

Description

@BenS89

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;
		}

Metadata

Metadata

Assignees

Labels

in: messagingIssues in messaging modules (jms, messaging)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions