WebSocket: a blog chat
Ordinary HTTP works as "question and answer": the client asks, the server answers, and the connection is no longer needed. That is not enough for a chat: the server must send a message by itself as soon as someone else writes it. WebSocket is a protocol for a permanent two-way connection: once connected, both the client and the server can send messages at any moment. In Javalin a WebSocket route is declared with the config.routes.ws method.
Connection events
A WebSocket handler receives a WsConfig object on which you register reactions to events:
| Event | When it happens |
|---|---|
onConnect | A client connected |
onMessage | A text message arrived, ctx.message() gives it |
onClose | The connection was closed |
onError | An error occurred |
The chat class
The chat keeps all open connections and sends every message to everyone:
// src/main/java/com/example/blog/Chat.java
package com.example.blog;
import io.javalin.websocket.WsConfig;
import io.javalin.websocket.WsContext;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class Chat {
private final Set<WsContext> sessions = ConcurrentHashMap.newKeySet();
public void configure(WsConfig ws) {
ws.onConnect(ctx -> {
sessions.add(ctx);
broadcast("Someone joined, online: " + sessions.size());
});
ws.onMessage(ctx -> broadcast(ctx.message()));
ws.onClose(ctx -> {
sessions.remove(ctx);
broadcast("Someone left, online: " + sessions.size());
});
}
private void broadcast(String text) {
for (WsContext client : sessions) {
if (client.session.isOpen()) {
client.send(text);
}
}
}
}WsContext is the context of one connection, similar to ctx in HTTP. The send method sends a string to the client; if you pass an object, Javalin turns it into JSON. A set made from ConcurrentHashMap is safe for different threads.
The route
Register the chat in Main:
// src/main/java/com/example/blog/Main.java
var chat = new Chat();
// inside Javalin.create(config -> { ... })
config.routes.ws("/chat", chat::configure);Checking it in the browser
curl cannot do WebSocket, but every browser can. Open http://localhost:8080 in two tabs, open the developer console (F12) in each and run:
const ws = new WebSocket("ws://localhost:8080/chat");
ws.onmessage = e => console.log("Received:", e.data);The address starts with ws:// instead of http://. In the second tab send a message with ws.send("Hi, Anna!"). Both tabs show:
Received: Someone joined, online: 1
Received: Someone joined, online: 2
Received: Hi, Anna!
The first line appears only in the first tab: it connected while it was alone. Close one tab, and the remaining one receives Someone left, online: 1.
Common mistake
A WebSocket route does not answer ordinary HTTP requests. If you open its address in a browser or call curl, you get 404:
curl -i http://localhost:8080/chatHTTP/1.1 404 Not Found
Content-Type: text/plain
Endpoint GET /chat not found
Connect to it only with a WebSocket client and with an address using the ws:// scheme (or wss:// for HTTPS).