Spring Boot — Chat Application with WebSocket | Code Factory

Donate : Link

WordPress Blog : Link

WebSocket is a communication protocol that makes it possible to establish a two-way communication channel between a server and a client.

WebSocket works by first establishing a regular HTTP connection with the server and then upgrading it to a bidirectional websocket connection by sending an Upgrade header.

WebSocket is supported in most modern web browsers and for browsers that don’t support it, we have libraries that provide fallbacks to other techniques like comet and long-polling.

Well, now that we know what websocket is and how it works, let’s jump into the implementation of our chat application.

Creating the Application

WebSocket Configuration

The first step is to configure the websocket endpoint and message broker. Create a new class WebSocketConfig inside com.example package with the following contents -

The @EnableWebSocketMessageBroker is used to enable our WebSocket server. We implement WebSocketMessageBrokerConfigurer interface and provide implementation for some of its methods to configure the websocket connection.

In the first method, we register a websocket endpoint that the clients will use to connect to our websocket server.

Notice the use of withSockJS() with the endpoint configuration. SockJS is used to enable fallback options for browsers that don’t support websocket.

You might have noticed the word STOMP in the method name. These methods come from Spring frameworks STOMP implementation. STOMP stands for Simple Text Oriented Messaging Protocol. It is a messaging protocol that defines the format and rules for data exchange.

Why do we need STOMP? Well, WebSocket is just a communication protocol. It doesn’t define things like — How to send a message only to users who are subscribed to a particular topic, or how to send a message to a particular user. We need STOMP for these functionalities.

In the second method, we’re configuring a message broker that will be used to route messages from one client to another.

The first line defines that the messages whose destination starts with “/app” should be routed to message-handling methods (we’ll define these methods shortly).

And, the second line defines that the messages whose destination starts with “/topic” should be routed to the message broker. Message broker broadcasts messages to all the connected clients who are subscribed to a particular topic.

In the above example, We have enabled a simple in-memory message broker. But you’re free to use any other full-featured message broker like RabbitMQ or ActiveMQ.

Creating the ChatMessage model

ChatMessage model is the message payload that will be exchanged between the clients and the server. Create a new package model inside com.example package, and then create the ChatMessage class inside model package with the following contents -

Creating the Controller for sending and receiving messages

We’ll define the message handling methods in our controller. These methods will be responsible for receiving messages from one client and then broadcasting it to others.

Create a new package controller inside the base package and then create the ChatController class with the following contents -

If you recall from the websocket configuration, all the messages sent from clients with a destination starting with /app will be routed to these message handling methods annotated with @MessageMapping.

For example, a message with destination /app/chat.sendMessage will be routed to the sendMessage() method, and a message with destination /app/chat.addUser will be routed to the addUser() method.

Adding WebSocket Event listeners

We’ll use event listeners to listen for socket connect and disconnect events so that we can log these events and also broadcast them when a user joins or leaves the chat room -

We’re already broadcasting user join event in the addUser() method defined inside ChatController. So, we don’t need to do anything in the SessionConnected event.

In the SessionDisconnect event, we’ve written code to extract the user’s name from the websocket session and broadcast a user leave event to all the connected clients.

Creating the front-end

Create the following folders and files inside src/main/resources directory -

The src/main/resources/static folder is the default location for static files in Spring Boot.

1. Creating the HTML — index.html

The HTML file contains the user interface for displaying the chat messages. It includes sockjs and stomp javascript libraries.

SockJS is a WebSocket client that tries to use native WebSockets and provides intelligent fallback options for older browsers that don’t support WebSocket. STOMP JS is the stomp client for javascript.

Following is the complete code for index.html -

2. JavaScript — main.js

Let’s now add the javascript required for connecting to the websocket endpoint and sending & receiving messages. First, add the following code to the main.js file, and then we’ll explore some of the important methods in this file -

The connect() function uses SockJS and stomp client to connect to the /ws endpoint that we configured in Spring Boot.

Upon successful connection, the client subscribes to /topic/public destination and tells the user’s name to the server by sending a message to the /app/chat.addUser destination.

The stompClient.subscribe() function takes a callback method which is called whenever a message arrives on the subscribed topic.

Rest of the code is used to display and format the messages on the screen.

3. Adding CSS — main.css

Finally, Add the following styles to the main.css file -

Running the application

You can run the Spring Boot application by typing the following command in your terminal -

OR run SpringBootWebsocketApplication.java

The application starts on Spring Boot’s default port 8080. You can browse the application at http://localhost:8080.