Finished writing the WebSocket chapter for the second edition of my Java 24 Hour Trainer. In this blog I’ll show you one of the code samples from lesson 28.

Pretty often you need to write a program that publishes the same message to all connected clients. For example, multiple clients of the online auctions have to be notified when a new bid is placed on the product. Another example is when a new stock price quote need to be pushed from the server to all connected clients. With websockets it’s a pretty easy task.

I’ll show you a basic example when a WebSocket endpoint pushes the server’s time to all connected clients. If you can publish the server’s time to all connected clients, you can publish any application-specific data.

The following endpoint WebSocketClock schedules the task that gets and formats the server’s time every second and publishes the time to all connected clients. I schedule this timer once when the first client connects to our endpoint. The method sendTimeToAll() finds all connected clients by invoking getOpenSessions() on the Session object. Then on each session it calls getBasicRemote().sendText().

@ServerEndpoint("/clock") public class WebSocketClock { static ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(); private static Set<Session> allSessions; DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); @OnOpen public void showTime(Session session){ allSessions = session.getOpenSessions(); // start the scheduler on the very first connection // to call sendTimeToAll every second if (allSessions.size()==1){ timer.scheduleAtFixedRate( () -> sendTimeToAll(session),0,1,TimeUnit.SECONDS); } } private void sendTimeToAll(Session session){ allSessions = session.getOpenSessions(); for (Session sess: allSessions){ try{ sess.getBasicRemote().sendText("Local time: " + LocalTime.now().format(timeFormatter)); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } } }

The Web client is pretty simple. On the page load the JavaScript code connects to the WebSocket endpoint on the server. The callback onMessage() is invoked when the message (current time) arrives. In this callback I update the content of the span HTML element with the current time. Since my Java code will send the message every second, the span content updates with this frequency. No page refreshes, no heavy HTTP headers, no AJAX long polling hacks either.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <span id="messageGoesHere"></span> <script type="text/javascript"> var ws = new WebSocket("ws://localhost:8080/Lesson28/clock"); ws.onmessage = function(event) { var mySpan = document.getElementById("messageGoesHere"); mySpan.innerHTML=event.data; }; ws.onerror = function(event){ console.log("Error ", event) } </script> </body> </html>

The next screenshot shows how Eclipse internal browser, Chrome, and Firefox display the current time published by my WebSocket endpoint.

Three Web clients get current time published by a WebSocket endpoint every second.

Iterating through all open sessions works fine if the number of connected clients is small. But if you have hundreds of clients, consider grouping the Session objects into separate collections in @OnOpen message handler, and sending messages to each group in parallel from multiple threads. Important: by default, a Java EE server creates a new instance of the server endpoint class for each client’s connection, so if you’ll be creating your own session collections they must be static:

private static Set<Session> sessionsChunk1 = Collections.synchronizedSet(new HashSet<>()); private static Set<Session> sessionsChunk2 = Collections.synchronizedSet(new HashSet<>());