0
# Asynchronous Operations
1
2
Comprehensive callback and promise APIs for building non-blocking, asynchronous applications with various callback implementations and patterns for efficient resource utilization.
3
4
## Capabilities
5
6
### Callback Interface
7
8
Core asynchronous operation completion handler with success/failure semantics.
9
10
```java { .api }
11
/**
12
* Callback interface for asynchronous operations
13
*/
14
public interface Callback {
15
/** Called when operation completes successfully */
16
void succeeded();
17
18
/** Called when operation fails */
19
void failed(Throwable x);
20
21
/** Check if callback is non-blocking */
22
default boolean isNonBlocking() { return false; }
23
24
/** Create callback from Runnable and Consumer */
25
static Callback from(Runnable success, Consumer<Throwable> failure);
26
27
/** Create callback from Runnable only */
28
static Callback from(Runnable success);
29
30
/** Get NOOP callback instance */
31
static Callback NOOP;
32
}
33
```
34
35
**Usage Examples:**
36
37
```java
38
import org.eclipse.jetty.util.Callback;
39
40
// Simple callback usage
41
public void performAsyncTask(Callback callback) {
42
new Thread(() -> {
43
try {
44
// Simulate work
45
Thread.sleep(1000);
46
callback.succeeded();
47
} catch (Exception e) {
48
callback.failed(e);
49
}
50
}).start();
51
}
52
53
// Using factory methods
54
Callback callback = Callback.from(
55
() -> System.out.println("Success!"),
56
error -> System.err.println("Failed: " + error)
57
);
58
59
performAsyncTask(callback);
60
```
61
62
### Promise Interface
63
64
Type-safe callback abstraction for operations that return results.
65
66
```java { .api }
67
/**
68
* Promise interface extending Callback with result handling
69
*/
70
public interface Promise<C> extends Callback {
71
/** Called when operation completes successfully with result */
72
void succeeded(C result);
73
74
/** Create promise from Consumer and Consumer for error */
75
static <T> Promise<T> from(Consumer<T> success, Consumer<Throwable> failure);
76
77
/** Complete promise immediately with result */
78
static <T> Promise<T> complete(T result);
79
}
80
```
81
82
**Usage Examples:**
83
84
```java
85
import org.eclipse.jetty.util.Promise;
86
87
// Promise with result
88
public void fetchData(Promise<String> promise) {
89
CompletableFuture.supplyAsync(() -> {
90
// Simulate data fetching
91
return "Hello, World!";
92
}).whenComplete((result, error) -> {
93
if (error != null) {
94
promise.failed(error);
95
} else {
96
promise.succeeded(result);
97
}
98
});
99
}
100
101
// Using promise
102
Promise<String> promise = Promise.from(
103
result -> System.out.println("Got: " + result),
104
error -> System.err.println("Error: " + error)
105
);
106
107
fetchData(promise);
108
```
109
110
### FuturePromise
111
112
Concrete implementation combining Future and Promise interfaces for synchronous and asynchronous usage patterns.
113
114
```java { .api }
115
/**
116
* Future-based promise implementation
117
*/
118
public class FuturePromise<C> implements Future<C>, Promise<C> {
119
/** Create empty future promise */
120
public FuturePromise();
121
122
/** Create future promise with immediate result */
123
public FuturePromise(C result);
124
125
/** Create future promise with immediate failure */
126
public FuturePromise(C ctx, Throwable failed);
127
128
/** Get result, blocking if necessary (from Future) */
129
public C get() throws InterruptedException, ExecutionException;
130
131
/** Get result with timeout (from Future) */
132
public C get(long timeout, TimeUnit unit)
133
throws InterruptedException, ExecutionException, TimeoutException;
134
135
/** Get result or throw original exception */
136
public C getOrThrow() throws Exception;
137
138
/** Check if operation completed */
139
public boolean isDone();
140
141
/** Check if operation was cancelled */
142
public boolean isCancelled();
143
144
/** Cancel the operation */
145
public boolean cancel(boolean mayInterruptIfRunning);
146
147
/** Utility to rethrow ExecutionException as IOException */
148
public static void rethrow(ExecutionException e) throws IOException;
149
}
150
```
151
152
**Usage Examples:**
153
154
```java
155
import org.eclipse.jetty.util.FuturePromise;
156
import java.util.concurrent.TimeUnit;
157
158
// Create and use FuturePromise
159
FuturePromise<String> promise = new FuturePromise<>();
160
161
// Start async operation
162
performAsyncTask(promise);
163
164
// Block for result
165
try {
166
String result = promise.get(5, TimeUnit.SECONDS);
167
System.out.println("Result: " + result);
168
} catch (TimeoutException e) {
169
System.out.println("Operation timed out");
170
promise.cancel(true);
171
} catch (ExecutionException e) {
172
System.out.println("Operation failed: " + e.getCause());
173
}
174
175
// Pre-completed promise
176
FuturePromise<Integer> completed = new FuturePromise<>(42);
177
assert completed.isDone();
178
assert completed.get() == 42;
179
180
// Failed promise
181
FuturePromise<String> failed = new FuturePromise<>(null, new RuntimeException("Error"));
182
assert failed.isDone();
183
try {
184
failed.getOrThrow(); // Throws the original RuntimeException
185
} catch (RuntimeException e) {
186
System.out.println("Expected failure: " + e.getMessage());
187
}
188
```
189
190
### Callback Implementations
191
192
Various callback implementations for different use cases.
193
194
```java { .api }
195
/**
196
* Callback that counts down operations
197
*/
198
public class CountingCallback implements Callback {
199
/** Create counting callback */
200
public CountingCallback(Callback callback, int count);
201
202
/** Get current count */
203
public int getCount();
204
}
205
206
/**
207
* Future-based callback implementation
208
*/
209
public class FutureCallback implements Callback, Future<Void> {
210
/** Create future callback */
211
public FutureCallback();
212
213
/** Create future callback with boolean result */
214
public FutureCallback(boolean completed);
215
216
/** Block until completion */
217
public void block() throws IOException;
218
}
219
220
/**
221
* Iterating callback for step-by-step processing
222
*/
223
public abstract class IteratingCallback implements Callback {
224
/** Perform next iteration step */
225
protected abstract Action process() throws Throwable;
226
227
/** Start iteration process */
228
public void iterate();
229
230
/** Action enum for iteration control */
231
public enum Action { SCHEDULED, IDLE, SUCCEEDED }
232
}
233
234
/**
235
* Shared blocking callback for reuse
236
*/
237
public class SharedBlockingCallback {
238
/** Create shared callback with pool */
239
public SharedBlockingCallback();
240
241
/** Acquire callback for use */
242
public Blocker acquire();
243
244
/** Blocker interface for blocking operations */
245
public interface Blocker extends Callback, Closeable {
246
void block() throws IOException;
247
}
248
}
249
```
250
251
**Usage Examples:**
252
253
```java
254
import org.eclipse.jetty.util.*;
255
256
// Counting multiple operations
257
CountingCallback counter = new CountingCallback(finalCallback, 3);
258
performAsyncTask(counter); // Will call finalCallback after 3 completions
259
performAsyncTask(counter);
260
performAsyncTask(counter);
261
262
// Future-style blocking
263
FutureCallback future = new FutureCallback();
264
performAsyncTask(future);
265
try {
266
future.get(5, TimeUnit.SECONDS); // Block with timeout
267
} catch (TimeoutException e) {
268
// Handle timeout
269
}
270
271
// Iterative processing
272
IteratingCallback processor = new IteratingCallback() {
273
private int step = 0;
274
275
@Override
276
protected Action process() throws Throwable {
277
if (step++ < 10) {
278
// Process step
279
return Action.SCHEDULED;
280
}
281
return Action.SUCCEEDED;
282
}
283
};
284
processor.iterate();
285
286
// Shared blocking callback
287
SharedBlockingCallback shared = new SharedBlockingCallback();
288
try (SharedBlockingCallback.Blocker blocker = shared.acquire()) {
289
performAsyncTask(blocker);
290
blocker.block(); // Block until completion
291
}
292
```
293
294
### Utility Classes
295
296
Additional utilities for asynchronous programming.
297
298
```java { .api }
299
/**
300
* Utility for blocking operations
301
*/
302
public class Blocker implements Callback, Closeable {
303
/** Block until callback completes */
304
public void block() throws IOException;
305
306
/** Block with timeout */
307
public boolean block(long timeout, TimeUnit unit) throws IOException;
308
309
/** Check if completed */
310
public boolean isDone();
311
312
/** Get failure cause if any */
313
public Throwable getFailure();
314
}
315
316
/**
317
* Wrapper callback for additional functionality
318
*/
319
public class CallbackWrapper implements Callback {
320
/** Create wrapper around another callback */
321
public CallbackWrapper(Callback callback);
322
323
/** Get wrapped callback */
324
public Callback getCallback();
325
}
326
```
327
328
**Usage Examples:**
329
330
```java
331
import org.eclipse.jetty.util.Blocker;
332
import org.eclipse.jetty.util.CallbackWrapper;
333
334
// Simple blocking
335
try (Blocker blocker = new Blocker()) {
336
performAsyncTask(blocker);
337
boolean completed = blocker.block(30, TimeUnit.SECONDS);
338
if (!completed) {
339
System.out.println("Operation timed out");
340
}
341
}
342
343
// Callback decoration
344
Callback wrapped = new CallbackWrapper(originalCallback) {
345
@Override
346
public void succeeded() {
347
System.out.println("Operation succeeded");
348
super.succeeded();
349
}
350
351
@Override
352
public void failed(Throwable x) {
353
System.out.println("Operation failed: " + x.getMessage());
354
super.failed(x);
355
}
356
};
357
```
358
359
## Patterns and Best Practices
360
361
### Callback Chaining
362
363
```java
364
// Chain multiple async operations
365
public void chainedOperations(Callback finalCallback) {
366
performFirstOperation(new Callback() {
367
@Override
368
public void succeeded() {
369
performSecondOperation(new Callback() {
370
@Override
371
public void succeeded() {
372
performThirdOperation(finalCallback);
373
}
374
375
@Override
376
public void failed(Throwable x) {
377
finalCallback.failed(x);
378
}
379
});
380
}
381
382
@Override
383
public void failed(Throwable x) {
384
finalCallback.failed(x);
385
}
386
});
387
}
388
```
389
390
### Error Handling
391
392
```java
393
// Robust error handling
394
public class SafeCallback implements Callback {
395
private final Callback delegate;
396
397
public SafeCallback(Callback delegate) {
398
this.delegate = delegate;
399
}
400
401
@Override
402
public void succeeded() {
403
try {
404
delegate.succeeded();
405
} catch (Exception e) {
406
// Log but don't propagate callback exceptions
407
logger.warn("Callback exception", e);
408
}
409
}
410
411
@Override
412
public void failed(Throwable x) {
413
try {
414
delegate.failed(x);
415
} catch (Exception e) {
416
logger.warn("Callback exception", e);
417
}
418
}
419
}
420
```
421
422
### Performance Considerations
423
424
- Use `isNonBlocking()` to indicate callback execution characteristics
425
- Prefer callback reuse over creating new instances when possible
426
- Use `SharedBlockingCallback` for blocking operations to reduce allocation
427
- Consider `IteratingCallback` for step-by-step processing to avoid stack overflow
428
429
## Error Handling
430
431
Asynchronous operations handle errors through the callback mechanism:
432
433
- `failed(Throwable)` is called for all operation failures
434
- Callback implementations should handle exceptions gracefully
435
- Use wrapper callbacks to add logging, retry logic, or error recovery
436
- Always handle both success and failure cases in callback implementations