Building Real-Time Notification Systems with WebSocket and Spring Boot

fullstackjavadev.in
3 min readJun 1, 2024

--

In modern web applications, real-time communication between the server and clients is becoming increasingly important. Traditional HTTP request-response communication is not suitable for scenarios where data needs to be pushed from the server to clients in real-time. This is where WebSocket comes into play. WebSocket is a protocol that provides full-duplex communication channels over a single TCP connection, allowing for bi-directional data flow between the server and clients.

Spring Boot provides excellent support for WebSocket through its spring-websocket module. In this blog post, we'll explore how to build a real-time notification system using WebSocket in a Spring Boot application.

Prerequisites

Before we dive in, ensure you have the following:

  • Basic knowledge of Spring Boot and Java
  • Understanding of the WebSocket protocol
  • Familiarity with front-end technologies like JavaScript and HTML

Setting Up the Spring Boot Application

1. Add Dependencies

First, create a new Spring Boot project or add the following dependencies to your existing pom.xml:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2. Enable WebSocket Support

Enable WebSocket support by adding the @EnableWebSocketMessageBroker annotation to your main application class or a dedicated configuration class.

Creating the WebSocket Configuration

1. Define WebSocket Configuration

Create a configuration class to set up WebSocket:

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;


@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").withSockJS();
}
}

2. Explanation

  • @EnableWebSocketMessageBroker enables WebSocket message handling.
  • setApplicationDestinationPrefixes maps incoming messages to @MessageMapping methods.
  • enableSimpleBroker sets up an in-memory message broker.

Implementing the WebSocket Handler

1. Create a Message Controller

Create a controller to handle incoming WebSocket messages:

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;


@Controller
public class NotificationController {
@MessageMapping("/send")
@SendTo("/topic/notifications")
public String sendNotification(String message) {
return message;
}
}

2. Explanation

  • @MessageMapping("/send") maps to /app/send.
  • @SendTo("/topic/notifications") sends the message to /topic/notifications.

Sending Notifications

1. Inject SimpMessagingTemplate

Inject SimpMessagingTemplate to send messages:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

@Service
public class NotificationService {
@Autowired
private SimpMessagingTemplate template;
public void sendNotification(String message) {
template.convertAndSend("/topic/notifications", message);
}
}

2. Explanation

  • convertAndSend sends a message to the specified destination.

Building the Front-End

1. Create HTML File

Create an HTML file with a WebSocket connection:

<!DOCTYPE html>
<html>
<head>
<title>WebSocket Notifications</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
</head>
<body>
<div id="notifications"></div>
<script>
var socket = new SockJS('/websocket');
var stompClient = Stomp.over(socket);

stompClient.connect({}, function(frame) {
stompClient.subscribe('/topic/notifications', function(notification) {
var notifications = document.getElementById('notifications');
var message = document.createElement('p');
message.appendChild(document.createTextNode(notification.body));
notifications.appendChild(message);
});
});
</script>
</body>
</html>

2. Explanation

  • Connect to the WebSocket endpoint.
  • Subscribe to /topic/notifications.
  • Display received messages in the browser.

Example Implementation

Here is a complete example implementation with the server-side and client-side components we discussed.

Server-Side Code

WebSocketConfig.java

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {


@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").withSockJS();
}
}

NotificationController.java

@Controller
public class NotificationController {


@MessageMapping("/send")
@SendTo("/topic/notifications")
public String sendNotification(String message) {
return message;
}
}

NotificationService.java

@Service
public class NotificationService {

@Autowired
private SimpMessagingTemplate template;
public void sendNotification(String message) {
template.convertAndSend("/topic/notifications", message);
}
}

Client-Side Code

index.html

<!DOCTYPE html>
<html>
<head>
<title>WebSocket Notifications</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
</head>
<body>
<div id="notifications"></div>
<script>
var socket = new SockJS('/websocket');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
stompClient.subscribe('/topic/notifications', function(notification) {
var notifications = document.getElementById('notifications');
var message = document.createElement('p');
message.appendChild(document.createTextNode(notification.body));
notifications.appendChild(message);
});
});
</script>
</body>
</html>

Conclusion

In this blog post, we learned how to implement real-time notifications using WebSocket in a Spring Boot application. We covered the setup, configuration, and implementation of the server-side and client-side components. WebSocket provides a powerful mechanism for real-time communication, enabling applications to deliver timely and relevant notifications to users.

By following this guide, you can create a robust real-time notification system that enhances user experience and engagement in your web applications.

--

--