Luciano Greiner
Luciano Greiner

Reputation: 183

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!

Upvotes: 4

Views: 9591

Answers (1)

Alessandro Polverini
Alessandro Polverini

Reputation: 2451

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.

Upvotes: 14

Related Questions