WebSocket is used to develop two-way communication between server and browser. For example, in a chat application, if a user sends a message to a different user, the application sends that message to the server first and the server informs the application of the second user . If we donxt use WebSocket, the application or the client will have to pull the server data continuously for any new updates.
WebSocket Application With Spring Boot:
In Sprint Boot, we can easily create a WebSocket application. In this tutorial, I will show you how to create a WebSocket server in Spring boot. We will learn how to connect and disconnect from a socket server and how to send a simple text message. The client will subscribe to the server, it will accept a string and push a separate string to the subscriber client.
Configuration :
In this example, we are using IntelliJ-IDEA IDE with Gradle build system to create the application. You can follow the same process to create it on a maven build system.
Create one Basic app :
Letxs create one basic Spring boot application. Create one basic Spring boot application using start.spring. In this example, we are using Gradle but you can also use Maven as the build system. Open the application on your favorite editor before moving to the next step.
We will use WebSocket in this application.
Adding dependencies :
Open your project level build.gradle file and add the following dependencies :
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.webjars:stomp-websocket:2.3.3'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Note that you can use the same dependencies for a maven project as well and the version may be different than the above we are using at the time of writing this article.
Letxs build the App :
We need to create four components in the application.
- Model class to hold the type of data
- A controller class to define the routes
- Configuration class to configure spring to enable WebSocket and STOMP messaging
- Browser client or an HTML file and a javascript file for user interaction.
We will create each of these components one by one :
1. Model class :
We need two model classes. The controller will get the data as a Java object, modify it and returns one new Java object. This new object will be shown to to the user.
The service gets STOMP messages whose body is a JSON. It uses the model class to model this object. Create one file InputMessage.java inside your project :
public class InputMessage {
private String message;
public InputMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
This is the input message class. Once the service will receive that message, it will process it and send back a different model with a different class :
public class OutputMessage {
private String message;
public OutputMessage(String message){
this.message = message;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
The return value is in JSON format. Spring will use the Jackson JSON library for this conversion. Both of these classes are POJO.
2. Controller class :
Second part is to create the message handling controller class. Create one class called xMessageController.javax with the below code :
package com.demo.socket;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class MessageController {
@MessageMapping("/")
@SendTo("/chat/sendMessage")
public OutputMessage sendMessage(InputMessage message) {
return new OutputMessage("New message " + message.getMessage());
}
}
This class has one method defined called xsendMessagex. It takes one xInputMessagex object and returns one xOutputMessagex object.
3. Configuration class :
The configuration class should implement the xWebSocketMessageBrokerConfigurerx class. Create one file Config.java with the below code :
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.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class Config implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/chat");
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat-websocket").withSockJS();
}
}
Make sure that your SpringBootApplication class is configured like below :
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SocketApplication {
public static void main(String[] args) {
SpringApplication.run(SocketApplication.class, args);
}
}
Thatxs it. With these five files, our socket application is ready. The only thing left is the front end part of the HTML, CSS changes.
Browser client :
We need one HTML and one java-script file to create the basic app. Both files should be placed in the xresources/staticx folder. Create one xindex.htmlx file with the below code :
x!DOCTYPE htmlx xhtmlx xheadx xtitlexHello WebSocketx/titlex xlink rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" /x xscript src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"xx/scriptx xscript src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.3.0/sockjs.js"xx/scriptx xscript src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"xx/scriptx xscript src="/app.js"xx/scriptx x/headx xbodyx xdiv class="container"x xdivx xlabelxPress start to connect and stop to disconnect :x/labelx x/divx xdiv style="margin-top: 5px;"x xbutton id="button-start" type="button" class="btn btn-primary"x Start x/buttonx xbutton id="button-stop" type="button" class="btn btn-danger"x Stop x/buttonx x/divx xdiv style="margin-top: 15px;"x xp id="infotext" class="text-info"xYou are not connectedx/px x/divx xdiv id="input-group" class="input-group mb-3" x xinput id= "message-input" type="text" class="form-control" placeholder="Enter a message here" aria-describedby="button-addon2" /x xdiv class="input-group-append"x xbutton class="btn btn-outline-secondary" type="button" id="button-send" x Send x/buttonx x/divx x/divx xp id="message" class="text-success"xx/px x/divx x/bodyx x/htmlx
Inside the same folder, create one app.js file :
var stompClient = null;
function resetProperties(connected) {
$("#button-start").prop("disabled", connected);
$("#button-stop").prop("disabled", !connected);
if (connected) {
$("#input-group").show();
$("#infotext").html("You are connected");
}
else {
$("#input-group").hide();
$("#infotext").html("You are not connected");
}
}
function connect() {
var socket = new SockJS('/chat-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
resetProperties(true);
console.log("reset...");
stompClient.subscribe('/chat/sendMessage', function (greeting) {
showMessageOnPage(JSON.parse(greeting.body).message);
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
resetProperties(false);
}
function sendMessage() {
stompClient.send("/chat/sendMessage", {}, JSON.stringify({'message': $("#message-input").val()}));
}
function showMessageOnPage(message) {
$("#message").append("" + message + "");
}
$(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
resetProperties(false);
$( "#button-start" ).click(function() { connect(); });
$( "#button-stop" ).click(function() { disconnect(); });
$( "#button-send" ).click(function() { sendMessage(); });
});
Your application is ready at this point. Start it and open xlocalhost:8080x on a server. It will show a screen like below :
Enter anything in the input field and hit the xsendx button, the receiver will receive that message via socket and print it out at the bottom :
WebSocket Vs REST :
WebSocket and REST are two different concepts. Following are the main differences between REST and WebSocket :
- WebSocket is a stateful protocol but REST is a stateless protocol.
- REST applications are normally used for occasional communication but WebSockets are ideal for continuous communication
- With REST applications, a new TCP connection is used for each request but WebSocket uses the same TCP connection over the life of the socket connection.
- Communication cost is lower for WebSocket as compared to REST APIs
- In WebSocket, it is possible for both server and client to send and receive data at the same time
WebSocket has few advantages than RESTful APIs but it is not a direct replacement for REST. If multiple clients need to be synced at the same time, xWebSocketx is the best option. But, if the clients are only reading and writing data to the server independent of each other, REST will do the work.