🏠Spring BootIntroduction to WebSocket with Spring Boot

Introduction to WebSocket with Spring Boot

Spring Boot

Let’s take a look at how to add WebSocket support to a spring boot application. We will try to create a simple chat application. Note that this implementation does not use STOMP.

What is WebSocket?

The WebSocket protocol helps in establishing a full-duplex two-way communication between client and server over a single TCP connection. This protocol is different from HTTP but works over HTTP for compatibility.

Adding Websocket Support to Spring Boot

To add websocket support, you should add the following dependency to your spring boot project.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
Code language: HTML, XML (xml)

Note that we are going to use the basic version of web socket to provide a public group chat.

Create a WebSocket Handler

Like many protocols, WebSocket follows a client-server architecture. In our case, the javascript on browsers will act as clients and the spring boot server will act as a WebSocket server.

public class ChatMessageHandler extends TextWebSocketHandler { List<WebSocketSession> webSocketSessions = Collections.synchronizedList(new ArrayList<>()); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { super.afterConnectionEstablished(session); webSocketSessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { super.afterConnectionClosed(session, status); webSocketSessions.remove(session); } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { super.handleMessage(session, message); for (WebSocketSession webSocketSession : webSocketSessions) { webSocketSession.sendMessage(message); } } }
Code language: Java (java)

Let’s go through this class part by part. Web sockets support both TEXT and BINARY based communication. In our case, We are using a TextWebSocketHandler to deal with messages. This class already comes with a default implementation. But we want to receive messages and send them to other sessions we have.

So, Whenever a new client connects, we will store them in an in-memory list. And when the client disconnects, we will clear them from the list. And when one of the clients sends a message, We can forward that message to all other WebSocket sessions connected to our spring boot application.

It is important to note that this implementation is for the sake of the demo. Also, this example tries to broadcast every message to everyone including the sender. Even though this might be a valid case for a chat application, you might need to use a database to store the data and respond with processed results in real life.

Now we need to map this handler to a path the clients can recognize.

Spring configuration for WebSocket

We have our handler. But Spring needs to know about the handler we created. Also, spring boot will take care of certain configurations for the WebSocket setup. Here is a simple configuration class. Like before, let’s go through this class part by part.

@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { webSocketHandlerRegistry.addHandler(new ChatMessageHandler(), "/chat"); } }
Code language: Java (java)

The @Configuration annotation bootstraps @Enable* type annotations. In this case, We have @EnableWebSocket. This annotation makes sure the autoconfiguration for WebSocket is done. Also, note that we are using registerWebSocketHandlers() method to map the ChatMessageHandler to the path “/chat”.

Simple JavaScript Web socket Client

As we have completed our server part let’s move to the client. Every modern browser supports WebSocket protocol by default. Here is a simple HTML to send and receive messages.

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script type="application/javascript"> let ws; function connect() { ws = new WebSocket("ws://localhost:8080/hello"); ws.onmessage = function (e) { printMessage(e.data); } document.getElementById("connectButton").disabled = true; document.getElementById("connectButton").value = "Connected"; document.getElementById("name").disabled = true; } function printMessage(data) { let messages = document.getElementById("messages"); let messageData = JSON.parse(data); let newMessage = document.createElement("div"); newMessage.innerHTML = messageData.name + " : " + messageData.message; messages.appendChild(newMessage); } function sendToGroupChat() { let messageText = document.getElementById("message").value; document.getElementById("message").value=""; let name = document.getElementById("name").value; let messageObject = { name: name, message: messageText } ws.send(JSON.stringify(messageObject)) } </script> </head> <body> <input type="text" id="name"><input id="connectButton" type="button" value="Connect" onclick="connect()"> <div id="messages"></div> <input type="text" id="message"> <input type="button" value="send" onclick="sendToGroupChat()"> </body> </html>
Code language: HTML, XML (xml)

Lets break this down. In java script, you can connect to a web socket using WebSocket built in type. This type requires a “ws://” endpoint to connect to the server.

Once connected, We can use the methods like send, onmessage, onerror, onopen and onclose methods to deal with the connected session. In our case, we are using the onmessage event to receive the data and show it on the HTML page. Similarly, we can use the send method to publish a message to the server.

Spring Boot WebSocket in Action

Here is a demo that explains how the the websocket work in real time.

As you can see, Once connected to the servers, each page gets the messages all by itself. This is possible via the onmessage method. Also, if you go to the network tab of chrome developer tools, you can see all messages sent and received through the WebSocket connection.

Summary

We learned how to write a simple WebSocket server-client implementation using spring boot and JavaScript. Note that the WebSocket only work in modern browsers that support WebSocket. Check this list of browsers that support WebSocket for more info.

Also, there are a couple of disadvantages while using the basic WebSocket implementation. For example, the socket connection will be reset on page refresh. So you need to handle and identify each client(via a stateful approach). As I mentioned earlier, not all browsers support web sockets. This means you should write a fallback mechanism on your own to avoid those browser-related issues.

Importantly, this example is done without STOMP. We will cover that in an upcoming post. So stay tuned.

All the code mentioned above is available in our GitHub repository. Feel free to checkout and run the application on your own.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *