Java WebSocket - 1.0
Description
This extension should be installed when analyzing projects containing WebSocket applications, and you want to view a transaction consisting of Client and Server objects for WebSocket communication with their corresponding links.
In what situation should you install this extension?
If your Java application uses Websocket communication APIs.
Technology support
| Library name | Package/namespace | Supported | Version supported |
|---|---|---|---|
| Java EE WebSocket | javax.websocket | ✅ | Up to 8.0 |
| Jakarta WebSocket | jakarta.websocket | ✅ | Up to 2.3.0 |
| Spring WebSocket | org.springframework.web.socket | ✅ | Up to 7.0.x |
| Spring WebFlux WebSocket | org.springframework.web.reactive | ✅ | Up to 5.0.0 |
| Jetty WebSocket Server | org.eclipse.jetty.websocket.server | ✅ | Up to 12.1.10 |
| Jetty WebSocket Client | org.eclipse.jetty.websocket.client | ✅ | Up to 12.1.10 |
| Netty | io.netty.handler.codec.http.websocketx | ✅ | Up to 4.2.15 |
| Vert.x | io.vertx | ✅ | Up to 5.1.2 |
| Undertow | io.undertow | ✅ | Up to 2.3 |
| Tyrus Server | org.glassfish.tyrus.server | ✅ | Up to 2.3.0 |
| Tyrus Client | org.glassfish.tyrus.client | ✅ | Up to 2.3.0 |
Supported Annotations
| Name | Description | Comment |
|---|---|---|
| @ServerEndpoint | jakarta.websocket.server.ServerEndpointjavax.websocket.server.ServerEndpoint | build WebSocket Server objects |
| @ClientEndpoint | jakarta.websocket.ClientEndpointjavax.websocket.ClientEndpoint | build WebSocket Client objects |
| @WebSocket | org.eclipse.jetty.websocket.api.annotations.WebSocket | indicates a Jetty WebSocket class |
| @OnOpen | jakarta.websocket.OnOpenjavax.websocket.OnOpen | decorate a Java method to indicate a new web socket session is open |
| @OnMessage | jakarta.websocket.OnMessagejavax.websocket.OnMessage | makes a Java method receive incoming web socket messages |
| @OnError | jakarta.websocket.OnErrorjavax.websocket.OnError | decorate a Java method to indicate it handle errors |
| @OnClose | jakarta.websocket.OnClosejavax.websocket.OnClose | decorate a Java method to indicate when a web socket session is closing |
| @OnWebSocketOpen | org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen | decorate a Java method to indicate a new web socket session is open in Jetty framework |
| @OnWebSocketMessage | org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage | makes a Java method receive incoming web socket messages in Jetty framework |
| @OnWebSocketError | org.eclipse.jetty.websocket.api.annotations.OnWebSocketError | decorate a Java method to indicate it handle errors in Jetty framework |
| @OnWebSocketClose | org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose | decorate a Java method to indicate when a web socket session is closing in Jetty framework |
Transactions
Transaction support is derived from metamodel concepts used to build CAST Imaging Blueprint and structural transaction flows. Entry Points start transactions; Exit Points include both output/boundary concepts and Data Entities manipulated by transactions.
| Role | Support | Breakdown |
|---|---|---|
| Entry Point | N/A | No data available |
| Exit Point | N/A | No data available |
ISO 5055 Structural Rules
Quality support is based on ISO 5055 structural rules available for the selected extension version.
| Reliability | Maintainability | Security | Performance Efficiency |
|---|---|---|---|
| N/A | N/A | N/A | N/A |
Dependencies
Some CAST extensions require the presence of other CAST extensions in order to function correctly. The Java Websocket extension requires the following CAST extensions to be installed:
- Universal Linker
- CAST AIP Internal Extension
- The Java Analyzer is required, but it is not a dependency, this extension will be automatically installed when Java source code is delivered for analysis.
Any dependent extensions are automatically downloaded and installed. You do not need to do anything.
Download and installation instructions
For Java applications using websocket libraries, the extension will be automatically installed by CAST Console. For upgrade, if the Extension Strategy is not set to Auto update, you can manually install the extension using the Application - Extensions interface.
What results can you expect?
Once the analysis/snapshot generation has completed, you can view the below objects and links created.
Objects
| Icon | Description | Comment |
|---|---|---|
![]() |
Java Server WebSocket | An object to represent server WebSocket |
![]() |
Java Client WebSocket | An object to represent client WebSocket |
![]() |
Java Unknown WebSocket Socket | An object to represent server WebSocket when URI is not resolved |
![]() |
Java Unknown Client WebSocket | An object to represent client WebSocket when URI is not resolved |
Links
| Link Type | Source and Destination Link | Supported Methods |
|---|---|---|
| callLink | From Java Server WebSocket / Java Unknown Server WebSocket to Caller Java method | JEE WebSocketjakarta.websocket.server.ServerEndpointjavax.websocket.server.ServerEndpoint jakarta.websocket.server.ServerContainer.addEndpointjavax.websocket.server.ServerContainer.addEndpoint Spring Raw WebSocketorg.springframework.web.socket.config.annotation.WebSocketHandlerRegistry.addHandlerSpring Reactive WebSocketorg.springframework.web.reactive.function.server.RequestPredicates.pathJetty WebSocketorg.eclipse.jetty.websocket.server.ServerWebSocketContainer.addMappingNetty WebSocketio.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.WebSocketServerProtocolHandlerio.netty.bootstrap.AbstractBootstrap.bind io.netty.handler.codec.http.websocketx.WebSocketServerProtocolConfig.newBuilderio.netty.handler.codec.http.websocketx.WebSocketServerProtocolConfig.Builder.websocketPath Vertx WebSocketio.vertx.ext.web.Router.routeUndertow WebSocketio.undertow.server.handlers.PathHandler.addPrefixPath |
| callLink | From Caller Java method to Java Client WebSocket / Java Unknown Client WebSocket | JEE WebSocketjavax.websocket.WebSocketContainer.connectToServerjakarta.websocket.WebSocketContainer.connectToServer Spring Raw WebSocketorg.springframework.web.socket.client.standard.StandardWebSocketClient.executeorg.springframework.web.socket.client.AbstractWebSocketClient.execute Spring Reactive WebSocketorg.springframework.web.reactive.socket.client.WebSocketClient.executeJetty WebSocketorg.eclipse.jetty.websocket.client.WebSocketClient.connectNetty WebSocketio.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory.newHandshakerVertx WebSocketio.vertx.core.http.WebSocketConnectOptions.setURIio.vertx.core.http.WebSocketConnectOptions.setHost io.vertx.core.http.WebSocketConnectOptions.setPort Undertow WebSocketio.undertow.websockets.client.WebSocketClient.connectionBuilder |
| callLink | From Java Server WebSocket to Annotated methods | JEE WebSocketjakarta.websocket.OnOpenjakarta.websocket.OnMessage jakarta.websocket.OnError jakarta.websocket.OnClose Jetty WebSocketorg.eclipse.jetty.websocket.api.annotations.OnWebSocketOpenjorg.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage org.eclipse.jetty.websocket.api.annotations.OnWebSocketError org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose |
| callLink | From Java Client WebSocket to Annotated methods | JEE WebSocketjakarta.websocket.OnOpenjakarta.websocket.OnMessage jakarta.websocket.OnError jakarta.websocket.OnClose Jetty WebSocketorg.eclipse.jetty.websocket.api.annotations.OnWebSocketOpenjorg.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage org.eclipse.jetty.websocket.api.annotations.OnWebSocketError org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose |
| callLink | From Java Client WebSocket to Java Server WebSocket | Linking is handled by Universal Linker |
Code Examples
JEE WebSocket with Tyrus Server
ChatServerEndpoint.java
package com.example;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
@ServerEndpoint("/chat")
public class ChatServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("[SERVER] OPEN: " + session.getId());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("[SERVER] RECV from " + session.getId() + ": " + message);
try {
// Echo the message back to the client
session.getBasicRemote().sendText("echo: " + message);
} catch (Exception e) {
e.printStackTrace();
}
}
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("[SERVER] CLOSE: " + session.getId() + " (" + reason + ")");
}
@OnError
public void onError(Session session, Throwable t) {
System.out.println("[SERVER] ERROR on " + session.getId());
t.printStackTrace();
}
}
JavaWsClient.java
``` java import jakarta.websocket.*; import java.net.URI;@ClientEndpoint public class JavaWsClient {
@OnOpen
public void onOpen(Session session) throws Exception {
System.out.println("connected");
session.getBasicRemote().sendText("hello server");
}
@OnMessage
public void onMessage(String message) {
System.out.println("received: " + message);
}
public static void main(String[] args) throws Exception {
// This is the client-side container:
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(
JavaWsClient.class,
URI.create("ws://localhost:8080/app/chat")
);
Thread.sleep(5000); // keep the JVM alive to receive messages
}
}
</details>
<details><summary>ServerMain.java</summary>
``` java
package com.example;
import org.glassfish.tyrus.server.Server;
import java.util.Collections;
public class ServerMain {
public static final String HOST = "localhost";
public static final int PORT = 8080;
public static final String CONTEXT_PATH = "/app";
public static void main(String[] args) throws Exception {
Server server = new Server(HOST, PORT, CONTEXT_PATH,
Collections.emptyMap(),
ChatServerEndpoint.class);
try {
server.start();
System.out.println("[SERVER] Started at ws://" + HOST + ":" + PORT
+ CONTEXT_PATH + "/chat");
System.out.println("[SERVER] Press ENTER to stop...");
System.in.read();
} finally {
server.stop();
System.out.println("[SERVER] Stopped.");
}
}
}

Jetty WebSocket
ChatServerEndpoint.java
package com.example;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@WebSocket // autoDemand = true by default
public class ChatServerEndpoint {
@OnWebSocketOpen
public void onOpen(Session session) {
System.out.println("[SERVER] OPEN: " + session.getRemoteSocketAddress());
}
@OnWebSocketMessage
public void onMessage(Session session, String message) {
System.out.println("[SERVER] RECV: " + message);
// Echo it back. The async send takes a Callback (use NOOP to ignore completion).
session.sendText("echo: " + message, Callback.NOOP);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
System.out.println("[SERVER] CLOSE: " + statusCode + " " + reason);
}
@OnWebSocketError
public void onError(Throwable cause) {
cause.printStackTrace();
}
}
JettyWsClient.java
package com.example;
import java.net.URI;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
public class JettyWsClient {
public static void main(String[] args) throws Exception {
WebSocketClient client = new WebSocketClient();
Object endpoint = new JettyWsClientEndpoint();
URI serverUri = URI.create("ws://localhost:8080/chat");
try {
client.start();
System.out.println("[CLIENT] connecting to " + serverUri);
CompletableFuture<Session> sessionPromise = client.connect(endpoint, serverUri);
sessionPromise.get(5, TimeUnit.SECONDS);
endpoint.awaitClose(5);
} finally {
client.stop();
}
System.out.println("[CLIENT] done.");
}
}
JettyWsClientEndpoint.java
package com.example;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@WebSocket
public class JettyWsClientEndpoint {
private final CountDownLatch closeLatch = new CountDownLatch(1);
@OnWebSocketOpen
public void onOpen(Session session) {
System.out.println("[CLIENT] connected");
session.sendText("hello server", Callback.NOOP); // � outgoing message
}
@OnWebSocketMessage
public void onMessage(Session session, String message) {
System.out.println("[CLIENT] received: " + message);
session.close(StatusCode.NORMAL, "done", Callback.NOOP);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
System.out.println("[CLIENT] closed: " + statusCode + " " + reason);
closeLatch.countDown();
}
@OnWebSocketError
public void onError(Throwable cause) {
cause.printStackTrace();
}
public boolean awaitClose(int seconds) throws InterruptedException {
return closeLatch.await(seconds, TimeUnit.SECONDS);
}
}
ServerMain.java
package com.example;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeHandler;
public class ServerMain {
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
WebSocketUpgradeHandler wsHandler = WebSocketUpgradeHandler.from(server);
server.setHandler(wsHandler);
wsHandler.getServerWebSocketContainer()
.addMapping("/chat",
(upgradeRequest, upgradeResponse, callback) -> new ChatServerEndpoint());
server.start();
System.out.println("[SERVER] Started at ws://localhost:8080/chat");
server.join();
}
}

Netty WebSocket
NettyWsClient.java
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import java.net.URI;
public class NettyWsClient {
private final URI serverUri;
public NettyWsClient(URI serverUri) {
this.serverUri = serverUri;
}
public void start() throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(
serverUri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders());
NettyWsClientHandler handler = new NettyWsClientHandler(handshaker);
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new NettyWsClientInitializer(handler));
Channel channel = bootstrap.connect(serverUri.getHost(), serverUri.getPort()).sync().channel();
handler.handshakeFuture().sync();
channel.writeAndFlush(new TextWebSocketFrame("Hello from config-builder client"));
Thread.sleep(1000);
channel.close().sync();
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) throws InterruptedException {
URI uri = URI.create("ws://localhost:8080/ws/chat");
new NettyWsClient(uri).start();
}
}
NettyWsServerInitializer.java
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolConfig;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
public class NettyWsServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
WebSocketServerProtocolConfig config = WebSocketServerProtocolConfig.newBuilder()
.websocketPath("/ws/chat")
.checkStartsWith(true)
.build();
ch.pipeline()
.addLast(new HttpServerCodec())
.addLast(new HttpObjectAggregator(65536))
.addLast(new WebSocketServerProtocolHandler(config))
.addLast(new NettyWsFrameHandler());
}
}




