Module: Real-time Messaging
Relevant source files
The following files were used as context for generating this wiki page:
- zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/ChatLauncher.java
- zheng-message/zheng-message-client/index.html
- zheng-message/zheng-message-sdk/src/main/java/com/zheng/message/sdk/MessageHelper.java
- zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/MessageEventHandler.java
- zheng-message/zheng-message-server/pom.xml
- zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/Data.java
The zheng-message module provides real-time messaging and chat functionality for the zheng project. It is a self-contained system composed of a server, a client, and an SDK, designed for event-based, bidirectional communication.
The architecture is built upon netty-socketio, a Java implementation of the Socket.IO server. The module is divided into three main components: zheng-message-server (the backend WebSocket server), zheng-message-client (a web-based chat client for demonstration), and zheng-message-sdk (a Java client library for programmatic message sending).
Architecture Overview
The messaging module consists of three primary components that interact to provide real-time communication. The server acts as a central hub, receiving messages from any client (web or SDK) and broadcasting them to all connected participants.
This diagram illustrates the flow of messages from different clients through the central server and back out to all connected clients.
zheng-message-server: The core WebSocket server built withnetty-socketio. It listens for client connections, handles incoming messages, and broadcasts them to all connected clients.zheng-message-client: A simple HTML/JavaScript client that serves as a demonstration and testing tool for the messaging functionality.zheng-message-sdk: A Java SDK that allows other backend services or Java applications to programmatically send messages through the message server.
Sources: zheng-message/pom.xml, zheng-message/zheng-message-server/pom.xml, zheng-message/zheng-message-client/index.html, zheng-message/zheng-message-sdk/src/main/java/com/zheng/message/sdk/MessageHelper.java
Server-Side Implementation (zheng-message-server)
The server is the heart of the messaging module, responsible for managing client connections and message relay.
Core Technology
The server leverages the netty-socketio library to implement the Socket.IO protocol on top of the Netty framework. This is declared as a system-scoped dependency in the project's pom.xml.
<!-- zheng-message/zheng-message-server/pom.xml:24-29 -->
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.12.zheng</version>
<scope>system</scope>
<systemPath>${basedir}/lib/netty-socketio-1.7.12.zheng.jar</systemPath>
</dependency>
Sources: zheng-message/zheng-message-server/pom.xml:24-29
Server Initialization
The ChatLauncher class serves as the main entry point for starting the message server. It configures and launches the SocketIOServer instance.
Key initialization steps in ChatLauncher.main():
- A
Configurationobject is created. - The hostname (
localhost) and port (8881) are set. - A
SocketIOServeris instantiated with the configuration. - The
MessageEventHandleris registered to handle socket events. - The server is started via
server.start().
// zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/ChatLauncher.java:12-23
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(8881);
final SocketIOServer server = new SocketIOServer(config);
// Add event handler
server.addListeners(new MessageEventHandler(server));
server.start();
// ...
}
Sources: zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/ChatLauncher.java:12-23
Event Handling
The MessageEventHandler class contains the logic for handling lifecycle and custom events from Socket.IO clients.
The message flow for a chat event is as follows:
The handler implements methods for three main events:
@OnConnect: Triggered when a client establishes a connection. It logs the client's session ID.@OnDisconnect: Triggered when a client disconnects. It logs the client's session ID.@OnEvent("chat"): The primary message handler. It receives aDataobject from a client and usesserver.getBroadcastOperations().sendEvent("chat", data)to broadcast the message to all other connected clients.
Sources: zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/MessageEventHandler.java
Data Model
Messages are exchanged using a simple Plain Old Java Object (POJO), Data.
| Field | Type | Description |
|---|---|---|
user | String | The username of the sender. |
msg | String | The content of the message. |
Sources: zheng-message/zheng-message-server/src/main/java/com/zheng/message/server/Data.java
Client-Side Implementation (zheng-message-client)
A simple web-based client is provided in index.html to demonstrate and test the chat functionality. It uses the standard socket.io.js client library.
The client UI consists of:
- An input for the username.
- An input for the message text.
- A "Send" button.
- An unordered list (
<ul>) to display received messages.
The core client-side logic involves:
- Connecting to the server:
var socket = io.connect('http://localhost:8881'); - Emitting a
chatevent with the user and message data when the form is submitted. - Listening for incoming
chatevents from the server and appending the message to the list.
// zheng-message/zheng-message-client/index.html:26-38
socket.on('connect', function() {
// Connected, let's sign-up for to receive messages for this room
output('<span class="connect-msg">Connected</span>');
});
// event handler for server sent messages
socket.on('chat', function(data) {
var a = new Date(data.time);
output('<span class="username-msg">' + data.user + '</span>' + '<span class="time-msg"> ' + a.getHours() + ':' + a.getMinutes() + ':' + a.getSeconds() + '</span>' + ': ' + data.msg);
});
Sources: zheng-message/zheng-message-client/index.html:12-59
Message SDK (zheng-message-sdk)
The zheng-message-sdk module provides a MessageHelper class, which acts as a Java client for the message server. This allows other Java applications within the zheng ecosystem to programmatically send messages.
The SDK uses the io.socket:socket.io-client library. The MessageHelper.main method demonstrates its usage:
- Establish a connection to the message server.
- Create a
JSONObjectpayload containing theuserandmsg. - Emit a
chatevent with the JSON payload.
// zheng-message/zheng-message-sdk/src/main/java/com/zheng/message/sdk/MessageHelper.java:16-29
public static void main(String[] args) throws URISyntaxException, InterruptedException {
IO.Options options = new IO.Options();
options.forceNew = true;
final Socket socket = IO.socket("http://localhost:8881", options);
socket.on(Socket.EVENT_CONNECT, objects -> {
System.out.println("client: " + "connect");
JSONObject jsonObject = new JSONObject();
jsonObject.put("user", "SDK");
jsonObject.put("msg", "Hello, I am a message from SDK!");
socket.emit("chat", jsonObject);
});
socket.connect();
}
Sources: zheng-message/zheng-message-sdk/src/main/java/com/zheng/message/sdk/MessageHelper.java
Configuration and Dependencies
The module's behavior and dependencies are defined in its Maven pom.xml files.
Key Dependencies
| Group ID | Artifact ID | Version | Scope | Description |
|---|---|---|---|---|
com.zheng | zheng-common | 1.0.0 | jar | Common utilities for the zheng project. |
com.corundumstudio.socketio | netty-socketio | 1.7.12.zheng | system | The core Socket.IO server implementation. |
io.socket | socket.io-client | 0.8.3 | compile | The Java client library for Socket.IO (in SDK). |
Sources: zheng-message/zheng-message-server/pom.xml, zheng-message/zheng-message-sdk/pom.xml
Embedded Server
The zheng-message-server is configured to run using the jetty-maven-plugin on port 8881.
<!-- zheng-message/zheng-message-server/pom.xml:76-78 -->
<httpConnector>
<port>8881</port>
</httpConnector>