Java EE HTML5 WebSockets with multiple clients example
Introduction
In the previous tutorial - Java EE HTML5 WebSocket example - we have implemented a simple Java EE WebSockets enabled application where the client sent a simple message to the server over a websocket and then received a sequence of responses from the server over the same channel.
In this tutorial we will implement an application where clients will interactively send messages to each other through the server. This way we will have an application where clients are in fact publishing and receiving events to/from the server over HTML5 websockets.
This tutorial considers the following environment:
- Ubuntu 12.04
- JDK 1.7.0.21
- Glassfish 4.0
WebSocket server endpoint
Let's define a Java EE websocket server endpoint:
package com.byteslounge.websockets; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketTest { private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>()); @OnMessage public void onMessage(String message, Session session) throws IOException { synchronized(clients){ // Iterate over the connected sessions // and broadcast the received message for(Session client : clients){ if (!client.equals(session)){ client.getBasicRemote().sendText(message); } } } } @OnOpen public void onOpen (Session session) { // Add session to the connected sessions set clients.add(session); } @OnClose public void onClose (Session session) { // Remove session from the connected sessions set clients.remove(session); } }
Similarly to what we have done in the previous tutorial - Java EE HTML5 WebSocket example - we are defining a ServerEndpoint that will be - as the name states - the server endpoint listening from client websocket connections.
We have a static Map that will hold all connected client sessions. This way we may broadcast received messages to other clients (method onMessage). Note that when we receive a message we broadcast it to all connected clients except the one who originated the message in the first place.
Methods onOpen and onClose are called when a client connects or disconnects from the server endpoint respectively. So we add or remove them from the sessions Map accordingly.
Note that when the parameter of type Session is included in the annotated ServerEndpoint methods the container will inject the session that corresponds to the client which originated the event.
Client side
Now we need to write the client-side of our websocket test application:
<!DOCTYPE html> <html> <head> <title>Testing websockets</title> </head> <body> <div> <input id="inputmessage" type="text" /> </div> <div> <input type="submit" value="Broadcast message" onclick="send()" /> </div> <div id="messages"></div> <script type="text/javascript"> var webSocket = new WebSocket('ws://localhost:8080/byteslounge/websocket'); webSocket.onerror = function(event) { onError(event) }; webSocket.onopen = function(event) { onOpen(event) }; webSocket.onmessage = function(event) { onMessage(event) }; function onMessage(event) { document.getElementById('messages').innerHTML += '<br />Received message: ' + event.data; } function onOpen(event) { document.getElementById('messages').innerHTML = 'Connection established'; } function onError(event) { alert(event.data); } function send() { var txt = document.getElementById('inputmessage').value; webSocket.send(txt); return false; } </script> </body> </html>
This page contains a simple input text where a user may write a message and a button to publish the message to the server over the established websocket channel.
Every time we receive a message from the server we write it into the page.
For more information about the websocket connection definition and the respective events please refer to Java EE HTML5 WebSocket example.
Testing
We may now test our application by accessing the testing page from two distinct web browser instances:
http://localhost:8080/byteslounge/page.html
We will see the Connection established message as expected:
Now we write a simple message (ex: "hello") in one of the clients and click the "Broadcast message" button:
The other connected client will receive the published message. Note that the message will be published to every connected client except the one who published the message in the first place (as we defined in the server endpoint):
Conclusion
We have developed a sample application where clients use websockets in full extent to communicate with a Java EE application server, ie. publishing and receiving events.
In our case the received events are sent by other clients. One can easily use a similar approach to enable periodic message sending from server to clients in order to notify them of some arbitrary event occurrence.
Downloadable sample
The example source code is available for download at the end of this page. The test was executed in Glassfish 4 (you will need a Java EE 7 compliant application server).