WebSocket implementation with Spring Boot

Spring Boot is a microservice-based Java framework used to create web application. It provides radically faster and widely accessible getting-started experience for the development along with ready to use non functional features. It is licensed under Apache License 2.0.
WebSocket
The WebSocket API is an advanced technology that provides full-duplex communication channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C.
It will be persistent connection to send and receive messages quickly between client and server without much overhead.It can be used for Chat Applications, Long Polling Applications, Multi-player Game Applications, Send live Analytics data.
Getting Started
In this article we will create a spring boot application using Maven and send some sample messages from client and server and receive vice versa. Create pom.xml with following dependencies inside the project dir
mkdir springwebsocket
cd springwebocket
In the pom.xml, we need to keep spring boot starter parent to create a spring boot project. We would require spring boot starter web for having the http endpoints. It will initially do a handshake on the http endpoints and then web socket protocol is used for future communications. Websocket related dependency are also added for sending and receiving the message in the back end.
Also spring boot maven plugin to make compile and executable jar.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nagappan</groupId>
<artifactId>springwebsocket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<licenses>
<license/>
</licenses>
<!-- Additional lines to be added here... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Now we will create the spring boot application starter in the main class using SpringApplication.run(classname). This will create the spring web context with the tomcat as embedded server container.
@RestController
@EnableAutoConfiguration
@ComponentScan(basePackages= {"com.nagappan.springwebsocket"})
public class SpringWebsocket {
@RequestMapping("/")
public String home() {
return "hello world";
}
public static void main(String args[]) {
SpringApplication.run(SpringWebsocket.class, args);
}
}
Component package scan has been added for the configuration of those packages automatically. We will now create websocket endpoint ("/my-websocket-endpoint") and register handler for the endpoint with websockethandler registry. The handler should be a sub class extended from WebSocketHandler.
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Bean
public WebSocketHandler myMessageHandler() {
return new MyMessageHandler();
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
System.out.println("websocket endpoint handler");
registry.addHandler(myMessageHandler(), "/my-websocket-endpoint");
}
}
The MyMessageHandler is responsible to send and receive text messages so we need to extend the handler from TextWebSocketHandler which has listeners for Connection establishment, Closing connections and Handling text messages. Once the connection is established it sends a message to client "You are now connected to the server. This is the first message".
public class MyMessageHandler extends TextWebSocketHandler {
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("web socket has been closed");
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
/* The WebSocket has been opened
I might save this session object so that I can send messages to it outside of this method
Let's send the first message */
System.out.println("web socket connection established");
session.sendMessage(new TextMessage("You are now connected to the server. This is the first message."));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {
System.out.println("Message received: " + textMessage.getPayload());
}
}
Client can now connect to websocket with WebSocket Javascript API. Javascript websocket API has event handlers for socket open and message handler. Create a websocket and connect to the websocket endpoint (/my-websocket-endpoint). On the successful socket open handler, send the message to the server through websocket. On successful receive server's message(socket.onmessage handler)and provides support to send message to the server. In this example, an input field is provided where user enters the message which will received by the server and it sends back the message to the client. Those discussion conversion will be displayed in the server message in the label fields.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spring web socket tutorial</title>
<script>
var socket = new WebSocket('ws://' + window.location.host + '/my-websocket-endpoint');
<!-- Add an event listener for when a connection is open -->
socket.onopen = function() {
console.log('WebSocket connection opened. Ready to send messages.');
<!-- Send a message to the server -->
socket.send('Hello, from WebSocket client!');
};
<!-- Add an event listener for when a message is received from the server -->
socket.onmessage = function(message) {
console.log('Message received from server: ');
console.log(message);
document.getElementById("displaymsg").innerText += "\n" + message.data;
};
function sendbtn() {
let textmsg = document.getElementById("msgtext").value;
console.log("goint to send message");
console.log(textmsg);
socket.send(textmsg);
}
</script>
</head>
<body>
<input id="msgtext" type="text"></input>
<button onclick="sendbtn()">Send</button>
<h1>Messages received from server</h1>
<div style="border-style: solid; border-width: 2px;">
<label id="displaymsg"></label>
</div>
</body>
</html>
Start the application using "mvn spring-boot:run". Then web client ui show all the message send to server in the below label html element.
Reference:
Source code : https://github.com/nagappan080810/springwebsockets