SockJS - WebSocket support
Introduction
SockJS is a browser/server communication framework designed to provide a WebSocket-like programming model when native WebSocket support is unavailable or unreliable. SockJS isn’t supported as a standalone library. It’s only recognised as the transport behind a STOMP client, through StompOverSockJS. This extension supports the following WebSocket libraries:
- @stomp/stompjs npm — STOMP over WebSocket library for browsers and Node.js.
- @stomp/rx-stomp npm — An RxJS-friendly STOMP-over-WebSocket client for the Web and Node.js.
- sockjs-client SockJS client implementation.
Objects
| Icon | Metamodel name | Description |
|---|---|---|
![]() |
TypeScript WebSocket Client | Represents a WebSocket client connection identified by its URL |
Links
| Link type | From | To | Created when |
|---|---|---|---|
callLink |
TypeScript Function / Method | TypeScript WebSocket Client | A function calls send() on a client connection — see filtering rule below |
callLink |
TypeScript WebSocket Client | TypeScript Function / Method | A handler is registered on the client |
Send links — semantic meaning
A send link (callLink from a function to a WebSocket object) represents that the function
actively pushes data to a WebSocket peer. In the call graph this makes the function a caller of
the WebSocket server or client object, complementing the callee links that already show which
functions receive messages from it.
Send link is created:
- Function → WebSocket Client: the function sends a message over an outbound client connection
(e.g.
client.publish({...})called from application code that is not itself a message handler).
Supported API methods
stomp/stompjs library
Client side
| API method | Object created / linked | Link type |
|---|---|---|
new Client({ webSocketFactory: () => new SockJS(url) }) (@stomp/stompjs) |
TypeScript WebSocket Client | — |
onConnect handler |
linked as callee of client | callLink |
onDisconnect handler |
linked as callee of client | callLink |
onStompError handler |
linked as callee of client | callLink |
onWebSocketError handler |
linked as callee of client | callLink |
onWebSocketClose handler |
linked as callee of client | callLink |
onUnhandledMessage handler |
linked as callee of client | callLink |
onUnhandledReceipt handler |
linked as callee of client | callLink |
onUnhandledFrame handler |
linked as callee of client | callLink |
stomp/rx-stomp package
Client side
| API method | Object created / linked | Link type |
|---|---|---|
| `new RxStomp() + rxStomp.configure({ webSocketFactory | brokerURL, … }) (@stomp/rx-stomp)` | TypeScript WebSocket Client |
stompErrors |
linked as callee of client | callLink |
webSocketErrors |
linked as callee of client | callLink |
unhandledMessage |
linked as callee of client | callLink |
unhandledReceipts |
linked as callee of client | callLink |
unhandledFrame |
linked as callee of client | callLink |
Example
When analyzing the following file
stomp-client.ts
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';
let chatSub = null;
// Client docs: https://stomp-js.github.io/api-docs/latest/classes/Client.html
const client = new Client({
// Use webSocketFactory (NOT brokerURL) when going through SockJS.
// It must return a WebSocket-like object synchronously; SockJS uses http(s)://
webSocketFactory: () => new SockJS('http://localhost:8080/stomp'),
connectHeaders: {
// login: 'guest', passcode: 'guest',
},
// Client.debug — verbose frame logging; remove in production
debug: (msg) => console.debug('[STOMP]', msg),
// Client.reconnectDelay — 0 disables automatic reconnect
reconnectDelay: 5000,
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000,
// Fired after the CONNECTED frame. Always (re)subscribe here so that
// subscriptions are restored after an automatic reconnect.
onConnect: (frame) => {
console.log('Connected:', frame.headers['server']);
chatSub = client.subscribe(
'/topic/chat',
(message) => {
const payload = JSON.parse(message.body);
console.log(`${payload.from}: ${payload.text}`);
// message.ack() / message.nack() if you subscribe with ack: 'client'
},
{ id: 'chat-sub' } // optional stable subscription id
);
sendChat('alice', 'hello from the browser 👋');
},
onStompError: (frame) => {
// Broker-level ERROR frame; connection is about to be closed
console.error('Broker error:', frame.headers['message'], frame.body);
},
onWebSocketError: (evt) => console.error('WebSocket error', evt),
onWebSocketClose: (evt) => console.warn('WebSocket closed', evt.code),
onDisconnect: () => console.log('Disconnected (RECEIPT for DISCONNECT)'),
});
export function sendChat(from, text) {
if (!client.connected) {
console.warn('Not connected yet');
return;
}
client.publish({
destination: '/app/chat',
body: JSON.stringify({ from, text }),
headers: { 'content-type': 'application/json' },
});
}
export async function stop() {
chatSub?.unsubscribe();
await client.deactivate(); // graceful DISCONNECT + close; stops reconnects
}
client.activate(); // starts connecting and keeps retrying per reconnectDelay
you will get the following result:

