Skyshift technologies Blog

Real-Time Communication with WebSockets: Integrating Angular, Spring Boot, and MySQL

In modern web applications, real-time communication has become essential, whether for live chat, notifications, or collaborative platforms. One of the most efficient ways to achieve this is through WebSockets. In this article, we will walk through how to integrate WebSocket communication between Angular (frontend), Spring Boot (backend), and MySQL (for storing message history).

What Are WebSockets?

WebSockets provide full-duplex communication channels over a single, long-lived connection. Unlike traditional HTTP, which follows a request-response pattern, WebSockets enable the server to push messages to the client without the client having to request them. This makes WebSockets ideal for applications that require real-time updates.

WebSocket Use Cases

WebSockets are perfect for scenarios where low-latency, real-time communication is essential, such as messaging apps, collaborative tools, and real-time monitoring systems. Their ability to maintain an open connection makes them ideal for applications where the server needs to push updates to clients immediately.

Here are some common use cases for WebSockets:

  • Real-Time Chat Applications
  • Live Notifications
  • Real-Time Collaboration Tools
  • Stock Market and Financial Tickers
  • Real-Time Dashboards
  • Sports Scores and Updates
  • Real-Time Auctions

Technologies We Will Use

  • Spring Boot: To manage WebSocket connections and broadcast messages.

What are we going to build?

In this example, we'll build a server that continuously generates events and broadcasts them to all connected WebSocket clients. This implementation uses a Spring Boot WebSocket server to push randomly generated events to clients at regular intervals.

1.Setting Up Spring Boot with WebSocket Support


                    
                    <dependencies>
                        <!-- Spring Boot WebSocket starter -->
                        <dependency>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-starter-websocket</artifactId>
                        </dependency>
                        
                        <!-- MySQL Connector -->
                        <dependency>
                            <groupId>mysql</groupId>
                            <artifactId>mysql-connector-java</artifactId>
                        </dependency>
                        
                        <!-- JPA for MySQL interaction -->
                        <dependency>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-starter-data-jpa</artifactId>
                        </dependency>
                    </dependencies>
                    
                    

2. WebSocketConfigurer

WebSocketConfigurer is the interface used to configure and register WebSocket handlers in Spring applications. Through this, developers define which endpoints handle WebSocket connections and can also manage cross-origin requests for these connections. It’s a crucial part of integrating WebSocket functionality into a Spring Boot app.

Core Functionalities of the WebSocketConfigurer

  1. Registering WebSocket Handlers: It allows you to define endpoints (URIs) where the WebSocket server will listen for incoming connections.
  2. Configuring Allowed Origins: You can specify which origins (URLs) are allowed to connect to your WebSocket. This is important for security, especially when your frontend and backend are hosted on different domains.
  3. Custom WebSocket Handlers: You can attach custom handlers that define how WebSocket connections and messages are handled.

Core Methods of WebSocketConfigurer

The primary method in WebSocketConfigurer is registerWebSocketHandlers. It accepts a WebSocketHandlerRegistry which is used to map WebSocket endpoints and configure related settings.

public interface WebSocketConfigurer {
                void registerWebSocketHandlers(WebSocketHandlerRegistry registry);
            }
                

3. WebSocketConfigurer Implementation

We will create a WebSocket configuration to set up the WebSocket connection in Spring Boot. This configuration will map WebSocket connections to a specific endpoint (in this case, /ws).

WebSocketConfig Class


    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    
    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(new CustomWebSocketHandler(), "/ws").setAllowedOrigins("*");
        }
    }
            

Here, we are setting up a handler that will manage WebSocket connections at /ws.

4. Handling WebSocket Messages in Spring Boot

Now that we have set up the connection, let’s see how we can handle incoming messages. In our case, the WebSocket will handle text-based messages. To manage these messages, we can extend the TextWebSocketHandler, which is a convenient class provided by Spring to handle text-specific WebSocket communication.

TextWebSocketHandler Overview

TextWebSocketHandler is a class provided by Spring that simplifies handling WebSocket messages, particularly text-based ones. It extends the AbstractWebSocketHandler class and is specialized for handling WebSocket messages that contain text payloads, making it easier to implement real-time communication features in your application.

Core Functionalities of the TextWebSocketHandler

  • Handling Incoming Text Messages: It provides a method to process text messages received from the client.
  • Handling WebSocket Events: It allows you to handle lifecycle events like when a WebSocket connection is established or closed.
  • Sending Messages Back to the Client: It allows you to send messages back to the connected client over the WebSocket connection.

Key Methods in TextWebSocketHandler

  • handleTextMessage(WebSocketSession session, TextMessage message)
    • This method is triggered when the WebSocket receives a text message from the client.
    • You can override it to define what should happen when a message arrives (e.g., broadcasting it to other clients, logging it, etc.).
  • afterConnectionEstablished(WebSocketSession session)
    • This method is called when a new WebSocket connection is established with a client.
    • You can use it to perform actions like logging the connection or sending a welcome message to the client.
  • afterConnectionClosed(WebSocketSession session, CloseStatus status)
    • This method is called when a WebSocket connection is closed.
    • You can use it to perform clean-up operations or log that the connection has been closed.
  • handleTransportError(WebSocketSession session, Throwable exception)
    • This method is called if there is an error in the WebSocket transport layer (e.g., network error or disconnection).
    • It allows you to log or handle such errors.

5. Implementation of TextWebSocketHandler

Now, we’ll implement the CustomWebSocketHandler class to manage WebSocket sessions and messages.

EventWebSocketHandler Class

The EventWebSocketHandler class extends TextWebSocketHandler and provides the implementation for managing WebSocket sessions. It maintains a thread-safe list of active WebSocket sessions, allowing us to broadcast messages to all connected clients.

Code Implementation


    import org.springframework.web.socket.TextMessage;
    import org.springframework.web.socket.WebSocketSession;
    import org.springframework.web.socket.handler.TextWebSocketHandler;
    
    import java.io.IOException;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class EventWebSocketHandler extends TextWebSocketHandler {
    
        // A thread-safe list to store WebSocket sessions
        private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            // Add the new session to the list
            sessions.add(session);
            System.out.println("New WebSocket connection established.");
        }
    
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
            // Remove the closed session from the list
            sessions.remove(session);
            System.out.println("WebSocket connection closed.");
        }
    
        public void broadcastEvent(String event) {
            // Send the event to all connected clients
            for (WebSocketSession session : sessions) {
                if (session.isOpen()) {
                    try {
                        session.sendMessage(new TextMessage(event));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
            
  • Thread-Safe Session Management: The class uses a CopyOnWriteArrayList to store WebSocket sessions, ensuring thread safety when adding or removing sessions.
  • Connection Handling: It overrides afterConnectionEstablished and afterConnectionClosed methods to manage session lifecycle events.
  • Broadcasting Messages: The broadcastEvent method sends messages to all connected clients, facilitating real-time updates.

6. Server Broadcasting Events to All Clients

In this section, we will implement the EventGenerator class, which simulates event generation and broadcasts these events to all connected WebSocket clients.

EventGenerator Class

The EventGenerator class uses Spring's @Scheduled annotation to generate a new event every 5 seconds. Each generated event is then sent to all connected WebSocket clients using the broadcastEvent method from the EventWebSocketHandler.

Code Implementation


    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalTime;
    
    @Component
    public class EventGenerator {
    
        @Autowired
        private EventWebSocketHandler webSocketHandler;
    
        // Simulate event generation every 5 seconds
        @Scheduled(fixedRate = 5000)
        public void generateEvent() {
            String event = "Event generated at: " + LocalTime.now();
            System.out.println(event);
            
            // Broadcast the event to all WebSocket clients
            webSocketHandler.broadcastEvent(event);
        }
    }
            
  • Scheduled Event Generation: The class uses the @Scheduled annotation to trigger event generation at fixed intervals (every 5 seconds).
  • Event Broadcasting: Each generated event is broadcasted to all connected WebSocket clients, facilitating real-time communication.
  • Time Stamping: Each event includes a timestamp, allowing clients to see when the event was generated.

7. Enable Scheduling in Your Spring Boot Application

To enable scheduling capabilities in your Spring Boot application, you need to annotate your main application class with @EnableScheduling. This allows you to use the @Scheduled annotation in your application to execute tasks at fixed intervals or specific times.

WebSocketApplication Class

Below is the implementation of the WebSocketApplication class, which serves as the entry point for your Spring Boot application and enables scheduling.

Code Implementation


    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @SpringBootApplication
    @EnableScheduling
    public class WebSocketApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(WebSocketApplication.class, args);
        }
    }
            
  • Scheduling Enabled: The @EnableScheduling annotation activates scheduling support in the application.

8. Conclusion

In this article, we explored setting up a WebSocket server using Spring Boot and handling server-generated events. In the next article, we’ll dive into the front-end integration, showing how to connect this WebSocket server to an Angular application for real-time updates. Stay tuned!