14

I did a simple web socket communication with spring 4, STOMP and sock.js, following this https://spring.io/guides/gs/messaging-stomp-websocket/

Now I want to upgrade it to simple chat. My problem is that when user subscribes to new chat room, he should get past messages. I don't know how to capture the moment when he subscribed to send him the list of the messages.

I tried using @MessageMapping annotation, but didn't reach any success:

@Controller
public class WebSocketController {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;


    @MessageMapping("/chat/{chatId}")
    public void chat(ChatMessage message, @DestinationVariable String chatId) {
        messagingTemplate.convertAndSend("/chat/" + chatId, new ChatMessage("message: " + message.getText()));
    }

    @SubscribeMapping("/chat")
    public void chatInit() {
        System.out.println("worked");
        int chatId = 1; //for example
        messagingTemplate.convertAndSend("/chat/" + chatId, new ChatMessage("connected"));
    }

}

Then I created that:

@Controller
public class ApplicationEventObserverController implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        System.out.println(applicationEvent);
    }
}

It works, but captures all possible events, I don't think it is a good practice.

So, my question can be rephrased: how to send initial data when user subscried to sth?

sinedsem
  • 5,413
  • 7
  • 29
  • 46
  • I found the similiar question here: http://stackoverflow.com/questions/24795340/how-to-find-all-users-subscribed-to-a-topic-in-spring-websockets – sinedsem Jan 07 '15 at 15:19
  • Seems like a similar problem to [this one](https://stackoverflow.com/questions/54330744/spring-boot-websocket-how-to-get-notified-on-client-subscriptions/55224040#55224040). Check out my answer there to see if it's of any use to you. – croc Mar 18 '19 at 14:58

1 Answers1

13

You can return anything directly to a client when it subscribes to a destination using a @SubscribeMapping handler method. The returned object won't go to the broker but will be sent directly to the client:

@SubscribeMapping("/chat")
public Collection<ChatMessage> chatInit() {
    ...
    return messages;
}

On the client side:

socket.subscribe("/app/chat", function(message) {
    ...
});

Check out the chat example on GitHub, which shows this exact scenario.

Sergi Almar
  • 8,054
  • 3
  • 32
  • 30
  • 2
    Still could not reach sth that I want. @Sergi Almar , Can I subscibe only one time and use this subscription both to obtain init messeges and the future messages? – sinedsem Jan 08 '15 at 23:54
  • @SubscribeMapping only works when I write stompClient.subscribe("/app/chat/"), but in this case I can't receive new messages – sinedsem Jan 09 '15 at 00:06
  • @SubscribeMapping is intended for request-reply scenario, so it can't capture topic subscription event. – hello.wjx Sep 15 '18 at 11:34