I aim to use SimpUserRegistry to check how many users are subscribed to a topic to limit the number of subscriptions. To test my code I used the basic https://spring.io/guides/gs/messaging-stomp-websocket/ project.
Here are my only changes to this project:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
private TopicSubscriptionInterceptor topicSubscriptionInterceptor
...
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(topicSubscriptionInterceptor);
}
}
//--------------------------------------------------------------------------------------
@Component
public class TopicSubscriptionInterceptor implements ChannelInterceptor {
@Autowired
private SimpUserRegistry userRegistry;
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel){
// ... use SimpUserRegistry to check amount of users subscribed to a topic and whether
// or not to allow a subscription (throw exception/null)
}
//-----------------------------------------------------------------------------------------
I've tried to just pass a new TopicSubscriptionInterceptor()
instead of adding it as a dependency using @Autowired but that obviously made all dependencies in TopicSubscriptionInterceptor null.
//---------------------------------------------------
Dependency Cycle:
┌─────┐
| webSocketConfig (field private com.xxx.yyy.interceptor.TopicSubscriptionInterceptor com.xxx.yyy.config.WebSocketConfig.topicSubscriptionInterceptor)
↑ ↓
| topicSubscriptionInterceptor (field private org.springframework.messaging.simp.user.SimpUserRegistry com.xxx.yyy.interceptor.TopicSubscriptionInterceptor.userRegistry)
↑ ↓
| org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration
└─────┘
Here's what I tried Edit(1):
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Bean
public TopicSubscriptionInterceptor
myTopicSubscriptionInterceptor(){
return new TopicSubscriptionInterceptor();
}
...
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(myTopicSubscriptionInterceptor());
}
}
Using Lazy Initialization fixed the issue although it feels like a bandaid solution. I'm not sure if there is another better way since I'm new to Spring.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
private TopicSubscriptionInterceptor topicSubscriptionInterceptor;
@Autowired
public WebSocketConfig(@Lazy TopicSubscriptionInterceptor topicSubscriptionInterceptor) {
this.topicSubscriptionInterceptor = topicSubscriptionInterceptor;
}
...
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(topicSubscriptionInterceptor);
}
}