0
# Client Support
1
2
WebSocket client implementations for establishing outbound WebSocket connections with connection management.
3
4
## Capabilities
5
6
### WebSocket Client Interface
7
8
Contract for initiating WebSocket requests to connect to a WebSocket server.
9
10
```java { .api }
11
/**
12
* Contract for initiating WebSocket requests to connect to a WebSocket server.
13
* Implementations handle the WebSocket handshake and connection establishment.
14
*/
15
interface WebSocketClient {
16
/**
17
* Execute WebSocket handshake using URI template.
18
* @param webSocketHandler handler for the connection
19
* @param uriTemplate URI template for the WebSocket endpoint
20
* @param uriVariables variables to substitute in the URI template
21
* @return future that completes when connection is established
22
*/
23
CompletableFuture<WebSocketSession> execute(
24
WebSocketHandler webSocketHandler,
25
String uriTemplate,
26
Object... uriVariables
27
);
28
29
/**
30
* Execute WebSocket handshake with headers and URI.
31
* @param webSocketHandler handler for the connection
32
* @param headers HTTP headers for the handshake request
33
* @param uri URI of the WebSocket endpoint
34
* @return future that completes when connection is established
35
*/
36
CompletableFuture<WebSocketSession> execute(
37
WebSocketHandler webSocketHandler,
38
@Nullable WebSocketHttpHeaders headers,
39
URI uri
40
);
41
42
/**
43
* Execute WebSocket handshake using URI template.
44
* @deprecated as of 5.0, in favor of {@link #execute}
45
*/
46
@Deprecated
47
CompletableFuture<WebSocketSession> doHandshake(
48
WebSocketHandler webSocketHandler,
49
String uriTemplate,
50
Object... uriVariables
51
);
52
53
/**
54
* Execute WebSocket handshake with headers and URI.
55
* @deprecated as of 5.0, in favor of {@link #execute}
56
*/
57
@Deprecated
58
CompletableFuture<WebSocketSession> doHandshake(
59
WebSocketHandler webSocketHandler,
60
@Nullable WebSocketHttpHeaders headers,
61
URI uri
62
);
63
}
64
```
65
66
**Usage Example:**
67
68
```java
69
@Service
70
public class WebSocketClientService {
71
private final WebSocketClient client;
72
private final WebSocketHandler handler;
73
74
public WebSocketClientService() {
75
this.client = new StandardWebSocketClient();
76
this.handler = new ClientWebSocketHandler();
77
}
78
79
public CompletableFuture<WebSocketSession> connectToServer(String serverUrl) {
80
// Simple connection
81
ListenableFuture<WebSocketSession> future = client.doHandshake(
82
handler,
83
serverUrl
84
);
85
86
return toCompletableFuture(future);
87
}
88
89
public CompletableFuture<WebSocketSession> connectWithAuth(String serverUrl, String token) {
90
// Connection with authentication headers
91
WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
92
headers.add("Authorization", "Bearer " + token);
93
headers.setSecWebSocketProtocol("chat", "echo");
94
95
URI uri = URI.create(serverUrl);
96
ListenableFuture<WebSocketSession> future = client.doHandshake(
97
handler,
98
headers,
99
uri
100
);
101
102
return toCompletableFuture(future);
103
}
104
105
public CompletableFuture<WebSocketSession> connectWithTemplate(String userId) {
106
// Connection using URI template
107
ListenableFuture<WebSocketSession> future = client.doHandshake(
108
handler,
109
"ws://localhost:8080/user/{userId}/websocket",
110
userId
111
);
112
113
return toCompletableFuture(future);
114
}
115
116
private CompletableFuture<WebSocketSession> toCompletableFuture(ListenableFuture<WebSocketSession> future) {
117
CompletableFuture<WebSocketSession> completableFuture = new CompletableFuture<>();
118
119
future.addCallback(
120
completableFuture::complete,
121
completableFuture::completeExceptionally
122
);
123
124
return completableFuture;
125
}
126
}
127
```
128
129
### Connection Management
130
131
Base classes for managing WebSocket connections with lifecycle support.
132
133
```java { .api }
134
/**
135
* Base class for connection managers that establish connections on startup.
136
* Implements Spring lifecycle interfaces for automatic connection management.
137
*/
138
abstract class ConnectionManagerSupport implements SmartLifecycle {
139
/**
140
* Set whether the connection should start automatically.
141
* @param autoStartup true to start automatically
142
*/
143
public void setAutoStartup(boolean autoStartup);
144
145
/**
146
* Check if auto-startup is enabled.
147
* @return true if auto-startup is enabled
148
*/
149
public boolean isAutoStartup();
150
151
/**
152
* Set the lifecycle phase for startup ordering.
153
* @param phase the lifecycle phase
154
*/
155
public void setPhase(int phase);
156
157
/**
158
* Get the lifecycle phase.
159
* @return the lifecycle phase
160
*/
161
public int getPhase();
162
163
/**
164
* Start the connection manager.
165
*/
166
public void start();
167
168
/**
169
* Stop the connection manager.
170
*/
171
public void stop();
172
173
/**
174
* Check if the connection manager is running.
175
* @return true if running
176
*/
177
public boolean isRunning();
178
}
179
180
/**
181
* Connection manager for establishing and maintaining WebSocket connections.
182
* Automatically reconnects on connection failure.
183
*/
184
class WebSocketConnectionManager extends ConnectionManagerSupport {
185
/**
186
* Create connection manager with URI template.
187
* @param client WebSocket client implementation
188
* @param webSocketHandler handler for the connection
189
* @param uriTemplate URI template for the endpoint
190
* @param uriVariables variables for the URI template
191
*/
192
public WebSocketConnectionManager(
193
WebSocketClient client,
194
WebSocketHandler webSocketHandler,
195
String uriTemplate,
196
Object... uriVariables
197
);
198
199
/**
200
* Set the connection URI.
201
* @param uri WebSocket endpoint URI
202
*/
203
public void setUri(URI uri);
204
205
/**
206
* Get the connection URI.
207
* @return WebSocket endpoint URI
208
*/
209
public URI getUri();
210
211
/**
212
* Set handshake headers.
213
* @param headers HTTP headers for handshake
214
*/
215
public void setHeaders(HttpHeaders headers);
216
217
/**
218
* Get handshake headers.
219
* @return HTTP headers for handshake
220
*/
221
public HttpHeaders getHeaders();
222
}
223
```
224
225
**Usage Example:**
226
227
```java
228
@Configuration
229
@EnableScheduling
230
public class WebSocketClientConfig {
231
232
@Bean
233
public WebSocketClient webSocketClient() {
234
return new StandardWebSocketClient();
235
}
236
237
@Bean
238
public WebSocketConnectionManager chatConnectionManager(
239
WebSocketClient client,
240
ChatClientHandler handler) {
241
242
WebSocketConnectionManager manager = new WebSocketConnectionManager(
243
client,
244
handler,
245
"ws://chat-server.example.com/chat"
246
);
247
248
// Configure connection manager
249
manager.setAutoStartup(true);
250
manager.setPhase(1000); // Start after other beans
251
252
// Add authentication headers
253
HttpHeaders headers = new HttpHeaders();
254
headers.add("Authorization", "Bearer ${chat.auth.token}");
255
manager.setHeaders(headers);
256
257
return manager;
258
}
259
260
@Bean
261
public WebSocketConnectionManager notificationConnectionManager(
262
WebSocketClient client,
263
NotificationClientHandler handler) {
264
265
WebSocketConnectionManager manager = new WebSocketConnectionManager(
266
client,
267
handler,
268
"wss://notifications.example.com/user/{userId}/notifications",
269
"${user.id}"
270
);
271
272
manager.setAutoStartup(true);
273
return manager;
274
}
275
}
276
277
@Component
278
public class ChatClientHandler extends AbstractWebSocketHandler {
279
280
@Override
281
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
282
logger.info("Connected to chat server: {}", session.getUri());
283
session.sendMessage(new TextMessage("Hello from client!"));
284
}
285
286
@Override
287
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
288
logger.info("Received message: {}", message.getPayload());
289
// Process incoming chat message
290
processChatMessage(message.getPayload());
291
}
292
293
@Override
294
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
295
logger.error("Transport error: {}", exception.getMessage());
296
// Connection manager will automatically attempt reconnection
297
}
298
299
@Override
300
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
301
logger.info("Connection closed: {} - {}", closeStatus.getCode(), closeStatus.getReason());
302
}
303
}
304
```
305
306
### Standard WebSocket Client
307
308
JSR-356 based WebSocket client implementation.
309
310
```java { .api }
311
/**
312
* WebSocket client implementation based on JSR-356 standard.
313
* Uses the standard WebSocketContainer for connections.
314
*/
315
class StandardWebSocketClient extends AbstractWebSocketClient implements WebSocketClient {
316
/**
317
* Create client with default WebSocketContainer.
318
*/
319
public StandardWebSocketClient();
320
321
/**
322
* Create client with custom WebSocketContainer.
323
* @param webSocketContainer JSR-356 WebSocket container
324
*/
325
public StandardWebSocketClient(WebSocketContainer webSocketContainer);
326
327
/**
328
* Set user properties for WebSocket connections.
329
* @param userProperties properties to set on WebSocket sessions
330
*/
331
public void setUserProperties(Map<String, Object> userProperties);
332
333
/**
334
* Get user properties.
335
* @return user properties map
336
*/
337
public Map<String, Object> getUserProperties();
338
}
339
```
340
341
**Usage Example:**
342
343
```java
344
@Configuration
345
public class StandardWebSocketClientConfig {
346
347
@Bean
348
public WebSocketContainer webSocketContainer() {
349
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
350
351
// Configure container properties
352
container.setDefaultMaxSessionIdleTimeout(300000); // 5 minutes
353
container.setDefaultMaxTextMessageBufferSize(64 * 1024); // 64KB
354
container.setDefaultMaxBinaryMessageBufferSize(64 * 1024); // 64KB
355
356
return container;
357
}
358
359
@Bean
360
public StandardWebSocketClient standardWebSocketClient(WebSocketContainer container) {
361
StandardWebSocketClient client = new StandardWebSocketClient(container);
362
363
// Set user properties for all connections
364
Map<String, Object> userProperties = new HashMap<>();
365
userProperties.put("client.version", "1.0");
366
userProperties.put("client.type", "spring-boot");
367
client.setUserProperties(userProperties);
368
369
return client;
370
}
371
}
372
373
@Service
374
public class FileTransferClient {
375
private final StandardWebSocketClient client;
376
377
public FileTransferClient(StandardWebSocketClient client) {
378
this.client = client;
379
}
380
381
public CompletableFuture<Void> uploadFile(String serverUrl, Path filePath) {
382
WebSocketHandler handler = new FileUploadHandler(filePath);
383
384
return client.doHandshake(handler, serverUrl)
385
.toCompletableFuture()
386
.thenCompose(session -> uploadFileContent(session, filePath));
387
}
388
389
private CompletableFuture<Void> uploadFileContent(WebSocketSession session, Path filePath) {
390
return CompletableFuture.runAsync(() -> {
391
try (FileInputStream fis = new FileInputStream(filePath.toFile())) {
392
byte[] buffer = new byte[8192];
393
int bytesRead;
394
395
while ((bytesRead = fis.read(buffer)) != -1) {
396
boolean isLast = (fis.available() == 0);
397
BinaryMessage chunk = new BinaryMessage(buffer, 0, bytesRead, isLast);
398
session.sendMessage(chunk);
399
}
400
401
session.close(CloseStatus.NORMAL);
402
} catch (IOException e) {
403
throw new RuntimeException("File upload failed", e);
404
}
405
});
406
}
407
}
408
```
409
410
### WebSocket Container Configuration
411
412
Factory bean for configuring JSR-356 WebSocket containers.
413
414
```java { .api }
415
/**
416
* Factory bean for creating and configuring JSR-356 WebSocketContainer.
417
* Provides Spring integration for WebSocket container configuration.
418
*/
419
class WebSocketContainerFactoryBean implements FactoryBean<WebSocketContainer>, InitializingBean {
420
/**
421
* Set the maximum session idle timeout.
422
* @param maxSessionIdleTimeout timeout in milliseconds
423
*/
424
public void setMaxSessionIdleTimeout(long maxSessionIdleTimeout);
425
426
/**
427
* Set the maximum text message buffer size.
428
* @param maxTextMessageBufferSize buffer size in bytes
429
*/
430
public void setMaxTextMessageBufferSize(int maxTextMessageBufferSize);
431
432
/**
433
* Set the maximum binary message buffer size.
434
* @param maxBinaryMessageBufferSize buffer size in bytes
435
*/
436
public void setMaxBinaryMessageBufferSize(int maxBinaryMessageBufferSize);
437
438
/**
439
* Set the async send timeout.
440
* @param asyncSendTimeout timeout in milliseconds
441
*/
442
public void setAsyncSendTimeout(long asyncSendTimeout);
443
444
/**
445
* Get the configured WebSocketContainer.
446
* @return configured WebSocket container
447
*/
448
public WebSocketContainer getObject();
449
450
/**
451
* Get the WebSocket container type.
452
* @return WebSocketContainer class
453
*/
454
public Class<?> getObjectType();
455
456
/**
457
* Check if the container is a singleton.
458
* @return true (container is singleton)
459
*/
460
public boolean isSingleton();
461
}
462
```
463
464
**Usage Example:**
465
466
```java
467
@Configuration
468
public class WebSocketContainerConfig {
469
470
@Bean
471
public WebSocketContainerFactoryBean webSocketContainer() {
472
WebSocketContainerFactoryBean factory = new WebSocketContainerFactoryBean();
473
474
factory.setMaxSessionIdleTimeout(300000); // 5 minutes
475
factory.setMaxTextMessageBufferSize(128 * 1024); // 128KB
476
factory.setMaxBinaryMessageBufferSize(512 * 1024); // 512KB
477
factory.setAsyncSendTimeout(10000); // 10 seconds
478
479
return factory;
480
}
481
482
@Bean
483
public StandardWebSocketClient webSocketClient(WebSocketContainer container) {
484
return new StandardWebSocketClient(container);
485
}
486
}
487
```