Spring Boot Netty Socket.IO Example

Gürkan UÇAR
folksdev
Published in
5 min readSep 5, 2022

Imagine that, you want to make a chat application for communicating with your friend. You will send and receive messages. But there is a problem. When you send a new message to your friend how will you inform him?

  • A -) Your friend will refresh the page every x seconds for checking new messages.
  • B -) Something must be to listen to data and then get and show messages automatically in real-time.

I think B is a better choice. Of course, we have some other alternatives. I mentioned before here: WebSockets

This is where WebSocket comes into play. WebSocket is a bi-directional communication protocol. Communication provides over a single TCP connection.

Thanks to the WebSocket protocol server and client can communicate in real-time.

In this article, I will show you how can we implement Socket.IO to spring boot. Let’s get started!

  • Create a new spring-boot project
  • Add this dependency to the pom.xml file
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.17</version>
</dependency>

Note That! The version is very important while working on netty-socket.io. If you do not choose the correct version, you may encounter some problems.

Additionally, if you want to connect to the socket from React or HTML website you have to select socket-io. client 2. x.x version.

  • Configure the application.properties file
socket-server.port=8085
socket-server.host=192.168.0.10

192.168.0.10 => write your “IP address” not “localhost ” for connecting to socket from other devices

  • Create SocketIOConfig class under the “config” package.
  • Create ServerCommandLineRunner class under the “config” package
@Component
@Slf4j
@RequiredArgsConstructor
public class ServerCommandLineRunner implements CommandLineRunner {
private final SocketIOServer server; @Override
public void run(String... args) throws Exception {
server.start();
}
}
  • Create a Message class and MessageType enum
@Data
public class Message {
private MessageType type;
private String message;
private String room;

public Message() {
}

public Message(MessageType type, String message) {
this.type = type;
this.message = message;
}
}
public enum MessageType {
SERVER, CLIENT
}
  • Create SocketModule class
  • server.addConnectListener(onConnected()) => triggering when someone connect to the socket
  • server.addDisconnectListener(onDisconnected()) => triggering when someone disconnect from the socket
  • server.addEventListener(“send_message”, Message.class, onChatReceived()) => it’s corresponding socket.on(“send_message”), which means you can handle events by given event name and object class.
  • senderClient.getNamespace().getBroadcastOperations().sendEvent(“get_message”, data.getMessage()) => sending data to all of the clients, includes yourself

We have a problem!

If you want to send a message to any specific room or any client, you can not use broadcast operations. You have to implement room logic or you can send a private message by socketID of user.

Let’s implement room logic

Firstly I will add a parameter to the connection URL whose name is “room”.

  • URL will look like this => ws://192.168.0.10:8085/socket.io/?room=room_name

And then I will get this room parameter in SocketModule => socket onConnected method. Please update this method by given code 👇

private ConnectListener onConnected() {
return (client) -> {
String room = client.getHandshakeData().getSingleUrlParam("room");
client.joinRoom(room);
log.info("Socket ID[{}] Connected to socket", client.getSessionId().toString());
};

client.joinRoom(“room”) => this code will join you to the room by given room name.

We have to update SocketModule => onChatReceived method too 👇

private DataListener<Message> onChatReceived() {
return (senderClient, data, ackSender) -> {
log.info(data.toString());
socketService.sendMessage(data.getRoom(),"get_message", senderClient, data.getMessage());
};
}

And don’t forget to add:

private final SocketService socketService;

SocketModule final Code will look like this:

I separated the sendMessage function from SocketModule and I created a SocketService class. Let’s look at this.

In sendMessage method, I am passing some parameters:

  • String room => which room will get the message
  • String eventName => which event will get the message
  • SocketIOClient sendeClient => who is wanting to send a message (except this while sending a message to room)
  • String message => message

In the for loop, we are getting all the users in a given room. Then if the person is not equal to the sender, we are sending the message to each person.

How Can We Test??

We will use postman for testing our socket.

First, you have to login to the postman to access the WebSocket tester module.

  • Click to the WebSocket Request option
  • Select the Socket.IO
  • Write the connection URL and add params (if you have params in URL, you will see the params under the params tab automatically).
  • ws://[YOUR_LOCAL_IP]:8085?room=a
  • Click the Settings tab and select v2 for client
  • Click the events tab and write your event name for getting messages.
  • Must be the same with:
  • Write your message class model and don’t forget to add room field
  • Write the socket handler event name and press sent button for sending messages
  • Duplicate tabs for testing and click to connect!

Video

Configure postman:

Working example:

You can find the codes here:

BONUS

Spring Boot & SocketIO & Reactjs — Chat application

github.com/gurkanucar/socketio-simple-chat

Res:

--

--