Using The Java Api For Websocket To Create A Chat Server
Save up to a workweek a year by efficiently managing your dev bookmarks, on www.bookmarks.dev.
Share your favorites with the community and they will be published on Github
In a previous post, I’ve used Server Sent Events to create a monitoring dashboard. SSE are a one way messaging format form server to clients
in contrast to Web Sockets where communication is bidirectional. In this post, I’ll use Web sockets to create a tiny chat server using Tyrus, the reference
implementation of the Java API for WebSocket (JSR 356). A great introduction to this API can be found on Oracle Network here.
In order to keep the tutorial simple, the server and clients will be command line apps, no GUIs here, it is a serious blog :smile: So let’s get started!
A quick introduction to the Java API for WebSocket
If you don’t have time to check all details of this API, here are the most important points to know. JSR 356 provides:
both a programmatic and a declarative way to define client and server endpoints. In this post, I’ll use the declarative way, through annotations.
lifecyle events to which we can listen: open/close a session, send/receive a message, etc
message encoder/decoder to marshal/unmarshall (binary or character) messages between clients and servers.
Encoders/Decorders are important since they allow us to use Java objects as messages instead of dealing with raw data that transit over the wire. We will see an example in a couple of minutes
That’s all we need to know for now in order to implement the chat application.
The data model
Since we will be creating a chat server, let’s first model messages with a POJO:
Messages will be encoded/decoded to JSON format between the server and clients using the following Encoder/Decoder classes:
That’s all for the data model, we have created our domain model object Message, and two utility classes to serialize/deserialize messages to/from JSON format.
The server side
The following is the code of the server endpoint. I’ll explain it in details right after the listing:
The code is self explanatory, but here are important points to note:
The ServerEndpoint annotation marks the class as a server endpoint. We need to specify the web socket endpoint as well as message encoder/decoder.
We need to hold a set of connected users in order to broadcast messages to chat rooms
All lifecycle event methods have a Session parameter that allows to get a handle of the user that initiated the action (join/leave/message)
MessageEncoder and MessageDecoder are used to marshal/unmarshal messages from JSON to our Message class. This is what allows us to have a parameter of type
Message in the onMessage method. Without these encoder/decoder classes, we need to handle raw text messages..
That’s all for the server side, nothing fancy :smile:
The client side
On the client side, we need to listen to the onMessage event and print the received message to the console:
Putting it all together
Now that we have defined the data model, client and server endpoints, we can proceed with a final main class to run the application.
The main class to run the server is the following:
All we have to do is create a org.glassfish.tyrus.server.Server instance and start it.
We should specify the ServerEndpoint class, the port and the websocket endpoint as parameters.
To create a client, I’ll use the following class:
The ClientManager provided by JSR 356 is the entry point to create clients.
Once we get a client, it is possible to connect to the server and obtain a Session object. This is the main point of interaction between server and clients.
It allows to send messages, register handlers and get/set sessions parameters.
The complete source code of the tutorial can be found here.
In this lab, I’ve created an example with one server and two clients.
In this post, we have seen how easy is to create a chat application using the Java API for WebSocket (JSR 356).
This API has been added in Java EE 7 and greatly simplify the programming model of real-time interactive applications.
Note that I’ve used only reference implementations of Java EE APIs, without using a container, nor third party APIs or libraries.
If only I meet one of those guys that say Java EE is heavy :rage:
I must admit that the Java API is also really great, easy and straightforward.
I hope you enjoyed this article. Time to get your hands dirty..