WebSockets

WebSocket handlers enable bi-directional real-time communication between client and server. Perfect for chat applications, live collaboration, and gaming.

Basic WebSocket handler
@org.eclipse.jetty.websocket.api.annotations.WebSocket
@WebSocket("/ws/chat")
public class ChatHandler {

    private static final Map<Session, String> users = new ConcurrentHashMap<>();

    @OnWebSocketConnect
    public void onConnect(Session session) throws IOException {
        users.put(session, "anonymous");
        session.getRemote().sendString("Welcome to the chat!");
    }

    @OnWebSocketMessage
    public void onMessage(Session session, String message) throws IOException {
        for (Session s : users.keySet()) {
            if (s.isOpen()) {
                s.getRemote().sendString(message);
            }
        }
    }

    @OnWebSocketClose
    public void onClose(Session session, int code, String reason) {
        users.remove(session);
    }
}
Client-side JavaScript
const ws = new WebSocket('ws://localhost:8080/ws/chat');

ws.onopen = () => {
    ws.send('Hello server!');
};

ws.onmessage = (event) => {
    console.log('Received:', event.data);
};

ws.onclose = () => {
    console.log('Disconnected');
};
Path convention

Use the /ws/ prefix for WebSocket endpoints to avoid conflicts with HTTP routes.

// ✅ No conflict
@WebSocket("/ws/chat")  // WebSocket endpoint
@GET("/chat")           // HTTP route (serves the HTML page)

// ❌ Conflict
@WebSocket("/chat")     // Conflicts with HTTP route below
@GET("/chat")
💡 Important

WebSocket handlers require both annotations and must be placed in a subpackage of your main package (e.g. websockets/):

  • @WebSocket("/path") — Obsidian annotation
  • @org.eclipse.jetty.websocket.api.annotations.WebSocket — Jetty annotation