Search code examples
spring-bootwebsocketspring-websocketstomp

@SubscribeMapping vs @MessageMapping


When using websockets with Spring Boot I've seen examples that use:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

     @Override
     public void configureMessageBroker(MessageBrokerRegistry config) {
      config.enableSimpleBroker("/topic/");
      config.setApplicationDestinationPrefixes("/app");
     }

     @Override
     public void registerStompEndpoints(StompEndpointRegistry registry) {
      registry.addEndpoint("/greeting");;
     }  
} 

Specifying the config.setApplicationDestinationPrefixes("/app") and in the controller using the @MessageMapping annotation.

And I've also seen examples that use only the enableSimpleBroker() and in the controller use @SubscribeMapping.

For what I understood the @MessageMapping is responsible to route the received message to the correct method. And methods with this annotation will only be triggered if the destination contains one of the prefixes declared in setApplicationDestinationPrefixes.

But @SubscribeMapping also route the message to the correct method and we don't need to call setApplicationDestinationPrefixes() in the config class.

What's the difference?


Solution

  • Short answer

    @MessageMapping-annotated methods will react only to the SEND messages with the destination having prefix /app and matching the topic set in the annotation.

    @SubscribeMapping-annotated methods will react only to the SUBSCRIBE messages with the destination matching the topic set in the annotation.

    Longer answer

    There are several types of STOMP commands that a client may send, among them are SUBSCRIBE and SEND.

    A method annotated with @SubscribeMapping("/topic/topic1") will receive only SUBSCRIBE messages with the destination "/topic/topic1". I.e. when client subscribes to the topic "/topic/topic1", this method will be called.

    When, on the contrary, the client sends SEND message to the "/topic/topic1" destination, this method won't be called.

    A method annotated with @MessageMapping("/topic2") will be called for SEND messages sent to the "/app/topic2" destination and, by default, will send the result to the destination "/topic/topic2".

    The logic is that client first CONNECTs, then SUBSCRIBEs to some topics and receives messages sent to these topics by the server (or other clients). It may also SEND some messages to some topics. Then it may UNSUBSCRIBE and DISCONNECT. The process of message exchange is managed by message broker which can be a simple in-memory object or some advanced product, like ActiveMQ or RabbitMQ etc.