Of course! This is a fantastic topic. Let's break down Java WebSockets and HTML5 WebSockets, covering the concepts, the technologies involved, and a complete, practical example.
The Big Picture: What are WebSockets?
Imagine a traditional website. Your browser (the client) makes a request to a server, and the server sends back a response. If the browser needs new data, it has to ask again. This is called a request-response model.
WebSockets change this. They provide a full-duplex, bidirectional communication channel over a single, long-lived TCP connection.
- Full-Duplex: Both the client and the server can send messages to each other at any time, independently.
- Persistent Connection: The connection stays open, eliminating the overhead of repeatedly opening and closing new connections (like in HTTP).
- Low Latency: Messages are pushed from the server to the client instantly, without the client having to ask first.
This is perfect for applications like:

- Chat applications
- Live notifications
- Real-time gaming
- Collaborative editing tools (like Google Docs)
- Live financial data feeds
The HTML5 Side: The Client-Side API
HTML5 introduced a standard JavaScript API for using WebSockets in the browser. This is what your web page will use to connect to the server.
Key Concepts & Methods
The API is centered around the WebSocket object.
-
Creating a Connection:
// The URL uses the 'ws://' scheme (for non-secure) or 'wss://' (for secure, like HTTPS) const socket = new WebSocket('ws://localhost:8080/my-websocket-endpoint'); -
Event Handlers: You set up functions to handle different events in the connection's lifecycle.

onopen: Fired when the connection is successfully established.onmessage: Fired when a message is received from the server.onerror: Fired when an error occurs.onclose: Fired when the connection is closed.
-
Methods:
send(data): Sends data to the server. The data can be a string,Blob, orArrayBuffer.close(): Closes the connection.
Simple HTML Client Example
Let's create a basic chat client. Save this as index.html.
<!DOCTYPE html>
<html>
<head>Java WebSocket Chat</title>
<style>
body { font-family: Arial, sans-serif; }
#chat-log {
border: 1px solid #ccc;
height: 300px;
overflow-y: scroll;
padding: 10px;
margin-bottom: 10px;
}
#input-area { display: flex; }
#message-input { flex-grow: 1; padding: 5px; }
button { padding: 5px 10px; }
</style>
</head>
<body>
<h1>Simple WebSocket Chat</h1>
<div id="chat-log"></div>
<div id="input-area">
<input type="text" id="message-input" placeholder="Type a message...">
<button id="send-button">Send</button>
</div>
<script>
// 1. Create a new WebSocket connection
const socket = new WebSocket('ws://localhost:8080/chat');
const chatLog = document.getElementById('chat-log');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
// 2. Set up event listeners
socket.onopen = function(event) {
console.log("Connection established!");
appendLog("Connected to the chat server.");
};
socket.onmessage = function(event) {
console.log("Message received from server:", event.data);
appendLog(event.data); // Display the received message
};
socket.onerror = function(error) {
console.error("WebSocket Error:", error);
appendLog("An error occurred.");
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
console.error('Connection died');
}
appendLog("Connection closed.");
};
// Function to append a message to the chat log
function appendLog(message) {
const p = document.createElement('p');
p.textContent = message;
chatLog.appendChild(p);
chatLog.scrollTop = chatLog.scrollHeight; // Auto-scroll
}
// Send a message when the button is clicked or Enter is pressed
function sendMessage() {
const message = messageInput.value;
if (message) {
console.log("Sending message to server:", message);
socket.send(message);
messageInput.value = ''; // Clear the input
}
}
sendButton.addEventListener('click', sendMessage);
messageInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>
The Java Side: The Server-Side Implementation
On the server, we need a WebSocket endpoint to listen for incoming connections. In the Java ecosystem, there are two main ways to do this:
A. The Modern Way: Jakarta WebSocket (formerly Java EE WebSocket)
This is the standard, annotation-based API. It's clean, easy to use, and supported by most Java servers (like Tomcat, WildFly, Jetty).

Key Annotations:
@ServerEndpoint: Marks a class as a WebSocket endpoint. The value is the path that clients will connect to.@OnOpen: A method that gets called when a new connection is established.@OnClose: A method that gets called when a connection is closed.@OnMessage: A method that gets called when a message is received from a client.@OnError: A method that gets called when an error occurs.
B. The Advanced Way: The Jakarta WebSocket API (Low-Level)
This gives you more control. You implement the jakarta.websocket.Endpoint interface and override its methods (onOpen, onClose, onError, onMessage). You would then configure your endpoint programmatically. For most use cases, the annotation-based approach is sufficient.
Simple Java Server Example (Using Annotations)
This example will create a simple chat server that broadcasts every received message to all connected clients.
Project Setup (Maven): You'll need the WebSocket API dependency.
<dependencies>
<!-- Jakarta WebSocket API (for the annotations) -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
<!-- You also need a WebSocket implementation, like Tyrus for testing -->
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-server</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly2-http</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
The Java Endpoint Class:
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
// This annotation marks this class as a WebSocket endpoint.
// The value is the relative URL path for the WebSocket connection.
@ServerEndpoint("/chat")
public class ChatEndpoint {
// A thread-safe Set to store all active sessions.
// We use a static Set because it's shared among all instances of this endpoint.
private static final Set<Session> chatroomUsers = Collections.synchronizedSet(new HashSet<>());
/**
* Called when a new WebSocket connection is opened.
* @param session The session for the new connection.
* @param config The configuration for this endpoint.
*/
@OnOpen
public void onOpen(Session session, EndpointConfig config) {
chatroomUsers.add(session);
System.out.println("New connection opened. Session ID: " + session.getId());
// You could broadcast a "user joined" message here if you wanted.
}
/**
* Called when a message is received from a client.
* @param message The message received from the client.
* @param session The session of the client who sent the message.
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("Message from " + session.getId() + ": " + message);
// Broadcast the received message to all connected clients.
for (Session user : chatroomUsers) {
if (user.isOpen()) {
user.getBasicRemote().sendText(message);
}
}
}
/**
* Called when a WebSocket connection is closed.
* @param session The session that is being closed.
* @
