Send STOMP message to a specific user with Spring WebSocket

In the previous tutorial, I showed you how to implement WebSocket using Spring WebSocket. In the example of that post, all users subscribed to “/topic/messages” will receive messages published to this topic. In case you want to only send to a certain user, how? In this tutorial, I will show you how to send a STOMP message to a specific user with Spring WebSocket!

I also created a Spring Boot project with Web and WebSocket dependency like the previous post.

The result is as follows:

Send STOMP message to a specific user with Spring WebSocket

I also declare to use WebJars with JQuerySocketJS client and Stomp WebSocket dependencies as follows:

Similar to the previous post, I also created a new class to configure WebSocket as follows:

Differences here:

  • The first is that I let the value of the parameter in the enableSimpleBroker() method be “queue”, the purpose is to show the purpose of the example, point-to-point, but you can name it whatever you want!
  • The main thing you need to know is that to send a message to a specific user, we will send the message to a default endpoint that starts with “/user”, “/user/queue/messages” for example. We can change this default prefix by using the setUserDestinationPrefix() method of the MessageBrokerRegistry object like I did above. In our example now, we need a message to the endpoint “/users/queue/messages”.

To handle the message from the client sent to the STOMP endpoint of the WebSocket server, I also created a new MessageController class with the following content:

I also use @MessageMapping to define a mapping method handle for the “/hello” request to the WebSocket server.

The difference here is that we don’t use the @SendTo annotation like in the previous tutorial, but will use the SimpMessagingTemplate class with the convertAndSendToUser() method to send a message to a specific user.

There are multiple overloads for this convertAndSendToUser() method:

Send STOMP message to a specific user with Spring WebSocket

I’m just using a simple method with 3 parameters: user, destination and payload.

The second parameter, destination, is the endpoint that the client needs to subscribe to, of course it is necessary to add the prefix that we have configured in the WebSocketConfiguration class. In my example, clients need to subscribe to the “/users/queue/messages” endpoint.

The third parameter, payload, is the message content that we need to send to the user.

The 1st parameter, user is the most important parameter that took me a lot of time to determine, because there is currently no Spring official document talking about this. It is actually the username associated with a session id when a client connects to the WebSocket server. By default, only session id is generated and comes with each WebSocket connection and username, if we don’t add code to define username, this username will be null. This username information, if any, will be contained in the implementation of the java.security.Principal interface, the SimpMessageHeaderAccessor class contains information about the WebSocket connection header and will contain the information of this implementation class. That’s why in the send() method of the MessageController class, I used the SimpMessageHeaderAccessor class as a parameter of this method.

In the example of this tutorial, I will pass the username information into the header of the WebSocket connection when the client connects to the WebSocket server and on the WebSocket server side, I will add the code for Spring to get it as the username of the WebSocket connection.

My front-end code is as follows:

index.html:

app.js:

The results when running my example are as follows:

Send STOMP message to a specific user with Spring WebSocket

We will enter the username that will be associated with the WebSocket connection then click the Connect button to create a WebSocket connection. For simplicity, I only allow users to enter the username they want to send the message, the message content will automatically generate from the WebSocket server. When a user receives a message from someone, the content of this message will be displayed behind the text “Message from someone”.

In the app.js file, as you can see, the client is subscribing to the “/users/queue/messages” endpoint to receive messages from other users.

Now, I will code the most important part of adding the username information associated with each connection to the WebSocket server.

First, I will create a new User class that implements the java.security.Principal interface:

Next, we will update the WebSocketConfiguration class to add an interceptor for each WebSocket connection to the WebSocket server. We will add code to set the user information for each connection, as follows:

The content of the UserInterceptor class is as follows:

In other words, for each WebSocket connection, I will get the username information that I have passed on the client side to assign user information to that connection. The setUser() method of the SimpMessageHeaderAccessor class with the java.security.Principal interface parameter will help us do this.

Now we can run the application to see how the results are!

I will open 2 browser windows, enter the user information “khanh” and “test” for each browser window and press the Connect button. Then, in the “test” user’s window, I will enter the username “khanh” and press the Send button. In the window of the user “khanh”, you will see the following results:

Send STOMP message to a specific user with Spring WebSocket

4.2/5 - (6 votes)

5 thoughts on “Send STOMP message to a specific user with Spring WebSocket

  1. Thank you for your work, Khanh,
    May I ask you where the server store websocket users? If you click ‘connect’ twice and next click ‘send’ button you will receive the message from server twice too. Why?
    Even after username changed (next ‘Connect’ button with different) you’ll receive more than one message from the server.
    How can we list or delete websocket connections?

    1. OK, i know, ‘stompClient.subscribe(‘/user/queue/reply’…’ more than once. 🙂
      But how can server list websocket users and how to secure websocket?

  2. I run the code posted here. Both sender and receiver connected to the server. And the server created msg. However, the receiver didn’t receive the msg. Don’t know what was wrong.

Add Comment