or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-config.mdcontent-handling.mdfiltering.mdhttp-client.mdindex.mdrequest-response.mdrouting.mdwebsocket.md

websocket.mddocs/

0

# WebSocket Support

1

2

WebSocket client functionality with message types (text, binary, close) and event-driven listener interface for real-time bidirectional communication.

3

4

## Capabilities

5

6

### WebSocket Interface

7

8

Main interface for WebSocket communication with message sending capabilities and resource management.

9

10

```java { .api }

11

/**

12

* WebSocket interface for bidirectional communication

13

* Extends Closeable for proper resource management

14

*/

15

public interface WebSocket extends Closeable {

16

/**

17

* Logger instance for WebSocket operations

18

*/

19

Logger LOG = Logger.getLogger(WebSocket.class.getName());

20

21

/**

22

* Sends a WebSocket message

23

* @param message Message to send (TextMessage, BinaryMessage, or CloseMessage)

24

* @return This WebSocket instance for chaining

25

*/

26

WebSocket send(Message message);

27

28

/**

29

* Sends text message (convenience method)

30

* @param data Text data to send

31

* @return This WebSocket instance for chaining

32

*/

33

default WebSocket sendText(CharSequence data);

34

35

/**

36

* Sends binary message (convenience method)

37

* @param data Binary data to send

38

* @return This WebSocket instance for chaining

39

*/

40

default WebSocket sendBinary(byte[] data);

41

42

/**

43

* Closes the WebSocket connection

44

*/

45

void close();

46

}

47

```

48

49

**Usage Examples:**

50

51

```java

52

import org.openqa.selenium.remote.http.*;

53

54

// Open WebSocket connection via HTTP client

55

HttpRequest wsRequest = new HttpRequest(HttpMethod.GET, "/websocket");

56

wsRequest.addHeader("Upgrade", "websocket");

57

58

WebSocket.Listener listener = new WebSocket.Listener() {

59

@Override

60

public void onText(CharSequence data) {

61

System.out.println("Received text: " + data);

62

}

63

64

@Override

65

public void onBinary(byte[] data) {

66

System.out.println("Received binary: " + data.length + " bytes");

67

}

68

69

@Override

70

public void onClose(int code, String reason) {

71

System.out.println("Connection closed: " + code + " - " + reason);

72

}

73

74

@Override

75

public void onError(Throwable cause) {

76

System.err.println("WebSocket error: " + cause.getMessage());

77

}

78

};

79

80

WebSocket socket = client.openSocket(wsRequest, listener);

81

82

// Send different types of messages

83

socket.sendText("Hello WebSocket!");

84

socket.sendBinary("Binary data".getBytes());

85

86

// Send custom messages

87

socket.send(new TextMessage("Custom text message"));

88

socket.send(new BinaryMessage("Custom binary".getBytes()));

89

90

// Chaining method calls

91

socket.sendText("Message 1")

92

.sendText("Message 2")

93

.sendBinary("data".getBytes());

94

95

// Close connection

96

socket.close();

97

```

98

99

### WebSocket Listener

100

101

Event-driven interface for handling incoming WebSocket messages and connection events.

102

103

```java { .api }

104

/**

105

* Listener interface for WebSocket events

106

* Extends Consumer<Message> for functional interface compatibility

107

*/

108

public interface Listener extends Consumer<Message> {

109

/**

110

* Default message dispatcher that routes messages to specific handlers

111

* @param message Incoming message (BinaryMessage, TextMessage, or CloseMessage)

112

*/

113

default void accept(Message message);

114

115

/**

116

* Handles incoming binary messages

117

* Default implementation does nothing

118

* @param data Binary message data

119

*/

120

default void onBinary(byte[] data);

121

122

/**

123

* Handles connection close events

124

* Default implementation does nothing

125

* @param code Close status code

126

* @param reason Close reason string

127

*/

128

default void onClose(int code, String reason);

129

130

/**

131

* Handles incoming text messages

132

* Default implementation does nothing

133

* @param data Text message data

134

*/

135

default void onText(CharSequence data);

136

137

/**

138

* Handles WebSocket errors

139

* Default implementation logs error at WARNING level

140

* @param cause Error cause

141

*/

142

default void onError(Throwable cause);

143

}

144

```

145

146

**Usage Examples:**

147

148

```java

149

import org.openqa.selenium.remote.http.*;

150

151

// Full listener implementation

152

WebSocket.Listener fullListener = new WebSocket.Listener() {

153

@Override

154

public void onText(CharSequence data) {

155

System.out.println("Text received: " + data);

156

// Echo back

157

if (socket != null) {

158

socket.sendText("Echo: " + data);

159

}

160

}

161

162

@Override

163

public void onBinary(byte[] data) {

164

System.out.println("Binary received: " + data.length + " bytes");

165

// Process binary data

166

processData(data);

167

}

168

169

@Override

170

public void onClose(int code, String reason) {

171

System.out.println("Connection closed with code " + code + ": " + reason);

172

cleanup();

173

}

174

175

@Override

176

public void onError(Throwable cause) {

177

System.err.println("WebSocket error occurred: " + cause.getMessage());

178

cause.printStackTrace();

179

// Custom error handling

180

handleError(cause);

181

}

182

183

private void processData(byte[] data) { /* process binary data */ }

184

private void cleanup() { /* cleanup resources */ }

185

private void handleError(Throwable cause) { /* handle error */ }

186

};

187

188

// Minimal listener (only text messages)

189

WebSocket.Listener textOnlyListener = new WebSocket.Listener() {

190

@Override

191

public void onText(CharSequence data) {

192

System.out.println("Received: " + data);

193

}

194

};

195

196

// Lambda-based listener using Consumer interface

197

WebSocket.Listener lambdaListener = message -> {

198

if (message instanceof TextMessage) {

199

System.out.println("Text: " + ((TextMessage) message).text());

200

} else if (message instanceof BinaryMessage) {

201

System.out.println("Binary: " + ((BinaryMessage) message).data().length + " bytes");

202

}

203

};

204

205

// Use listeners with WebSocket

206

WebSocket socket1 = client.openSocket(wsRequest, fullListener);

207

WebSocket socket2 = client.openSocket(wsRequest, textOnlyListener);

208

WebSocket socket3 = client.openSocket(wsRequest, lambdaListener);

209

```

210

211

## Message Types

212

213

### Message Interface

214

215

Base interface for all WebSocket message types.

216

217

```java { .api }

218

/**

219

* Marker interface for WebSocket messages

220

* Implemented by TextMessage, BinaryMessage, and CloseMessage

221

*/

222

public interface Message {

223

// Marker interface - no methods

224

}

225

```

226

227

### TextMessage

228

229

WebSocket text message implementation for string data.

230

231

```java { .api }

232

/**

233

* WebSocket text message containing string data

234

*/

235

public class TextMessage implements Message {

236

/**

237

* Creates text message from character sequence

238

* @param text Text content for the message

239

*/

240

public TextMessage(CharSequence text);

241

242

/**

243

* Gets the text content

244

* @return Message text as String

245

*/

246

public String text();

247

}

248

```

249

250

**Usage Examples:**

251

252

```java

253

// Create and send text messages

254

TextMessage message1 = new TextMessage("Hello World");

255

TextMessage message2 = new TextMessage(new StringBuilder("Dynamic content"));

256

257

socket.send(message1);

258

socket.send(message2);

259

260

// Access text content

261

String content = message1.text();

262

System.out.println("Message content: " + content);

263

264

// Use in listener

265

WebSocket.Listener listener = new WebSocket.Listener() {

266

@Override

267

public void onText(CharSequence data) {

268

// Can also receive via accept method:

269

}

270

271

@Override

272

public void accept(Message message) {

273

if (message instanceof TextMessage) {

274

TextMessage textMsg = (TextMessage) message;

275

System.out.println("Received text: " + textMsg.text());

276

}

277

}

278

};

279

```

280

281

### BinaryMessage

282

283

WebSocket binary message implementation for byte data with defensive copying.

284

285

```java { .api }

286

/**

287

* WebSocket binary message containing byte data

288

* Makes defensive copies to ensure data integrity

289

*/

290

public class BinaryMessage implements Message {

291

/**

292

* Creates binary message from ByteBuffer

293

* Makes read-only copy of the buffer

294

* @param data ByteBuffer containing binary data

295

*/

296

public BinaryMessage(ByteBuffer data);

297

298

/**

299

* Creates binary message from byte array

300

* Makes defensive copy of the array

301

* @param data Byte array containing binary data

302

*/

303

public BinaryMessage(byte[] data);

304

305

/**

306

* Gets the binary data

307

* Returns copy of internal data to prevent modification

308

* @return Byte array copy of message data

309

*/

310

public byte[] data();

311

}

312

```

313

314

**Usage Examples:**

315

316

```java

317

import java.nio.ByteBuffer;

318

319

// Create binary messages from byte array

320

byte[] imageData = loadImageData();

321

BinaryMessage imageMessage = new BinaryMessage(imageData);

322

socket.send(imageMessage);

323

324

// Create from ByteBuffer

325

ByteBuffer buffer = ByteBuffer.allocate(1024);

326

buffer.put("Binary content".getBytes());

327

buffer.flip();

328

BinaryMessage bufferMessage = new BinaryMessage(buffer);

329

socket.send(bufferMessage);

330

331

// Access binary data (returns defensive copy)

332

byte[] messageData = imageMessage.data();

333

System.out.println("Message size: " + messageData.length + " bytes");

334

335

// Modify returned data doesn't affect original

336

byte[] data = imageMessage.data();

337

data[0] = 0; // This doesn't change the message's internal data

338

339

// Use in listener

340

WebSocket.Listener listener = new WebSocket.Listener() {

341

@Override

342

public void onBinary(byte[] data) {

343

System.out.println("Received " + data.length + " bytes");

344

processImageData(data);

345

}

346

347

@Override

348

public void accept(Message message) {

349

if (message instanceof BinaryMessage) {

350

BinaryMessage binMsg = (BinaryMessage) message;

351

byte[] data = binMsg.data();

352

saveBinaryData(data);

353

}

354

}

355

356

private void processImageData(byte[] data) { /* process image */ }

357

private void saveBinaryData(byte[] data) { /* save to file */ }

358

};

359

```

360

361

### CloseMessage

362

363

WebSocket close message with status code and reason.

364

365

```java { .api }

366

/**

367

* WebSocket close message with status code and optional reason

368

*/

369

public class CloseMessage implements Message {

370

/**

371

* Creates close message with status code only

372

* @param code Close status code

373

*/

374

public CloseMessage(int code);

375

376

/**

377

* Creates close message with status code and reason

378

* @param code Close status code

379

* @param reason Close reason string

380

*/

381

public CloseMessage(int code, String reason);

382

383

/**

384

* Gets the close status code

385

* @return Status code indicating close reason

386

*/

387

public int code();

388

389

/**

390

* Gets the close reason string

391

* @return Close reason or empty string if not provided

392

*/

393

public String reason();

394

}

395

```

396

397

**Usage Examples:**

398

399

```java

400

// Create close messages

401

CloseMessage normalClose = new CloseMessage(1000); // Normal closure

402

CloseMessage errorClose = new CloseMessage(1002, "Protocol error");

403

CloseMessage customClose = new CloseMessage(4000, "Custom application error");

404

405

// Send close messages

406

socket.send(normalClose);

407

408

// Access close information

409

int closeCode = errorClose.code(); // 1002

410

String closeReason = errorClose.reason(); // "Protocol error"

411

412

System.out.println("Closing with code " + closeCode + ": " + closeReason);

413

414

// Use in listener

415

WebSocket.Listener listener = new WebSocket.Listener() {

416

@Override

417

public void onClose(int code, String reason) {

418

System.out.println("Connection closed: " + code + " - " + reason);

419

420

// Handle different close codes

421

switch (code) {

422

case 1000:

423

System.out.println("Normal closure");

424

break;

425

case 1001:

426

System.out.println("Endpoint going away");

427

break;

428

case 1002:

429

System.out.println("Protocol error");

430

break;

431

default:

432

System.out.println("Other close reason: " + code);

433

}

434

}

435

436

@Override

437

public void accept(Message message) {

438

if (message instanceof CloseMessage) {

439

CloseMessage closeMsg = (CloseMessage) message;

440

handleClose(closeMsg.code(), closeMsg.reason());

441

}

442

}

443

444

private void handleClose(int code, String reason) {

445

// Custom close handling logic

446

}

447

};

448

```

449

450

## WebSocket Connection Lifecycle

451

452

Complete example showing WebSocket connection lifecycle:

453

454

```java

455

import org.openqa.selenium.remote.http.*;

456

import java.util.concurrent.CountDownLatch;

457

import java.util.concurrent.TimeUnit;

458

459

public class WebSocketExample {

460

private WebSocket socket;

461

private final CountDownLatch closeLatch = new CountDownLatch(1);

462

463

public void connectAndCommunicate() throws InterruptedException {

464

// Create HTTP client

465

HttpClient client = HttpClient.Factory.createDefault()

466

.createClient(new URL("wss://echo.websocket.org"));

467

468

// Create WebSocket request

469

HttpRequest wsRequest = new HttpRequest(HttpMethod.GET, "/");

470

471

// Create listener

472

WebSocket.Listener listener = new WebSocket.Listener() {

473

@Override

474

public void onText(CharSequence data) {

475

System.out.println("Echo received: " + data);

476

}

477

478

@Override

479

public void onClose(int code, String reason) {

480

System.out.println("Connection closed: " + code + " - " + reason);

481

closeLatch.countDown();

482

}

483

484

@Override

485

public void onError(Throwable cause) {

486

System.err.println("WebSocket error: " + cause.getMessage());

487

closeLatch.countDown();

488

}

489

};

490

491

// Open connection

492

socket = client.openSocket(wsRequest, listener);

493

494

// Send messages

495

socket.sendText("Hello WebSocket!");

496

socket.sendText("This is a test message");

497

498

// Send binary data

499

socket.sendBinary("Binary test data".getBytes());

500

501

// Wait a bit for responses

502

Thread.sleep(2000);

503

504

// Close connection gracefully

505

socket.send(new CloseMessage(1000, "Normal closure"));

506

507

// Wait for close confirmation

508

closeLatch.await(10, TimeUnit.SECONDS);

509

510

// Cleanup

511

client.close();

512

}

513

}

514

```