Introduction to WebSocket in Java: From Theory to Real-Time Applications
Modern web applications increasingly require instant data exchange between client and server. Traditional HTTP with its "request-response" model is poorly suited for tasks requiring constant connection: online chats, stock quotes, multiplayer games, or monitoring dashboards. This is where the WebSocket protocol comes to the rescue, establishing a permanent bidirectional connection. In this article, we'll explore how to implement WebSocket in Java, create a simple chat server and client, and discuss best practices for a production environment.
What is WebSocket and Why Java?
WebSocket is a protocol operating over TCP that allows real-time message exchange without the overhead of HTTP headers. After the handshake (upgrade from HTTP to WebSocket), the server and client can send data to each other at any time. Java is an excellent choice for implementing WebSocket due to:
- Built-in support in Jakarta EE (formerly Java EE) via JSR 356.
- High performance and multithreading.
- Ecosystem of frameworks (Spring, Netty, Tyrus) that simplify development.
Unlike polling and SSE (Server-Sent Events), WebSocket provides full-duplex communication without delays.
Architecture of a WebSocket Application in Java
A typical real-time application in Java includes three components:
- WebSocket server — accepts connections, manages sessions, processes incoming messages.
- WebSocket client — a browser (JavaScript) or a native Java application that initiates the connection.
- Business logic — message processing, broadcast, database persistence.
Let's look at implementing the server using Jakarta WebSocket annotations and a client in JavaScript.
Server Side: @ServerEndpoint Annotations
To create a server, simply add the jakarta.websocket-api dependency (or javax.websocket-api for older versions). Example of a simple echo server:
import jakarta.websocket.*;import jakarta.websocket.server.ServerEndpoint;import java.io.IOException;
@ServerEndpoint("/echo")public class EchoEndpoint {
@OnOpen public void onOpen(Session session) { System.out.println("New connection: " + session.getId()); }
@OnMessage public void onMessage(String message, Session session) throws IOException { System.out.println("Received: " + message); // Send back (echo) session.getBasicRemote().sendText("Echo: " + message); }
@OnClose public void onClose(Session session, CloseReason reason) { System.out.println("Connection closed: " + reason.getReasonPhrase()); }
@OnError public void onError(Session session, Throwable error) { error.printStackTrace(); }}The server is deployed in any Servlet container (Tomcat, Jetty, GlassFish). For Spring Boot, use @ServerEndpoint together with SpringBootApplication.
Client Side: JavaScript
The browser client connects via the standard WebSocket API:
const socket = new WebSocket("ws://localhost:8080/echo");
socket.onopen = function(event) { console.log("Connection established"); socket.send("Hello, server!");};
socket.onmessage = function(event) { console.log("Message from server: " + event.data);};
socket.onclose = function(event) { console.log("Connection closed");};Note that the URL starts with ws:// (or wss:// for a secure connection).
Creating a Real-Time Chat in Java
Now let's build a full