Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Spring WebSocket send message to a specific user?

I am reading the book Spring in Action 4 to work with STOMP messaging over WebSocket.

Suppose the user destination prefix is set as "/user" as below:

registry.setUserDestinationPrefix("/user");

Then client subscribes to a destination with below JavaScript code:

stomp.subscribe("/user/queue/notifications", handleNotifications);

Then on the server, the actual destination that the client subscribes to should be derived from its session, maybe like this:

/queue/notifications-user6hr83v6t  --- (1)

Then I use the SimpMessagingTemplate to send message to that user:

messaging.convertAndSendToUser( username, "/queue/notifications",
                           new Notification("You just got mentioned!"));

Then the message will be sent to destination like this:

/user/<username>/queue/notifications  ---(2)

Well, the two destinations (1) and (2) look different, how could the message ever reach the client?

like image 407
smwikipedia Avatar asked Nov 15 '15 13:11

smwikipedia


People also ask

Can a WebSocket server send message to client?

Messages sent by the server to the client can include plain text messages, binary data, or images. Whenever data is sent, the onmessage function is fired. This event acts as a client's ear to the server. Whenever the server sends data, the onmessage event gets fired.

How do Websockets communicate?

In order to communicate using the WebSocket protocol, you need to create a WebSocket object; this will automatically attempt to open the connection to the server. The URL to which to connect; this should be the URL to which the WebSocket server will respond.

How does WebSocket work in Spring boot?

In order to tell Spring to forward client requests to the endpoint , we need to register the handler. Start the application- Go to http://localhost:8080 Click on start new chat it opens the WebSocket connection. Type text in the textbox and click send. On clicking end chat, the WebSocket connection will be closed.

How does WebSocket send data?

The WebSocket. send() method enqueues the specified data to be transmitted to the server over the WebSocket connection, increasing the value of bufferedAmount by the number of bytes needed to contain the data.


1 Answers

The path

/user/<username>/queue/notifications 

seems to be the "logical" path which is used in documentation. It is also initially created with convertAndSendToUser method. It is then translated into a technical format which is done in UserDestinationMessageHandler class in this line

UserDestinationResult result = this.destinationResolver.resolveDestination(message);

eg.

Given the subscription:

stompClient.subscribe('/user/queue/reply', function (greeting) { ...

sending a message with

stompClient.send("/app/personal", ...

and intercepting it with

@MessageMapping("/personal")
public void personalMessage(SimpMessageHeaderAccessor headerAccessor, PoCRequestMessage message) {

    SimpMessageHeaderAccessor ha = SimpMessageHeaderAccessor
            .create(SimpMessageType.MESSAGE);
    ha.setSessionId(headerAccessor.getSessionId());
    ha.setLeaveMutable(true);
    PoCReplyMessage reply = new PoCReplyMessage("Personal Message" + message.getName());
    simpMessagingTemplate.convertAndSendToUser(headerAccessor.getSessionId(), "/queue/reply", reply, ha.getMessageHeaders());
}

the destination will be resolved as follows:

source destination: /user/zojdn53y/queue/reply
target destination: /queue/reply-userzojdn53y

this is how the final destination name is resolved. The target destination is the real name of the queue that is created (at least as long an external message broker is used - didn't check this for a simple in-memory broker but I assume this would be the same).

One important thing to note is that when you want to use an unauthenticated user (most often scenario when experimenting with Websockets) you need to additionally put the message headers in convertAndSendToUser method - this is well described in

Spring WebSocket @SendToSession: send message to specific session

like image 116
Daniel Raczynski Avatar answered Dec 19 '22 18:12

Daniel Raczynski