Javascript is required
ยท
7 min read

Sending Message To Specific Anonymous User On Spring WebSocket

Sending Message To Specific Anonymous User On Spring WebSocket Image

In my current, I had the opportunity to develop a new application based on Vue.js in the frontend and Spring Boot in the backend. The backend should send updates to the frontend via a WebSocket connection so that users do not need to refresh the website to see the latest information.

The view should show a list of transfers where the user can modify the results by using filters and pagination. As a requirement, each user should receive specific results based on his filters and pagination without broadcasting this to all other connected users. The user does not need to authenticate itself at the backend.

Most tutorials cover either the case of broadcasting messages to all connected users or to send messages to certain authenticated users. In this article, I will demonstrate how to send messages to anonymous users without broadcasting the messages.

The Demo Project

I have a created a demo project to be able to demonstrate the functionality. It is a simple monorepo which contains a backend and a frontend folder.

Backend

The Spring Boot backend was bootstrapped using Spring Initializr where I chose WebSocket as the only dependency:

Spring Initializr Setup

Configure Websocket

The next step is to configure the application to use a WebSocket connection. To configure the Spring Boot application I followed this tutorial without the frontend part.

After this tutorial we have a working WebSocket controller that receives and sends messages via a WebSocket connection:

1@Slf4j
2@Controller
3public class GreetingController {
4
5    @MessageMapping("/hello")
6    @SendTo("/topic/greetings")
7    public Greeting greeting(HelloMessage message) throws Exception {
8        log.info("Received greeting message {}", message);
9        greetingService.addUserName(principal.getName());
10        Thread.sleep(1000); // simulated delay
11        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
12    }
13}

The greeting() method is called if a message is sent to the /hello destination. This is ensured by using the @MessageMapping annotation. The received message is then sent to / topic/greetings. I have added a simulated delay to simulate any asynchronous operation that could be executed on the server-side in between receiving and sending messages.

In this implementation, all messages are broadcasted to all connected users by using the @SendTo annotation.

Greeting.java and HelloMessage.java are simple Java classes which represent the transferred data objects:

1public class Greeting {
2
3    private String content;
4
5    public Greeting() {
6    }
7
8    public Greeting(String content) {
9        this.content = content;
10    }
11
12    public String getContent() {
13        return content;
14    }
15}
1public class HelloMessage {
2
3    private String name;
4
5    public HelloMessage() {
6    }
7
8    public HelloMessage(String name) {
9        this.name = name;
10    }
11
12    public String getName() {
13        return name;
14    }
15
16    public void setName(String name) {
17        this.name = name;
18    }
19}

The WebSocket is configured in WebSocketConfig.java:

1@Configuration
2@EnableWebSocketMessageBroker
3public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
4
5    @Override
6    public void configureMessageBroker(MessageBrokerRegistry config) {
7        config.enableSimpleBroker("/topic");
8        config.setApplicationDestinationPrefixes("/app");
9    }
10
11    @Override
12    public void registerStompEndpoints(StompEndpointRegistry registry) {
13        registry.addEndpoint("/ws").setAllowedOrigins("*");
14        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
15    }
16}

In my project, we send updates to the clients via a scheduled interval so I also added this functionality to this demo project. The first step is to enable scheduling in the Spring Boot application using the @EnableScheduling annotation:

1@SpringBootApplication
2@EnableScheduling // this annotation enables scheduling
3public class WebsocketAnonymousMessagesDemoApplication {
4
5    public static void main(String[] args) {
6        SpringApplication.run(WebsocketAnonymousMessagesDemoApplication.class, args);
7    }
8}

Next, a Scheduler.java class handles the scheduled tasks and triggers GreetingService to send a new message each second:

1@Slf4j
2@Component
3public class Scheduler {
4    private final GreetingService greetingService;
5
6    Scheduler(GreetingService greetingService) {
7        this.greetingService = greetingService;
8    }
9
10    @Scheduled(fixedRateString = "6000", initialDelayString = "0")
11    public void schedulingTask() {
12        log.info("Send messages due to schedule");
13        greetingService.sendMessages();
14    }
15}

GreetingsService.java injects SimpMessagingTemplate which provides methods to programmatically send WebSocket messages: