0
# Content Management
1
2
The content management capability provides flexible content handling for request bodies and response processing, supporting strings, byte arrays, streams, files, forms, and multipart data with both synchronous and asynchronous content delivery.
3
4
## Request Content Interface
5
6
The base interface for all request content types.
7
8
```java { .api }
9
public interface Request.Content {
10
String getContentType();
11
long getLength();
12
boolean isReproducible();
13
}
14
```
15
16
## String Content
17
18
Handle text-based request content including JSON, XML, and plain text.
19
20
### StringRequestContent
21
22
```java { .api }
23
public class StringRequestContent implements Request.Content {
24
public StringRequestContent(String content);
25
public StringRequestContent(String content, Charset charset);
26
public StringRequestContent(String contentType, String content);
27
public StringRequestContent(String contentType, String content, Charset charset);
28
29
public String getString();
30
public Charset getCharset();
31
}
32
```
33
34
### Usage Examples
35
36
```java
37
// Simple string content
38
StringRequestContent content = new StringRequestContent("Hello, World!");
39
40
// JSON content with explicit content type
41
String jsonData = "{\"name\":\"John\",\"age\":30}";
42
StringRequestContent jsonContent = new StringRequestContent("application/json", jsonData);
43
44
// XML content with custom charset
45
String xmlData = "<?xml version=\"1.0\"?><user><name>John</name></user>";
46
StringRequestContent xmlContent = new StringRequestContent(
47
"application/xml",
48
xmlData,
49
StandardCharsets.UTF_8
50
);
51
52
// Send with request
53
ContentResponse response = client.POST("https://api.example.com/users")
54
.content(jsonContent)
55
.send();
56
```
57
58
## Binary Content
59
60
Handle binary data including byte arrays and ByteBuffers.
61
62
### BytesRequestContent
63
64
```java { .api }
65
public class BytesRequestContent implements Request.Content {
66
public BytesRequestContent(byte[] bytes);
67
public BytesRequestContent(String contentType, byte[] bytes);
68
public BytesRequestContent(byte[]... bytes);
69
public BytesRequestContent(String contentType, byte[]... bytes);
70
71
public byte[] getBytes();
72
}
73
```
74
75
### ByteBufferRequestContent
76
77
```java { .api }
78
public class ByteBufferRequestContent implements Request.Content {
79
public ByteBufferRequestContent(ByteBuffer... buffers);
80
public ByteBufferRequestContent(String contentType, ByteBuffer... buffers);
81
82
public ByteBuffer[] getByteBuffers();
83
}
84
```
85
86
### Usage Examples
87
88
```java
89
// Binary data from byte array
90
byte[] imageData = Files.readAllBytes(Paths.get("image.png"));
91
BytesRequestContent imageContent = new BytesRequestContent("image/png", imageData);
92
93
// Multiple byte arrays
94
byte[] header = "HEADER".getBytes();
95
byte[] body = "BODY".getBytes();
96
BytesRequestContent multiContent = new BytesRequestContent("application/octet-stream", header, body);
97
98
// ByteBuffer content
99
ByteBuffer buffer = ByteBuffer.allocate(1024);
100
buffer.put("Binary data".getBytes());
101
buffer.flip();
102
ByteBufferRequestContent bufferContent = new ByteBufferRequestContent("application/octet-stream", buffer);
103
104
// Send binary content
105
ContentResponse response = client.POST("https://api.example.com/upload")
106
.content(imageContent)
107
.send();
108
```
109
110
## Stream Content
111
112
Handle streaming data from InputStreams and OutputStreams.
113
114
### InputStreamRequestContent
115
116
```java { .api }
117
public class InputStreamRequestContent implements Request.Content {
118
public InputStreamRequestContent(InputStream stream);
119
public InputStreamRequestContent(String contentType, InputStream stream);
120
public InputStreamRequestContent(InputStream stream, long contentLength);
121
public InputStreamRequestContent(String contentType, InputStream stream, long contentLength);
122
123
public InputStream getInputStream();
124
}
125
```
126
127
### OutputStreamRequestContent
128
129
```java { .api }
130
public class OutputStreamRequestContent implements Request.Content {
131
public OutputStreamRequestContent();
132
public OutputStreamRequestContent(String contentType);
133
134
public OutputStream getOutputStream();
135
public void close();
136
}
137
```
138
139
### Usage Examples
140
141
```java
142
// Upload file via InputStream
143
try (FileInputStream fileStream = new FileInputStream("document.pdf")) {
144
InputStreamRequestContent streamContent = new InputStreamRequestContent(
145
"application/pdf",
146
fileStream,
147
new File("document.pdf").length()
148
);
149
150
ContentResponse response = client.POST("https://api.example.com/documents")
151
.content(streamContent)
152
.send();
153
}
154
155
// Generate content via OutputStream
156
OutputStreamRequestContent outputContent = new OutputStreamRequestContent("text/csv");
157
158
// Write data to the OutputStream in a background thread
159
CompletableFuture.runAsync(() -> {
160
try (OutputStream out = outputContent.getOutputStream();
161
PrintWriter writer = new PrintWriter(out)) {
162
163
writer.println("Name,Age,Email");
164
writer.println("John,30,john@example.com");
165
writer.println("Jane,25,jane@example.com");
166
} catch (IOException e) {
167
throw new RuntimeException(e);
168
}
169
});
170
171
ContentResponse response = client.POST("https://api.example.com/data")
172
.content(outputContent)
173
.send();
174
```
175
176
## File Content
177
178
Handle file uploads with automatic content type detection.
179
180
### PathRequestContent
181
182
```java { .api }
183
public class PathRequestContent implements Request.Content {
184
public PathRequestContent(Path file);
185
public PathRequestContent(String contentType, Path file);
186
public PathRequestContent(Path file, ByteBufferPool bufferPool);
187
public PathRequestContent(String contentType, Path file, ByteBufferPool bufferPool);
188
189
public Path getPath();
190
}
191
```
192
193
### Usage Examples
194
195
```java
196
// Simple file upload
197
Path documentPath = Paths.get("/path/to/document.pdf");
198
PathRequestContent fileContent = new PathRequestContent(documentPath);
199
200
// File upload with explicit content type
201
PathRequestContent imageContent = new PathRequestContent("image/jpeg", documentPath);
202
203
// Upload the file
204
ContentResponse response = client.POST("https://api.example.com/upload")
205
.content(fileContent)
206
.send();
207
208
// Alternative: Direct file method on Request
209
ContentResponse response2 = client.POST("https://api.example.com/upload")
210
.file(documentPath)
211
.send();
212
```
213
214
## Form Content
215
216
Handle HTML form submissions including URL-encoded and multipart forms.
217
218
### FormRequestContent
219
220
```java { .api }
221
public class FormRequestContent implements Request.Content {
222
public FormRequestContent(Fields fields);
223
public FormRequestContent(Fields fields, Charset charset);
224
225
public Fields getFields();
226
public Charset getCharset();
227
}
228
```
229
230
### Usage Examples
231
232
```java
233
// Create form fields
234
Fields fields = new Fields();
235
fields.add("username", "john.doe");
236
fields.add("password", "secret123");
237
fields.add("remember", "true");
238
239
// Create form content
240
FormRequestContent formContent = new FormRequestContent(fields);
241
242
// Submit form
243
ContentResponse response = client.POST("https://example.com/login")
244
.content(formContent)
245
.send();
246
247
// Form with custom charset
248
FormRequestContent utf8Form = new FormRequestContent(fields, StandardCharsets.UTF_8);
249
```
250
251
## Multipart Content
252
253
Handle multipart form submissions including file uploads and mixed content types.
254
255
### MultiPartRequestContent
256
257
```java { .api }
258
public class MultiPartRequestContent implements Request.Content {
259
public MultiPartRequestContent();
260
public MultiPartRequestContent(String boundary);
261
262
public MultiPartRequestContent addPart(MultiPart.Part part);
263
public MultiPartRequestContent addFieldPart(String name, ContentSource content, HttpFields headers);
264
public MultiPartRequestContent addFilePart(String name, String fileName, ContentSource content, HttpFields headers);
265
public void close();
266
267
public String getBoundary();
268
}
269
```
270
271
### Usage Examples
272
273
```java
274
// Create multipart content
275
MultiPartRequestContent multipart = new MultiPartRequestContent();
276
277
// Add text field
278
multipart.addFieldPart("description",
279
new StringContentSource("Document upload"),
280
null);
281
282
// Add file upload
283
Path filePath = Paths.get("/path/to/document.pdf");
284
multipart.addFilePart("file",
285
"document.pdf",
286
new PathContentSource(filePath),
287
HttpFields.build().add("Content-Type", "application/pdf"));
288
289
// Add another text field
290
multipart.addFieldPart("category",
291
new StringContentSource("documents"),
292
null);
293
294
// Submit multipart form
295
ContentResponse response = client.POST("https://api.example.com/upload")
296
.content(multipart)
297
.send();
298
299
// Always close multipart content
300
multipart.close();
301
```
302
303
### Complex Multipart Example
304
305
```java
306
MultiPartRequestContent multipart = new MultiPartRequestContent();
307
308
// Add JSON metadata
309
String jsonMetadata = "{\"title\":\"My Document\",\"tags\":[\"important\",\"draft\"]}";
310
multipart.addFieldPart("metadata",
311
new StringContentSource(jsonMetadata),
312
HttpFields.build().add("Content-Type", "application/json"));
313
314
// Add multiple files
315
Path[] files = {
316
Paths.get("/path/to/document.pdf"),
317
Paths.get("/path/to/image.png")
318
};
319
320
for (int i = 0; i < files.length; i++) {
321
Path file = files[i];
322
String fileName = file.getFileName().toString();
323
String contentType = Files.probeContentType(file);
324
325
multipart.addFilePart("files",
326
fileName,
327
new PathContentSource(file),
328
HttpFields.build().add("Content-Type", contentType));
329
}
330
331
try {
332
ContentResponse response = client.POST("https://api.example.com/bulk-upload")
333
.content(multipart)
334
.send();
335
336
System.out.println("Upload completed: " + response.getStatus());
337
} finally {
338
multipart.close();
339
}
340
```
341
342
## Asynchronous Content
343
344
Handle content that is generated asynchronously or streamed over time.
345
346
### AsyncRequestContent
347
348
```java { .api }
349
public class AsyncRequestContent implements Request.Content {
350
public AsyncRequestContent();
351
public AsyncRequestContent(String contentType);
352
353
public void offer(ByteBuffer buffer);
354
public void offer(ByteBuffer buffer, Callback callback);
355
public void close();
356
public boolean isClosed();
357
public void fail(Throwable failure);
358
}
359
```
360
361
### Usage Examples
362
363
```java
364
// Create async content
365
AsyncRequestContent asyncContent = new AsyncRequestContent("text/plain");
366
367
// Start the request (non-blocking)
368
CompletableFuture<ContentResponse> future = client.POST("https://api.example.com/stream")
369
.content(asyncContent)
370
.send();
371
372
// Generate content asynchronously
373
CompletableFuture.runAsync(() -> {
374
try {
375
for (int i = 0; i < 10; i++) {
376
String data = "Chunk " + i + "\n";
377
ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());
378
asyncContent.offer(buffer);
379
380
Thread.sleep(100); // Simulate processing time
381
}
382
} catch (InterruptedException e) {
383
asyncContent.fail(e);
384
Thread.currentThread().interrupt();
385
} finally {
386
asyncContent.close();
387
}
388
});
389
390
// Wait for response
391
ContentResponse response = future.get(30, TimeUnit.SECONDS);
392
```
393
394
### Real-time Data Streaming
395
396
```java
397
public class DataStreamer {
398
private final AsyncRequestContent content;
399
private final CompletableFuture<ContentResponse> responseFuture;
400
401
public DataStreamer(HttpClient client, String url) {
402
this.content = new AsyncRequestContent("application/json");
403
this.responseFuture = client.POST(url)
404
.content(content)
405
.send();
406
}
407
408
public void sendData(Object data) {
409
try {
410
String json = objectMapper.writeValueAsString(data);
411
ByteBuffer buffer = ByteBuffer.wrap(json.getBytes(StandardCharsets.UTF_8));
412
content.offer(buffer);
413
} catch (Exception e) {
414
content.fail(e);
415
}
416
}
417
418
public void finish() {
419
content.close();
420
}
421
422
public ContentResponse waitForResponse() throws Exception {
423
return responseFuture.get(60, TimeUnit.SECONDS);
424
}
425
}
426
427
// Usage
428
DataStreamer streamer = new DataStreamer(client, "https://api.example.com/realtime");
429
430
// Send data over time
431
for (SensorReading reading : sensorReadings) {
432
streamer.sendData(reading);
433
Thread.sleep(1000); // Send every second
434
}
435
436
streamer.finish();
437
ContentResponse response = streamer.waitForResponse();
438
```
439
440
## Content Source Integration
441
442
Integration with Jetty's Content.Source system for advanced content handling.
443
444
### ContentSourceRequestContent
445
446
```java { .api }
447
public class ContentSourceRequestContent implements Request.Content {
448
public ContentSourceRequestContent(Content.Source contentSource);
449
public ContentSourceRequestContent(String contentType, Content.Source contentSource);
450
451
public Content.Source getContentSource();
452
}
453
```
454
455
### Usage with Custom Content Sources
456
457
```java
458
// Custom content source that generates data
459
Content.Source customSource = new Content.Source() {
460
private int count = 0;
461
462
@Override
463
public Content.Chunk read() {
464
if (count >= 5) {
465
return Content.Chunk.EOF;
466
}
467
468
String data = "Generated data " + (++count) + "\n";
469
ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());
470
return Content.Chunk.from(buffer);
471
}
472
473
@Override
474
public void demand(Runnable demandCallback) {
475
// Immediately signal data availability
476
demandCallback.run();
477
}
478
};
479
480
ContentSourceRequestContent sourceContent = new ContentSourceRequestContent(
481
"text/plain",
482
customSource
483
);
484
485
ContentResponse response = client.POST("https://api.example.com/custom")
486
.content(sourceContent)
487
.send();
488
```
489
490
## Content Utilities and Best Practices
491
492
### Content Length Considerations
493
494
```java
495
// For content with known length
496
byte[] data = "Known size content".getBytes();
497
BytesRequestContent content = new BytesRequestContent("text/plain", data);
498
// Length is automatically set to data.length
499
500
// For streaming content with unknown length
501
InputStream stream = new FileInputStream("largefile.dat");
502
InputStreamRequestContent streamContent = new InputStreamRequestContent("application/octet-stream", stream);
503
// Uses chunked transfer encoding
504
505
// For streaming content with known length
506
long fileSize = Files.size(Paths.get("largefile.dat"));
507
InputStreamRequestContent sizedStreamContent = new InputStreamRequestContent(
508
"application/octet-stream",
509
stream,
510
fileSize
511
);
512
```
513
514
### Content Type Best Practices
515
516
```java
517
// Explicit content types for better server processing
518
StringRequestContent jsonContent = new StringRequestContent(
519
"application/json; charset=utf-8",
520
jsonData
521
);
522
523
// Use proper MIME types for files
524
Path imagePath = Paths.get("photo.jpg");
525
String mimeType = Files.probeContentType(imagePath);
526
PathRequestContent imageContent = new PathRequestContent(mimeType, imagePath);
527
528
// Custom content types for specific APIs
529
BytesRequestContent customContent = new BytesRequestContent(
530
"application/vnd.api+json",
531
jsonApiData.getBytes()
532
);
533
```
534
535
### Memory Management
536
537
```java
538
// For large files, prefer streaming over loading into memory
539
Path largeFile = Paths.get("large-dataset.csv");
540
541
// Good: Streaming approach
542
PathRequestContent fileContent = new PathRequestContent("text/csv", largeFile);
543
544
// Avoid: Loading entire file into memory
545
byte[] fileBytes = Files.readAllBytes(largeFile); // Can cause OutOfMemoryError
546
BytesRequestContent memoryContent = new BytesRequestContent("text/csv", fileBytes);
547
```