or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-support.mdconfiguration.mdcore-websocket-api.mdhandler-framework.mdindex.mdmessage-types.mdserver-integration.mdsockjs-support.mdstomp-messaging.md

sockjs-support.mddocs/

0

# SockJS Support

1

2

SockJS fallback support providing WebSocket-like object in browsers that don't support WebSocket natively, with multiple transport options.

3

4

## Capabilities

5

6

### SockJS Service Interface

7

8

Main contract for processing SockJS HTTP requests with fallback transport support.

9

10

```java { .api }

11

/**

12

* Main contract for processing SockJS HTTP requests.

13

* Handles protocol negotiation and transport selection for SockJS connections.

14

*/

15

interface SockJsService {

16

/**

17

* Handle SockJS request with appropriate transport.

18

* @param request HTTP request

19

* @param response HTTP response

20

* @param sockJsPath SockJS endpoint path

21

* @param webSocketHandler WebSocket handler for the connection

22

* @throws SockJsException if request processing fails

23

*/

24

void handleRequest(

25

ServerHttpRequest request,

26

ServerHttpResponse response,

27

String sockJsPath,

28

WebSocketHandler webSocketHandler

29

) throws SockJsException;

30

31

/**

32

* Get the welcome message for info requests.

33

* @return welcome message string

34

*/

35

String getWelcomeMessage();

36

37

/**

38

* Check if origin validation is enabled.

39

* @return true if origin validation is enabled

40

*/

41

boolean getAllowedOrigins();

42

}

43

```

44

45

### Transport Types

46

47

Enumeration of available SockJS transport types for fallback scenarios.

48

49

```java { .api }

50

/**

51

* Enumeration of SockJS transport types.

52

* Provides different fallback mechanisms for WebSocket connections.

53

*/

54

enum TransportType {

55

/**

56

* Native WebSocket transport (preferred).

57

*/

58

WEBSOCKET,

59

60

/**

61

* XMLHttpRequest transport for sending data.

62

*/

63

XHR,

64

65

/**

66

* XMLHttpRequest send transport for one-way data sending.

67

*/

68

XHR_SEND,

69

70

/**

71

* XMLHttpRequest streaming transport for real-time data.

72

*/

73

XHR_STREAMING,

74

75

/**

76

* Server-Sent Events transport for real-time data.

77

*/

78

EVENT_SOURCE,

79

80

/**

81

* HTML file transport using hidden iframe.

82

*/

83

HTML_FILE;

84

85

/**

86

* Get the transport type from string value.

87

* @param value string representation of transport type

88

* @return corresponding TransportType

89

*/

90

public static TransportType fromValue(String value);

91

92

/**

93

* Get the string value of this transport type.

94

* @return string representation

95

*/

96

public String value();

97

98

/**

99

* Get the HTTP method used by this transport.

100

* @return HTTP method (GET or POST)

101

*/

102

public HttpMethod getHttpMethod();

103

104

/**

105

* Check if this transport sends no-cache instructions.

106

* @return true if no-cache headers are sent

107

*/

108

public boolean sendsNoCacheInstruction();

109

110

/**

111

* Check if this transport sends session cookies.

112

* @return true if session cookies are sent

113

*/

114

public boolean sendsSessionCookie();

115

116

/**

117

* Check if this transport supports CORS.

118

* @return true if CORS is supported

119

*/

120

public boolean supportsCors();

121

122

/**

123

* Check if this transport supports Origin header.

124

* @return true if Origin header is supported

125

*/

126

public boolean supportsOrigin();

127

}

128

```

129

130

### SockJS Session Interface

131

132

SockJS session abstraction extending WebSocketSession with SockJS-specific features.

133

134

```java { .api }

135

/**

136

* SockJS session abstraction extending WebSocketSession.

137

* Provides SockJS-specific session management and transport handling.

138

*/

139

interface SockJsSession extends WebSocketSession {

140

/**

141

* Get the unique session identifier.

142

* @return session ID

143

*/

144

String getId();

145

146

/**

147

* Close the SockJS session.

148

* @throws IOException if closing fails

149

*/

150

void close() throws IOException;

151

152

/**

153

* Close the SockJS session with specific status.

154

* @param status close status

155

* @throws IOException if closing fails

156

*/

157

void close(CloseStatus status) throws IOException;

158

}

159

```

160

161

### SockJS Configuration

162

163

Configuration interfaces and classes for customizing SockJS behavior.

164

165

```java { .api }

166

/**

167

* Configuration interface for SockJS services.

168

* Provides settings for timeouts, limits, and transport options.

169

*/

170

interface SockJsServiceConfig {

171

/**

172

* Get the streaming bytes limit before reconnection.

173

* @return bytes limit for streaming transports

174

*/

175

int getStreamBytesLimit();

176

177

/**

178

* Get the heartbeat interval in milliseconds.

179

* @return heartbeat time

180

*/

181

long getHeartbeatTime();

182

183

/**

184

* Get the task scheduler for SockJS operations.

185

* @return task scheduler instance

186

*/

187

TaskScheduler getTaskScheduler();

188

189

/**

190

* Get the message codec for frame encoding/decoding.

191

* @return message codec instance

192

*/

193

MessageCodec getMessageCodec();

194

}

195

196

/**

197

* Factory interface for creating SockJS sessions.

198

*/

199

interface SockJsSessionFactory {

200

/**

201

* Create a new SockJS session.

202

* @param sessionId unique session identifier

203

* @param handler WebSocket handler for the session

204

* @param attributes session attributes

205

* @return new SockJS session instance

206

*/

207

SockJsSession createSession(

208

String sessionId,

209

WebSocketHandler handler,

210

Map<String, Object> attributes

211

);

212

}

213

```

214

215

### Default SockJS Service

216

217

Default implementation of SockJS service with pre-configured transport handlers.

218

219

```java { .api }

220

/**

221

* Default SockJS service implementation with pre-configured transports.

222

* Supports all standard SockJS transport types.

223

*/

224

class DefaultSockJsService extends AbstractSockJsService {

225

/**

226

* Create default SockJS service with task scheduler.

227

* @param scheduler task scheduler for SockJS operations

228

*/

229

public DefaultSockJsService(TaskScheduler scheduler);

230

231

/**

232

* Set whether to enable WebSocket transport.

233

* @param webSocketEnabled true to enable WebSocket

234

*/

235

public void setWebSocketEnabled(boolean webSocketEnabled);

236

237

/**

238

* Check if WebSocket transport is enabled.

239

* @return true if WebSocket is enabled

240

*/

241

public boolean isWebSocketEnabled();

242

243

/**

244

* Set the session cookie needed indicator.

245

* @param sessionCookieNeeded true if session cookie is needed

246

*/

247

public void setSessionCookieNeeded(boolean sessionCookieNeeded);

248

249

/**

250

* Check if session cookie is needed.

251

* @return true if session cookie is needed

252

*/

253

public boolean isSessionCookieNeeded();

254

255

/**

256

* Set the heartbeat time in milliseconds.

257

* @param heartbeatTime heartbeat interval

258

*/

259

public void setHeartbeatTime(long heartbeatTime);

260

261

/**

262

* Get the heartbeat time.

263

* @return heartbeat interval in milliseconds

264

*/

265

public long getHeartbeatTime();

266

267

/**

268

* Set the disconnect delay in milliseconds.

269

* @param disconnectDelay delay before closing inactive sessions

270

*/

271

public void setDisconnectDelay(long disconnectDelay);

272

273

/**

274

* Get the disconnect delay.

275

* @return disconnect delay in milliseconds

276

*/

277

public long getDisconnectDelay();

278

279

/**

280

* Set the streaming bytes limit.

281

* @param streamBytesLimit bytes limit for streaming transports

282

*/

283

public void setStreamBytesLimit(int streamBytesLimit);

284

285

/**

286

* Get the streaming bytes limit.

287

* @return bytes limit for streaming transports

288

*/

289

public int getStreamBytesLimit();

290

}

291

```

292

293

**Usage Example:**

294

295

```java

296

@Configuration

297

@EnableWebSocket

298

public class SockJsConfig implements WebSocketConfigurer {

299

300

@Bean

301

public TaskScheduler sockJsTaskScheduler() {

302

ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();

303

scheduler.setPoolSize(10);

304

scheduler.setThreadNamePrefix("SockJS-");

305

scheduler.initialize();

306

return scheduler;

307

}

308

309

@Override

310

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

311

// Register handler with SockJS support

312

registry.addHandler(new ChatWebSocketHandler(), "/chat")

313

.withSockJS()

314

.setHeartbeatTime(25000) // 25 second heartbeat

315

.setDisconnectDelay(5000) // 5 second disconnect delay

316

.setStreamBytesLimit(128 * 1024) // 128KB streaming limit

317

.setSessionCookieNeeded(false) // No session cookie required

318

.setClientLibraryUrl("https://cdn.jsdelivr.net/npm/sockjs-client@1.6.1/dist/sockjs.min.js")

319

.setTransportHandlers(customTransportHandlers())

320

.setAllowedOrigins("*");

321

}

322

323

private List<TransportHandler> customTransportHandlers() {

324

List<TransportHandler> handlers = new ArrayList<>();

325

326

// Enable/disable specific transports

327

handlers.add(new WebSocketTransportHandler(handshakeHandler()));

328

handlers.add(new XhrPollingTransportHandler());

329

handlers.add(new XhrStreamingTransportHandler());

330

handlers.add(new JsonpPollingTransportHandler());

331

handlers.add(new EventSourceTransportHandler());

332

handlers.add(new HtmlFileTransportHandler());

333

334

return handlers;

335

}

336

337

@Bean

338

public DefaultSockJsService sockJsService() {

339

DefaultSockJsService service = new DefaultSockJsService(sockJsTaskScheduler());

340

341

service.setWebSocketEnabled(true);

342

service.setHeartbeatTime(25000);

343

service.setDisconnectDelay(5000);

344

service.setStreamBytesLimit(128 * 1024);

345

service.setSessionCookieNeeded(false);

346

347

return service;

348

}

349

}

350

```

351

352

### SockJS Transport Handlers

353

354

Transport handler implementations for different SockJS transport types.

355

356

```java { .api }

357

/**

358

* Contract for handling SockJS transport requests.

359

* Implementations handle specific transport protocols.

360

*/

361

interface TransportHandler {

362

/**

363

* Get the transport type handled by this handler.

364

* @return transport type

365

*/

366

TransportType getTransportType();

367

368

/**

369

* Check if the handler supports the given session type.

370

* @param session SockJS session

371

* @return true if session type is supported

372

*/

373

boolean checkSessionType(SockJsSession session);

374

375

/**

376

* Handle transport request.

377

* @param request HTTP request

378

* @param response HTTP response

379

* @param webSocketHandler WebSocket handler

380

* @param sockJsSession SockJS session

381

* @throws SockJsException if handling fails

382

*/

383

void handleRequest(

384

ServerHttpRequest request,

385

ServerHttpResponse response,

386

WebSocketHandler webSocketHandler,

387

SockJsSession sockJsSession

388

) throws SockJsException;

389

}

390

391

/**

392

* Transport handler for WebSocket transport.

393

*/

394

class WebSocketTransportHandler implements TransportHandler {

395

/**

396

* Create WebSocket transport handler.

397

* @param handshakeHandler handshake handler for WebSocket upgrade

398

*/

399

public WebSocketTransportHandler(HandshakeHandler handshakeHandler);

400

}

401

402

/**

403

* Transport handler for XHR polling.

404

*/

405

class XhrPollingTransportHandler extends AbstractHttpSendingTransportHandler {

406

public XhrPollingTransportHandler();

407

}

408

409

/**

410

* Transport handler for XHR streaming.

411

*/

412

class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHandler {

413

public XhrStreamingTransportHandler();

414

}

415

416

/**

417

* Transport handler for Server-Sent Events.

418

*/

419

class EventSourceTransportHandler extends AbstractHttpSendingTransportHandler {

420

public EventSourceTransportHandler();

421

}

422

423

/**

424

* Transport handler for HTML file transport.

425

*/

426

class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandler {

427

public HtmlFileTransportHandler();

428

}

429

430

/**

431

* Transport handler for JSONP polling.

432

*/

433

class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHandler {

434

public JsonpPollingTransportHandler();

435

}

436

437

/**

438

* Transport handler for receiving XHR messages.

439

*/

440

class XhrReceivingTransportHandler extends AbstractHttpReceivingTransportHandler {

441

public XhrReceivingTransportHandler();

442

}

443

```

444

445

### SockJS Frame Handling

446

447

Frame format and message codec interfaces for SockJS protocol.

448

449

```java { .api }

450

/**

451

* Contract for formatting SockJS frames for transport.

452

*/

453

interface SockJsFrameFormat {

454

/**

455

* Format a SockJS frame for the specific transport.

456

* @param frame SockJS frame to format

457

* @return formatted frame string

458

*/

459

String format(SockJsFrame frame);

460

}

461

462

/**

463

* Contract for encoding and decoding SockJS messages.

464

*/

465

interface SockJsMessageCodec {

466

/**

467

* Encode messages into SockJS frame format.

468

* @param messages array of message strings

469

* @return encoded frame content

470

* @throws IOException if encoding fails

471

*/

472

String encode(String... messages) throws IOException;

473

474

/**

475

* Decode SockJS frame content into messages.

476

* @param content encoded frame content

477

* @return array of decoded messages

478

* @throws IOException if decoding fails

479

*/

480

String[] decode(String content) throws IOException;

481

482

/**

483

* Decode SockJS frame content from input stream.

484

* @param content input stream with encoded content

485

* @return array of decoded messages

486

* @throws IOException if decoding fails

487

*/

488

String[] decodeInputStream(InputStream content) throws IOException;

489

}

490

491

/**

492

* Represents a SockJS frame with type and content.

493

*/

494

class SockJsFrame {

495

/**

496

* Create an open frame.

497

* @return open frame instance

498

*/

499

public static SockJsFrame openFrame();

500

501

/**

502

* Create a heartbeat frame.

503

* @return heartbeat frame instance

504

*/

505

public static SockJsFrame heartbeatFrame();

506

507

/**

508

* Create a message frame with encoded messages.

509

* @param codec message codec for encoding

510

* @param messages messages to include

511

* @return message frame instance

512

*/

513

public static SockJsFrame messageFrame(MessageCodec codec, String... messages);

514

515

/**

516

* Create a close frame with status and reason.

517

* @param code close status code

518

* @param reason close reason

519

* @return close frame instance

520

*/

521

public static SockJsFrame closeFrame(int code, String reason);

522

523

/**

524

* Get the frame type.

525

* @return frame type

526

*/

527

public SockJsFrameType getType();

528

529

/**

530

* Get the frame content.

531

* @return frame content string

532

*/

533

public String getContent();

534

}

535

536

/**

537

* Enumeration of SockJS frame types.

538

*/

539

enum SockJsFrameType {

540

/**

541

* Connection opened frame.

542

*/

543

OPEN,

544

545

/**

546

* Heartbeat frame for keep-alive.

547

*/

548

HEARTBEAT,

549

550

/**

551

* Message frame containing data.

552

*/

553

MESSAGE,

554

555

/**

556

* Connection closed frame.

557

*/

558

CLOSE

559

}

560

561

/**

562

* Default implementation of SockJsFrameFormat.

563

*/

564

class DefaultSockJsFrameFormat implements SockJsFrameFormat {

565

public DefaultSockJsFrameFormat();

566

}

567

568

/**

569

* SockJS message codec using Jackson 2 for JSON processing.

570

*/

571

class Jackson2SockJsMessageCodec extends AbstractSockJsMessageCodec {

572

public Jackson2SockJsMessageCodec();

573

}

574

```

575

576

### SockJS Client Support

577

578

Client-side SockJS implementation for connecting to SockJS-enabled servers.

579

580

```java { .api }

581

/**

582

* Main SockJS client implementation.

583

* Provides automatic transport fallback for unreliable connections.

584

*/

585

class SockJsClient implements WebSocketClient {

586

/**

587

* Create SockJS client with transport list.

588

* @param transports list of transport implementations

589

*/

590

public SockJsClient(List<Transport> transports);

591

592

/**

593

* Set the message codec for frame processing.

594

* @param messageCodec codec instance

595

*/

596

public void setMessageCodec(SockJsMessageCodec messageCodec);

597

598

/**

599

* Get the message codec.

600

* @return codec instance

601

*/

602

public SockJsMessageCodec getMessageCodec();

603

604

/**

605

* Set the info receiver for server capability detection.

606

* @param infoReceiver info receiver implementation

607

*/

608

public void setInfoReceiver(InfoReceiver infoReceiver);

609

610

/**

611

* Get the info receiver.

612

* @return info receiver implementation

613

*/

614

public InfoReceiver getInfoReceiver();

615

}

616

617

/**

618

* Contract for SockJS client transport implementations.

619

*/

620

interface Transport {

621

/**

622

* Connect using this transport.

623

* @param request transport request information

624

* @param handler WebSocket handler for the connection

625

* @return future that completes when connected

626

*/

627

ListenableFuture<WebSocketSession> connect(

628

TransportRequest request,

629

WebSocketHandler handler

630

);

631

632

/**

633

* Get transport type.

634

* @return transport type

635

*/

636

TransportType getTransportType();

637

}

638

639

/**

640

* SockJS client WebSocket transport implementation.

641

*/

642

class WebSocketTransport implements Transport {

643

/**

644

* Create WebSocket transport with client.

645

* @param webSocketClient underlying WebSocket client

646

*/

647

public WebSocketTransport(WebSocketClient webSocketClient);

648

}

649

650

/**

651

* XHR transport implementation using RestTemplate.

652

*/

653

class RestTemplateXhrTransport extends AbstractXhrTransport {

654

/**

655

* Create XHR transport with RestTemplate.

656

*/

657

public RestTemplateXhrTransport();

658

659

/**

660

* Create XHR transport with custom RestTemplate.

661

* @param restTemplate configured RestTemplate instance

662

*/

663

public RestTemplateXhrTransport(RestTemplate restTemplate);

664

}

665

```

666

667

**Usage Example:**

668

669

```java

670

@Service

671

public class SockJsClientService {

672

673

private final SockJsClient sockJsClient;

674

675

public SockJsClientService() {

676

// Configure transports in preference order

677

List<Transport> transports = Arrays.asList(

678

new WebSocketTransport(new StandardWebSocketClient()),

679

new RestTemplateXhrTransport(),

680

new JettyXhrTransport()

681

);

682

683

this.sockJsClient = new SockJsClient(transports);

684

this.sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());

685

}

686

687

public CompletableFuture<WebSocketSession> connectToChat(String serverUrl) {

688

WebSocketHandler handler = new ChatClientHandler();

689

690

ListenableFuture<WebSocketSession> future = sockJsClient.doHandshake(

691

handler,

692

serverUrl + "/chat"

693

);

694

695

return toCompletableFuture(future);

696

}

697

698

public CompletableFuture<WebSocketSession> connectWithAuth(String serverUrl, String token) {

699

WebSocketHandler handler = new AuthenticatedClientHandler(token);

700

701

WebSocketHttpHeaders headers = new WebSocketHttpHeaders();

702

headers.add("Authorization", "Bearer " + token);

703

704

ListenableFuture<WebSocketSession> future = sockJsClient.doHandshake(

705

handler,

706

headers,

707

URI.create(serverUrl + "/secure-chat")

708

);

709

710

return toCompletableFuture(future);

711

}

712

}

713

714

// Client handler with SockJS transport fallback awareness

715

public class ChatClientHandler extends AbstractWebSocketHandler {

716

717

@Override

718

public void afterConnectionEstablished(WebSocketSession session) throws Exception {

719

logger.info("Connected via transport: {}", getTransportType(session));

720

session.sendMessage(new TextMessage("Hello from SockJS client!"));

721

}

722

723

@Override

724

protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

725

String payload = message.getPayload();

726

logger.info("Received: {}", payload);

727

728

// Echo message back

729

session.sendMessage(new TextMessage("Echo: " + payload));

730

}

731

732

@Override

733

public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

734

logger.error("Transport error ({}): {}",

735

getTransportType(session), exception.getMessage());

736

737

// SockJS client will automatically try fallback transports

738

}

739

740

private String getTransportType(WebSocketSession session) {

741

// Try to determine actual transport used

742

if (session instanceof NativeWebSocketSession nativeSession) {

743

Object nativeSessionObj = nativeSession.getNativeSession();

744

return nativeSessionObj.getClass().getSimpleName();

745

}

746

return "unknown";

747

}

748

}

749

```

750

751

### SockJS Exception Classes

752

753

Exception hierarchy for SockJS-related errors.

754

755

```java { .api }

756

/**

757

* Base exception for SockJS-related errors.

758

*/

759

class SockJsException extends Exception {

760

/**

761

* Create SockJS exception with message.

762

* @param message error message

763

*/

764

public SockJsException(String message);

765

766

/**

767

* Create SockJS exception with message and cause.

768

* @param message error message

769

* @param cause underlying cause

770

*/

771

public SockJsException(String message, Throwable cause);

772

}

773

774

/**

775

* Exception for SockJS transport failures.

776

*/

777

class SockJsTransportFailureException extends SockJsException {

778

/**

779

* Create transport failure exception.

780

* @param message error message

781

* @param cause underlying cause

782

*/

783

public SockJsTransportFailureException(String message, Throwable cause);

784

}

785

786

/**

787

* Exception for SockJS message delivery failures.

788

*/

789

class SockJsMessageDeliveryException extends SockJsException {

790

/**

791

* Create message delivery exception.

792

* @param message error message

793

*/

794

public SockJsMessageDeliveryException(String message);

795

}

796

```