Skip to main content

Introduction

The Justina Backend provides WebSocket endpoints for real-time bidirectional communication between clients and the server. WebSockets enable:
  • Live telemetry streaming from surgical simulations
  • Instant notifications to AI systems when surgeries complete
  • Low-latency data transfer for responsive user experiences

WebSocket Base URL

All WebSocket connections are established at:
ws://localhost:8080/ws/{endpoint}
For secure connections (recommended in production):
wss://your-domain.com/ws/{endpoint}

Available Channels

EndpointPurposeRequired Role
/ws/simulationStream surgical telemetry data in real-timeROLE_SURGEON
/ws/aiReceive surgery completion notificationsROLE_AI

Authentication

WebSocket connections require JWT authentication via query parameter:
ws://localhost:8080/ws/simulation?token=<your-jwt-token>

Why Query Parameters?

Unlike HTTP requests, WebSocket handshakes don’t easily support custom headers. The token is passed as a query parameter and validated during the handshake phase before the connection is established.

Authentication Flow

1

Extract Token

Parse token parameter from WebSocket URL query string
2

Validate JWT

Verify token signature, expiration, and issuer
3

Extract Claims

Retrieve userId, username, and role from token payload
4

Store Attributes

Save user information in WebSocket session attributes:
  • SURGEON_ID - User’s UUID
  • USERNAME - User’s username
  • ROLE - User’s role (ROLE_SURGEON or ROLE_AI)
5

Authorize Connection

Allow connection if token is valid, reject otherwise

Connection Examples

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';

// Connect to simulation channel
const simulationWs = new WebSocket(
  `ws://localhost:8080/ws/simulation?token=${token}`
);

simulationWs.onopen = () => {
  console.log('Connected to simulation channel');
};

simulationWs.onerror = (error) => {
  console.error('WebSocket error:', error);
};

simulationWs.onclose = (event) => {
  console.log('Connection closed:', event.code, event.reason);
};

Connection Security

Token Validation

Expired or invalid tokens result in immediate connection rejection with POLICY_VIOLATION status.
The handshake interceptor validates:
  • Token signature (HMAC-SHA256)
  • Token expiration (24-hour validity)
  • Token issuer (Justina_Backend)
  • Required claims (userId, role)

Role-Based Access

Connections are restricted by role:
  • /ws/simulation - Only ROLE_SURGEON can connect
  • /ws/ai - Only ROLE_AI can connect
Attempting to connect to a channel without the required role results in POLICY_VIOLATION closure.

WebSocket Close Status Codes

CodeReasonDescription
1000Normal ClosureConnection closed cleanly
1002Protocol ErrorWebSocket protocol violation
1003Bad DataInvalid message format (e.g., malformed JSON)
1008Policy ViolationAuthentication failure or insufficient permissions
1011Internal ErrorServer-side error during message processing

Message Format

All WebSocket messages use JSON format. Each channel has specific message schemas:

Simulation Channel

See Simulation Channel for telemetry message formats.

AI Channel

See AI Channel for notification message formats.

Connection Lifecycle

1

Handshake

Client initiates connection with JWT token in query parameter
2

Authentication

Server validates token and extracts user information
3

Connection Established

WebSocket connection is opened if authentication succeeds
4

Message Exchange

Client and server exchange JSON messages bidirectionally
5

Closure

Either party can close the connection gracefully

Error Handling

Authentication Errors

const ws = new WebSocket('ws://localhost:8080/ws/simulation?token=invalid');

ws.onclose = (event) => {
  if (event.code === 1008) {
    console.error('Authentication failed: Invalid or expired token');
    // Redirect to login or refresh token
  }
};

Message Validation Errors

ws.onclose = (event) => {
  if (event.code === 1003) {
    console.error('Bad data sent: Message validation failed');
    // Check message format and required fields
  }
};

Best Practices

1

Handle Reconnection

Implement automatic reconnection logic with exponential backoff
2

Validate Messages

Ensure all outgoing messages match the expected JSON schema
3

Monitor Connection State

Track connection status and notify users of disconnections
4

Secure Tokens

Never log or expose JWT tokens in error messages
5

Use WSS in Production

Always use wss:// (WebSocket Secure) over HTTPS domains

CORS Configuration

WebSocket endpoints allow connections from all origins (*). For production deployments, configure specific allowed origins in WebSocketConfig.java:
registry.addHandler(simulationHandler, "/ws/simulation")
    .addInterceptors(handshakeInterceptor)
    .setAllowedOrigins("https://your-frontend-domain.com");

Troubleshooting

Connection Immediately Closes

Cause: Invalid or missing JWT token Solution: Verify token is included in URL and hasn’t expired

”POLICY_VIOLATION” Error

Cause: Insufficient role permissions or authentication failure Solution: Ensure token has the correct role for the channel

Message Not Received

Cause: Invalid JSON format or missing required fields Solution: Validate message structure against channel documentation

Next Steps

Simulation Channel

Stream telemetry data from surgical simulations

AI Channel

Receive real-time surgery completion notifications

Build docs developers (and LLMs) love