0
# Client API
1
2
The JAX-RS Client API provides a fluent interface for consuming RESTful web services. It supports synchronous, asynchronous, and reactive invocation patterns with built-in support for request/response filtering, configuration, and entity processing.
3
4
## Core Imports
5
6
```java
7
import javax.ws.rs.client.Client;
8
import javax.ws.rs.client.ClientBuilder;
9
import javax.ws.rs.client.WebTarget;
10
import javax.ws.rs.client.Invocation;
11
import javax.ws.rs.client.Entity;
12
import javax.ws.rs.client.AsyncInvoker;
13
import javax.ws.rs.client.SyncInvoker;
14
import javax.ws.rs.client.InvocationCallback;
15
import javax.ws.rs.client.RxInvoker;
16
import javax.ws.rs.client.CompletionStageRxInvoker;
17
import javax.ws.rs.client.ClientRequestFilter;
18
import javax.ws.rs.client.ClientResponseFilter;
19
import javax.ws.rs.client.ClientRequestContext;
20
import javax.ws.rs.client.ClientResponseContext;
21
import javax.ws.rs.client.ResponseProcessingException;
22
23
import javax.ws.rs.core.MediaType;
24
import javax.ws.rs.core.Response;
25
import javax.ws.rs.core.GenericType;
26
import javax.ws.rs.core.MultivaluedMap;
27
import javax.ws.rs.core.Configuration;
28
29
import javax.ws.rs.ext.ReaderInterceptor;
30
import javax.ws.rs.ext.WriterInterceptor;
31
32
import java.util.concurrent.Future;
33
import java.util.concurrent.CompletionStage;
34
import java.io.IOException;
35
```
36
37
## Client Creation
38
39
### ClientBuilder
40
41
Main entry point for creating Client instances.
42
43
```java { .api }
44
public abstract class ClientBuilder implements Configurable<ClientBuilder> {
45
46
public static ClientBuilder newBuilder();
47
public static Client newClient();
48
public static Client newClient(Configuration configuration);
49
50
public abstract ClientBuilder withConfig(Configuration config);
51
public abstract Client build();
52
}
53
```
54
55
### Client Interface
56
57
Main client interface for building requests.
58
59
```java { .api }
60
public interface Client extends Configurable<Client> {
61
62
void close();
63
64
WebTarget target(String uri);
65
WebTarget target(URI uri);
66
WebTarget target(UriBuilder uriBuilder);
67
WebTarget target(Link link);
68
69
Invocation.Builder invocation(Link link);
70
}
71
```
72
73
**Basic Client Usage:**
74
75
```java
76
// Create client
77
Client client = ClientBuilder.newClient();
78
79
// Simple GET request
80
Response response = client.target("https://api.example.com/users/123")
81
.request(MediaType.APPLICATION_JSON)
82
.get();
83
84
if (response.getStatus() == 200) {
85
User user = response.readEntity(User.class);
86
System.out.println("User: " + user.getName());
87
}
88
89
// Always close the client
90
client.close();
91
```
92
93
## WebTarget Interface
94
95
Represents a resource target identified by URI.
96
97
```java { .api }
98
public interface WebTarget extends Configurable<WebTarget> {
99
100
URI getUri();
101
UriBuilder getUriBuilder();
102
103
WebTarget path(String path);
104
WebTarget resolveTemplate(String name, Object value);
105
WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath);
106
WebTarget resolveTemplateFromEncoded(String name, Object value);
107
WebTarget resolveTemplates(Map<String, Object> templateValues);
108
WebTarget resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath);
109
WebTarget resolveTemplatesFromEncoded(Map<String, Object> templateValues);
110
111
WebTarget matrixParam(String name, Object... values);
112
WebTarget queryParam(String name, Object... values);
113
114
Invocation.Builder request();
115
Invocation.Builder request(String... acceptedResponseTypes);
116
Invocation.Builder request(MediaType... acceptedResponseTypes);
117
}
118
```
119
120
**WebTarget Usage Examples:**
121
122
```java
123
Client client = ClientBuilder.newClient();
124
125
// Building complex URIs
126
WebTarget baseTarget = client.target("https://api.example.com");
127
128
// Path building
129
WebTarget usersTarget = baseTarget.path("/users").path("/{userId}");
130
131
// Template resolution
132
WebTarget specificUser = usersTarget.resolveTemplate("userId", "123");
133
134
// Query parameters
135
WebTarget searchTarget = baseTarget.path("/search")
136
.queryParam("q", "java")
137
.queryParam("limit", 10)
138
.queryParam("offset", 0);
139
140
// Matrix parameters
141
WebTarget productsTarget = baseTarget.path("/products")
142
.matrixParam("color", "red")
143
.matrixParam("size", "large");
144
145
// Execute requests
146
Response userResponse = specificUser.request(MediaType.APPLICATION_JSON).get();
147
Response searchResponse = searchTarget.request(MediaType.APPLICATION_JSON).get();
148
```
149
150
## Invocation Building
151
152
### Invocation and Builder Interfaces
153
154
```java { .api }
155
public interface Invocation {
156
157
Invocation property(String name, Object value);
158
Response invoke();
159
<T> T invoke(Class<T> responseType);
160
<T> T invoke(GenericType<T> responseType);
161
162
Future<Response> submit();
163
<T> Future<T> submit(Class<T> responseType);
164
<T> Future<T> submit(GenericType<T> responseType);
165
<T> Future<T> submit(InvocationCallback<T> callback);
166
}
167
168
public static interface Invocation.Builder extends SyncInvoker {
169
170
Invocation build(String method);
171
Invocation build(String method, Entity<?> entity);
172
Invocation buildGet();
173
Invocation buildDelete();
174
Invocation buildPost(Entity<?> entity);
175
Invocation buildPut(Entity<?> entity);
176
177
AsyncInvoker async();
178
179
Invocation.Builder accept(String... mediaTypes);
180
Invocation.Builder accept(MediaType... mediaTypes);
181
Invocation.Builder acceptLanguage(Locale... locales);
182
Invocation.Builder acceptLanguage(String... locales);
183
Invocation.Builder acceptEncoding(String... encodings);
184
Invocation.Builder cookie(Cookie cookie);
185
Invocation.Builder cookie(String name, String value);
186
Invocation.Builder cacheControl(CacheControl cacheControl);
187
Invocation.Builder header(String name, Object value);
188
Invocation.Builder headers(MultivaluedMap<String, Object> headers);
189
Invocation.Builder property(String name, Object value);
190
191
CompletionStageRxInvoker rx();
192
<T extends RxInvoker> T rx(Class<T> clazz);
193
}
194
```
195
196
## Synchronous Invocations
197
198
### SyncInvoker Interface
199
200
```java { .api }
201
public interface SyncInvoker {
202
203
Response get();
204
<T> T get(Class<T> responseType);
205
<T> T get(GenericType<T> responseType);
206
207
Response put(Entity<?> entity);
208
<T> T put(Entity<?> entity, Class<T> responseType);
209
<T> T put(Entity<?> entity, GenericType<T> responseType);
210
211
Response post(Entity<?> entity);
212
<T> T post(Entity<?> entity, Class<T> responseType);
213
<T> T post(Entity<?> entity, GenericType<T> responseType);
214
215
Response delete();
216
<T> T delete(Class<T> responseType);
217
<T> T delete(GenericType<T> responseType);
218
219
Response head();
220
Response options();
221
<T> T options(Class<T> responseType);
222
<T> T options(GenericType<T> responseType);
223
224
Response trace();
225
<T> T trace(Class<T> responseType);
226
<T> T trace(GenericType<T> responseType);
227
228
Response method(String name);
229
<T> T method(String name, Class<T> responseType);
230
<T> T method(String name, GenericType<T> responseType);
231
Response method(String name, Entity<?> entity);
232
<T> T method(String name, Entity<?> entity, Class<T> responseType);
233
<T> T method(String name, Entity<?> entity, GenericType<T> responseType);
234
}
235
```
236
237
**Synchronous Usage Examples:**
238
239
```java
240
Client client = ClientBuilder.newClient();
241
WebTarget target = client.target("https://api.example.com/users");
242
243
// GET requests
244
User user = target.path("/123")
245
.request(MediaType.APPLICATION_JSON)
246
.get(User.class);
247
248
// GET with response inspection
249
Response response = target.path("/123")
250
.request(MediaType.APPLICATION_JSON)
251
.get();
252
if (response.getStatus() == 200) {
253
User user = response.readEntity(User.class);
254
}
255
256
// POST requests
257
User newUser = new User("John", "john@example.com");
258
User created = target.request(MediaType.APPLICATION_JSON)
259
.post(Entity.json(newUser), User.class);
260
261
// PUT requests
262
User updatedUser = target.path("/123")
263
.request(MediaType.APPLICATION_JSON)
264
.put(Entity.json(user), User.class);
265
266
// DELETE requests
267
Response deleteResponse = target.path("/123")
268
.request()
269
.delete();
270
271
// Custom headers
272
User userWithAuth = target.path("/123")
273
.request(MediaType.APPLICATION_JSON)
274
.header("Authorization", "Bearer " + token)
275
.header("X-Client-Version", "1.0")
276
.get(User.class);
277
278
// Generic types for collections
279
List<User> users = target.request(MediaType.APPLICATION_JSON)
280
.get(new GenericType<List<User>>(){});
281
```
282
283
## Asynchronous Invocations
284
285
### AsyncInvoker Interface
286
287
```java { .api }
288
public interface AsyncInvoker {
289
290
Future<Response> get();
291
<T> Future<T> get(Class<T> responseType);
292
<T> Future<T> get(GenericType<T> responseType);
293
<T> Future<T> get(InvocationCallback<T> callback);
294
295
Future<Response> put(Entity<?> entity);
296
<T> Future<T> put(Entity<?> entity, Class<T> responseType);
297
<T> Future<T> put(Entity<?> entity, GenericType<T> responseType);
298
<T> Future<T> put(Entity<?> entity, InvocationCallback<T> callback);
299
300
Future<Response> post(Entity<?> entity);
301
<T> Future<T> post(Entity<?> entity, Class<T> responseType);
302
<T> Future<T> post(Entity<?> entity, GenericType<T> responseType);
303
<T> Future<T> post(Entity<?> entity, InvocationCallback<T> callback);
304
305
Future<Response> delete();
306
<T> Future<T> delete(Class<T> responseType);
307
<T> Future<T> delete(GenericType<T> responseType);
308
<T> Future<T> delete(InvocationCallback<T> callback);
309
310
Future<Response> head();
311
Future<Response> head(InvocationCallback<Response> callback);
312
313
Future<Response> options();
314
<T> Future<T> options(Class<T> responseType);
315
<T> Future<T> options(GenericType<T> responseType);
316
<T> Future<T> options(InvocationCallback<T> callback);
317
318
Future<Response> trace();
319
<T> Future<T> trace(Class<T> responseType);
320
<T> Future<T> trace(GenericType<T> responseType);
321
<T> Future<T> trace(InvocationCallback<T> callback);
322
323
Future<Response> method(String name);
324
<T> Future<T> method(String name, Class<T> responseType);
325
<T> Future<T> method(String name, GenericType<T> responseType);
326
<T> Future<T> method(String name, InvocationCallback<T> callback);
327
Future<Response> method(String name, Entity<?> entity);
328
<T> Future<T> method(String name, Entity<?> entity, Class<T> responseType);
329
<T> Future<T> method(String name, Entity<?> entity, GenericType<T> responseType);
330
<T> Future<T> method(String name, Entity<?> entity, InvocationCallback<T> callback);
331
}
332
```
333
334
### InvocationCallback Interface
335
336
```java { .api }
337
public interface InvocationCallback<RESPONSE> {
338
339
void completed(RESPONSE response);
340
void failed(Throwable throwable);
341
}
342
```
343
344
**Asynchronous Usage Examples:**
345
346
```java
347
Client client = ClientBuilder.newClient();
348
WebTarget target = client.target("https://api.example.com/users");
349
350
// Async with Future
351
Future<User> futureUser = target.path("/123")
352
.request(MediaType.APPLICATION_JSON)
353
.async()
354
.get(User.class);
355
356
// Wait for result
357
User user = futureUser.get(); // Blocks until completion
358
359
// Async with callback
360
target.path("/123")
361
.request(MediaType.APPLICATION_JSON)
362
.async()
363
.get(new InvocationCallback<User>() {
364
@Override
365
public void completed(User user) {
366
System.out.println("Received user: " + user.getName());
367
}
368
369
@Override
370
public void failed(Throwable throwable) {
371
System.err.println("Request failed: " + throwable.getMessage());
372
}
373
});
374
375
// Async POST with callback
376
User newUser = new User("Jane", "jane@example.com");
377
target.request(MediaType.APPLICATION_JSON)
378
.async()
379
.post(Entity.json(newUser), new InvocationCallback<User>() {
380
@Override
381
public void completed(User createdUser) {
382
System.out.println("User created: " + createdUser.getId());
383
}
384
385
@Override
386
public void failed(Throwable throwable) {
387
System.err.println("User creation failed: " + throwable.getMessage());
388
}
389
});
390
```
391
392
## Reactive Extensions
393
394
### RxInvoker Interfaces
395
396
```java { .api }
397
public interface RxInvoker<T> {
398
399
T get();
400
<R> T get(Class<R> responseType);
401
<R> T get(GenericType<R> responseType);
402
403
T put(Entity<?> entity);
404
<R> T put(Entity<?> entity, Class<R> responseType);
405
<R> T put(Entity<?> entity, GenericType<R> responseType);
406
407
T post(Entity<?> entity);
408
<R> T post(Entity<?> entity, Class<R> responseType);
409
<R> T post(Entity<?> entity, GenericType<R> responseType);
410
411
T delete();
412
<R> T delete(Class<R> responseType);
413
<R> T delete(GenericType<R> responseType);
414
415
T head();
416
T options();
417
<R> T options(Class<R> responseType);
418
<R> T options(GenericType<R> responseType);
419
420
T trace();
421
<R> T trace(Class<R> responseType);
422
<R> T trace(GenericType<R> responseType);
423
424
T method(String name);
425
<R> T method(String name, Class<R> responseType);
426
<R> T method(String name, GenericType<R> responseType);
427
T method(String name, Entity<?> entity);
428
<R> T method(String name, Entity<?> entity, Class<R> responseType);
429
<R> T method(String name, Entity<?> entity, GenericType<R> responseType);
430
}
431
432
public interface CompletionStageRxInvoker extends RxInvoker<CompletionStage> {
433
}
434
```
435
436
**Reactive Usage Examples:**
437
438
```java
439
import java.util.concurrent.CompletionStage;
440
441
Client client = ClientBuilder.newClient();
442
WebTarget target = client.target("https://api.example.com/users");
443
444
// CompletionStage-based reactive calls
445
CompletionStage<User> userStage = target.path("/123")
446
.request(MediaType.APPLICATION_JSON)
447
.rx()
448
.get(User.class);
449
450
// Chain operations
451
userStage.thenCompose(user -> {
452
// Load user's orders
453
return target.path("/" + user.getId() + "/orders")
454
.request(MediaType.APPLICATION_JSON)
455
.rx()
456
.get(new GenericType<List<Order>>(){});
457
}).thenAccept(orders -> {
458
System.out.println("User has " + orders.size() + " orders");
459
}).exceptionally(throwable -> {
460
System.err.println("Error: " + throwable.getMessage());
461
return null;
462
});
463
464
// Parallel requests
465
CompletionStage<User> userStage = target.path("/123")
466
.request(MediaType.APPLICATION_JSON)
467
.rx()
468
.get(User.class);
469
470
CompletionStage<List<Order>> ordersStage = target.path("/123/orders")
471
.request(MediaType.APPLICATION_JSON)
472
.rx()
473
.get(new GenericType<List<Order>>(){});
474
475
// Combine results
476
userStage.thenCombine(ordersStage, (user, orders) -> {
477
return new UserWithOrders(user, orders);
478
}).thenAccept(userWithOrders -> {
479
System.out.println("Complete user data loaded");
480
});
481
```
482
483
## Entity Processing
484
485
### Entity Class
486
487
Encapsulates message entity with variant information.
488
489
```java { .api }
490
public final class Entity<T> {
491
492
public static <T> Entity<T> entity(T entity, MediaType mediaType);
493
public static <T> Entity<T> entity(T entity, String mediaType);
494
public static <T> Entity<T> entity(T entity, Variant variant);
495
496
public static <T> Entity<T> json(T entity);
497
public static <T> Entity<T> xml(T entity);
498
public static <T> Entity<T> html(T entity);
499
public static <T> Entity<T> text(T entity);
500
public static <T> Entity<T> xhtml(T entity);
501
public static Entity<Form> form(Form form);
502
public static Entity<Form> form(MultivaluedMap<String, String> formData);
503
504
public Variant getVariant();
505
public MediaType getMediaType();
506
public String getEncoding();
507
public Locale getLanguage();
508
public T getEntity();
509
510
public Annotation[] getAnnotations();
511
}
512
```
513
514
**Entity Usage Examples:**
515
516
```java
517
Client client = ClientBuilder.newClient();
518
WebTarget target = client.target("https://api.example.com/users");
519
520
// JSON entity
521
User user = new User("John", "john@example.com");
522
Response response = target.request(MediaType.APPLICATION_JSON)
523
.post(Entity.json(user));
524
525
// XML entity
526
User xmlUser = target.request(MediaType.APPLICATION_XML)
527
.post(Entity.xml(user), User.class);
528
529
// Custom media type
530
User customUser = target.request("application/vnd.api+json")
531
.post(Entity.entity(user, "application/vnd.api+json"), User.class);
532
533
// Form data
534
MultivaluedMap<String, String> formData = new MultivaluedHashMap<>();
535
formData.add("name", "John");
536
formData.add("email", "john@example.com");
537
538
Response formResponse = target.request()
539
.post(Entity.form(formData));
540
541
// Form object
542
Form form = new Form();
543
form.param("name", "John");
544
form.param("email", "john@example.com");
545
546
Response formObjectResponse = target.request()
547
.post(Entity.form(form));
548
```
549
550
## Client Configuration and Filtering
551
552
JAX-RS clients support configuration and filtering for cross-cutting concerns.
553
554
**Configuration Example:**
555
556
```java
557
// Custom client configuration
558
Client client = ClientBuilder.newBuilder()
559
.connectTimeout(5, TimeUnit.SECONDS)
560
.readTimeout(30, TimeUnit.SECONDS)
561
.register(new LoggingFilter())
562
.register(new AuthenticationFilter())
563
.build();
564
565
// Per-request configuration
566
Response response = client.target("https://api.example.com/users")
567
.property("custom.timeout", 10000)
568
.request(MediaType.APPLICATION_JSON)
569
.header("X-API-Key", apiKey)
570
.get();
571
```
572
573
## Client Filters and Interceptors
574
575
### Client Request Filter
576
577
Interface for filtering client requests before they are sent to the server.
578
579
```java { .api }
580
@FunctionalInterface
581
public interface ClientRequestFilter {
582
void filter(ClientRequestContext requestContext) throws IOException;
583
}
584
```
585
586
### Client Response Filter
587
588
Interface for filtering client responses after they are received from the server.
589
590
```java { .api }
591
@FunctionalInterface
592
public interface ClientResponseFilter {
593
void filter(ClientRequestContext requestContext,
594
ClientResponseContext responseContext) throws IOException;
595
}
596
```
597
598
### Client Request Context
599
600
Provides access to request context during client-side filtering.
601
602
```java { .api }
603
public interface ClientRequestContext {
604
Object getProperty(String name);
605
Collection<String> getPropertyNames();
606
void setProperty(String name, Object object);
607
void removeProperty(String name);
608
609
URI getUri();
610
void setUri(URI uri);
611
String getMethod();
612
void setMethod(String method);
613
614
MultivaluedMap<String, Object> getHeaders();
615
MultivaluedMap<String, String> getStringHeaders();
616
String getHeaderString(String name);
617
618
Date getDate();
619
Locale getLanguage();
620
MediaType getMediaType();
621
List<MediaType> getAcceptableMediaTypes();
622
List<Locale> getAcceptableLanguages();
623
624
Map<String, Cookie> getCookies();
625
boolean hasEntity();
626
Object getEntity();
627
void setEntity(Object entity);
628
void setEntity(Object entity, Annotation[] annotations, MediaType mediaType);
629
630
Class<?> getEntityClass();
631
Type getEntityType();
632
Annotation[] getEntityAnnotations();
633
OutputStream getEntityStream();
634
void setEntityStream(OutputStream outputStream);
635
636
Client getClient();
637
Configuration getConfiguration();
638
void abortWith(Response response);
639
}
640
```
641
642
### Client Response Context
643
644
Provides access to response context during client-side filtering.
645
646
```java { .api }
647
public interface ClientResponseContext {
648
int getStatus();
649
void setStatus(int code);
650
Response.StatusType getStatusInfo();
651
void setStatusInfo(Response.StatusType statusInfo);
652
653
MultivaluedMap<String, String> getHeaders();
654
String getHeaderString(String name);
655
Set<String> getAllowedMethods();
656
Date getDate();
657
Date getLastModified();
658
Locale getLanguage();
659
int getLength();
660
MediaType getMediaType();
661
Map<String, NewCookie> getCookies();
662
EntityTag getEntityTag();
663
664
boolean hasEntity();
665
InputStream getEntityStream();
666
void setEntityStream(InputStream input);
667
}
668
```
669
670
**Client Filter Usage Example:**
671
672
```java
673
// Authentication filter
674
@Provider
675
public class BearerTokenFilter implements ClientRequestFilter {
676
private final String token;
677
678
public BearerTokenFilter(String token) {
679
this.token = token;
680
}
681
682
@Override
683
public void filter(ClientRequestContext requestContext) throws IOException {
684
requestContext.getHeaders().add("Authorization", "Bearer " + token);
685
}
686
}
687
688
// Logging filter
689
@Provider
690
public class ClientLoggingFilter implements ClientRequestFilter, ClientResponseFilter {
691
692
@Override
693
public void filter(ClientRequestContext requestContext) throws IOException {
694
System.out.println("Request: " + requestContext.getMethod() + " " + requestContext.getUri());
695
}
696
697
@Override
698
public void filter(ClientRequestContext requestContext,
699
ClientResponseContext responseContext) throws IOException {
700
System.out.println("Response: " + responseContext.getStatus());
701
}
702
}
703
704
// Register filters
705
Client client = ClientBuilder.newBuilder()
706
.register(new BearerTokenFilter("abc123"))
707
.register(new ClientLoggingFilter())
708
.build();
709
```
710
711
## Exception Handling
712
713
### Client-Side Exceptions
714
715
```java { .api }
716
public class ProcessingException extends RuntimeException {
717
public ProcessingException(String message);
718
public ProcessingException(String message, Throwable cause);
719
public ProcessingException(Throwable cause);
720
}
721
722
public class ResponseProcessingException extends ProcessingException {
723
public ResponseProcessingException(Response response, String message);
724
public ResponseProcessingException(Response response, String message, Throwable cause);
725
public ResponseProcessingException(Response response, Throwable cause);
726
727
public Response getResponse();
728
}
729
```
730
731
**Exception Handling Example:**
732
733
```java
734
try {
735
User user = client.target("https://api.example.com/users/123")
736
.request(MediaType.APPLICATION_JSON)
737
.get(User.class);
738
} catch (ProcessingException e) {
739
// Network or processing error
740
System.err.println("Request processing failed: " + e.getMessage());
741
} catch (WebApplicationException e) {
742
// HTTP error response (4xx, 5xx)
743
Response response = e.getResponse();
744
System.err.println("HTTP error " + response.getStatus() + ": " +
745
response.readEntity(String.class));
746
}
747
```