Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Stomp @SubscribeMapping for User Destination

I am trying to get notified when an user subscribes to a stomp user destination using @SubscribeMapping annotation. My ideia is to send some initialization data to when it joins.

Although i am not being able to get this working:

Javascript:

stompClient.subscribe('/user/monitor', function(msg) {
            console.log(msg);    
        });

Java side:

@SubscribeMapping("/monitor-user{clientId}")
public void init(@DestinationVariable("clientId") String clientId) {
    messagingTemplate.convertAndSend("/user/" + clientId + "/monitor", getOps());
}

I tried many mapping combinations such as "/user/monitor-{clientId}", "/user/monitor" (Removing clientId), no success at all.

What is the expected mapping value so this get called?

Thank you!

like image 602
Luciano Greiner Avatar asked Dec 12 '22 04:12

Luciano Greiner


1 Answers

Since the client subscribes to the "/user/monitor" queue, the server @SubscribeMapping annotation must be to "/user/monitor" and not to "/user/monitor{something}".

The server can understand what client is depending on your authentication scheme. If you use a sockjs websocket you can use HTTP authentication, and hence leverage Spring Security, and add a "Principal" parameter to your function that will hold user information:

@SubscribeMapping("/monitor")
public void init(Principal p) {
    String user = p.getName();
    messagingTemplate.convertAndSendToUser(user, "/monitor", getOps());
}

If you don't use http authentication you may send the server the user info, for example adding a custom STOMP header that can be accessed from the server using a SimpMessageHeaderAccessor:

@SubscribeMapping("/monitor")
public void init(SimpMessageHeaderAccessor accessor) {
    String user = accessor.getFirstNativeHeader("userid");
    messagingTemplate.convertAndSendToUser(user, "/monitor", getOps());
}

Another way could be to subscribe to a different queue name which contains the user information (and this maybe was your proposal). The client must use a code similar to:

stompClient.subscribe('/topic/byUser/'+userId, function(msg) {
    console.log(msg);    
});

so that the server can access it this way:

@SubscribeMapping("/byUser/{userId}")
public void init(@DestinationVariable String userId) {
    messagingTemplate.convertAndSendToUser(userId, "/monitor", getOps());
}

but in this case keep in mind that that queue is public and hence other clients can access their messages if they knows other client names.

like image 60
Alessandro Polverini Avatar answered Jan 14 '23 08:01

Alessandro Polverini