Skip to content

Commit 6ecb93d

Browse files
committed
Adding exceptionallyAsync / exceptionallyCompose[Async] API as in Java 12
1 parent 94a4c4d commit 6ecb93d

14 files changed

+367
-10
lines changed

src/main/java/net/tascalate/concurrent/ConfigurableDependentPromise.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,35 @@ public <U> DependentPromise<U> thenComposeAsync(Function<? super T, ? extends Co
365365
public DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn, boolean enlistOrigin) {
366366
return wrap(delegate.exceptionally(fn), origin(enlistOrigin));
367367
}
368+
369+
@Override
370+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, boolean enlistOrigin) {
371+
return handleAsync(SharedFunctions.exceptionallyApply(fn), enlistOrigin);
372+
}
373+
374+
@Override
375+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor, boolean enlistOrigin) {
376+
return handleAsync(SharedFunctions.exceptionallyApply(fn), executor, enlistOrigin);
377+
}
378+
379+
@Override
380+
public DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin) {
381+
return this.handle(SharedFunctions.exceptionallyCompose(fn), enlistOrigin)
382+
.thenCompose(Function.identity(), true);
383+
}
384+
385+
@Override
386+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin) {
387+
return this.handleAsync(SharedFunctions.exceptionallyCompose(fn), enlistOrigin)
388+
.thenCompose(Function.identity(), true);
389+
}
390+
391+
@Override
392+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor, boolean enlistOrigin) {
393+
return this.handleAsync(SharedFunctions.exceptionallyCompose(fn), executor, enlistOrigin)
394+
.thenCompose(Function.identity(), true);
395+
}
396+
368397

369398
public DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action, boolean enlistOrigin) {
370399
return wrap(delegate.whenComplete(action), origin(enlistOrigin));
@@ -562,6 +591,31 @@ public DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn) {
562591
return exceptionally(fn, defaultEnlistOrigin());
563592
}
564593

594+
@Override
595+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
596+
return exceptionallyAsync(fn, defaultEnlistOrigin());
597+
}
598+
599+
@Override
600+
public DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
601+
return exceptionallyCompose(fn, defaultEnlistOrigin());
602+
}
603+
604+
@Override
605+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
606+
return exceptionallyComposeAsync(fn, defaultEnlistOrigin());
607+
}
608+
609+
@Override
610+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
611+
return exceptionallyComposeAsync(fn, executor, defaultEnlistOrigin());
612+
}
613+
614+
@Override
615+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
616+
return exceptionallyAsync(fn, executor, defaultEnlistOrigin());
617+
}
618+
565619
@Override
566620
public DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
567621
return whenComplete(action, defaultEnlistOrigin());

src/main/java/net/tascalate/concurrent/DependentPromise.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ DependentPromise<Void> runAfterEitherAsync(CompletionStage<?> other,
281281

282282
DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn, boolean enlistOrigin);
283283

284+
DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, boolean enlistOrigin);
285+
286+
DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor, boolean enlistOrigin);
287+
288+
DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin);
289+
290+
DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin);
291+
292+
DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor, boolean enlistOrigin);
293+
284294
DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action, boolean enlistOrigin);
285295

286296
DependentPromise<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, boolean enlistOrigin);
@@ -401,6 +411,21 @@ DependentPromise<Void> runAfterEitherAsync(CompletionStage<?> other,
401411
@Override
402412
DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn);
403413

414+
@Override
415+
DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn);
416+
417+
@Override
418+
DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor);
419+
420+
@Override
421+
DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn);
422+
423+
@Override
424+
DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn);
425+
426+
@Override
427+
DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor);
428+
404429
@Override
405430
DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
406431

src/main/java/net/tascalate/concurrent/ExecutorBoundCompletionStage.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,26 @@ public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends Com
175175
public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn) {
176176
return wrap(delegate.exceptionally(fn));
177177
}
178+
179+
public CompletionStage<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
180+
return exceptionallyAsync(fn, defaultExecutor);
181+
}
182+
183+
public CompletionStage<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
184+
return wrap(Promises.exceptionallyApplyAsync(delegate, fn, executor));
185+
}
186+
187+
public CompletionStage<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
188+
return wrap(Promises.exceptionallyCompose(delegate, fn));
189+
}
190+
191+
public CompletionStage<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
192+
return exceptionallyComposeAsync(fn, defaultExecutor);
193+
}
194+
195+
public CompletionStage<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
196+
return wrap(Promises.exceptionallyComposeAsync(delegate, fn, executor));
197+
}
178198

179199
public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
180200
return wrap(delegate.whenComplete(action));

src/main/java/net/tascalate/concurrent/MultitargetException.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,24 @@ public static MultitargetException of(final Throwable exception) {
5252

5353
@Override
5454
public void printStackTrace(PrintStream s) {
55-
super.printStackTrace(s);
56-
printExceptions(s, (ex, padding) -> {
57-
PrintStream ps = new PrintStream(new PaddedOutputStream(s, padding));
58-
ex.printStackTrace(ps);
59-
});
55+
synchronized (s) {
56+
super.printStackTrace(s);
57+
printExceptions(s, (ex, padding) -> {
58+
PrintStream ps = new PrintStream(new PaddedOutputStream(s, padding));
59+
ex.printStackTrace(ps);
60+
});
61+
}
6062
}
6163

6264
@Override
6365
public void printStackTrace(PrintWriter w) {
64-
super.printStackTrace(w);
65-
printExceptions(w, (ex, padding) -> {
66-
PrintWriter pw = new PrintWriter(new PaddedWriter(w, padding), true);
67-
ex.printStackTrace(pw);
68-
});
66+
synchronized (w) {
67+
super.printStackTrace(w);
68+
printExceptions(w, (ex, padding) -> {
69+
PrintWriter pw = new PrintWriter(new PaddedWriter(w, padding), true);
70+
ex.printStackTrace(pw);
71+
});
72+
}
6973
}
7074

7175
private <O extends Appendable> void printExceptions(O out, BiConsumer<Throwable, String> nestedExceptionPrinter) {

src/main/java/net/tascalate/concurrent/Promise.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,26 @@ Promise<Void> runAfterEitherAsync(CompletionStage<?> other,
317317
<U> Promise<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor);
318318

319319
Promise<T> exceptionally(Function<Throwable, ? extends T> fn);
320+
321+
default Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
322+
return handleAsync(SharedFunctions.exceptionallyApply(fn));
323+
}
324+
325+
default Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
326+
return handleAsync(SharedFunctions.exceptionallyApply(fn), executor);
327+
}
328+
329+
default Promise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
330+
return Promises.flatMap(handle(SharedFunctions.exceptionallyCompose(fn)));
331+
}
332+
333+
default Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
334+
return Promises.flatMap(handleAsync(SharedFunctions.exceptionallyCompose(fn)));
335+
}
336+
337+
default Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
338+
return Promises.flatMap(handleAsync(SharedFunctions.exceptionallyCompose(fn), executor));
339+
}
320340

321341
Promise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
322342

src/main/java/net/tascalate/concurrent/Promises.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ public static <T> CompletionStage<T> withDefaultExecutor(CompletionStage<T> stag
109109
return new ExecutorBoundCompletionStage<>(stage, executor);
110110
}
111111

112+
113+
public static <T> Promise<T> flatMap(CompletionStage<? extends CompletionStage<T>> stage) {
114+
return flatMap(from(stage));
115+
}
116+
117+
public static <T> Promise<T> flatMap(Promise<? extends CompletionStage<T>> promise) {
118+
return promise.dependent()
119+
.thenCompose(Function.identity(), true)
120+
.raw();
121+
}
122+
112123
/**
113124
* <p>Returns a promise that is resolved successfully when all {@link CompletionStage}-s passed as parameters
114125
* are completed normally; if any promise completed exceptionally, then resulting promise is resolved faulty
@@ -477,6 +488,26 @@ public static <T> Promise<List<T>> atLeast(int minResultsCount, int maxErrorsCou
477488
}
478489
}
479490

491+
public static <T> CompletionStage<T> exceptionallyApplyAsync(CompletionStage<? extends T> delegate, Function<Throwable, ? extends T> fn) {
492+
return delegate.handleAsync(SharedFunctions.exceptionallyApply(fn));
493+
}
494+
495+
public static <T> CompletionStage<T> exceptionallyApplyAsync(CompletionStage<? extends T> delegate, Function<Throwable, ? extends T> fn, Executor executor) {
496+
return delegate.handleAsync(SharedFunctions.exceptionallyApply(fn), executor);
497+
}
498+
499+
public static <T> Promise<T> exceptionallyCompose(CompletionStage<? extends T> delegate, Function<Throwable, ? extends CompletionStage<T>> fn) {
500+
return flatMap( delegate.handle(SharedFunctions.exceptionallyCompose(fn)) );
501+
}
502+
503+
public static <T> Promise<T> exceptionallyComposeAsync(CompletionStage<? extends T> delegate, Function<Throwable, ? extends CompletionStage<T>> fn) {
504+
return flatMap( delegate.handleAsync(SharedFunctions.exceptionallyCompose(fn)) );
505+
}
506+
507+
public static <T> Promise<T> exceptionallyComposeAsync(CompletionStage<? extends T> delegate, Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
508+
return flatMap( delegate.handleAsync(SharedFunctions.exceptionallyCompose(fn), executor) );
509+
}
510+
480511
public static Promise<Void> retry(Runnable codeBlock, Executor executor,
481512
RetryPolicy<? super Void> retryPolicy) {
482513

src/main/java/net/tascalate/concurrent/SharedFunctions.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ static boolean cancelPromise(CompletionStage<?> promise, boolean mayInterruptIfR
8383
}
8484
}
8585

86+
static <T> BiFunction<T, Throwable, T> exceptionallyApply(Function<Throwable, ? extends T> fn) {
87+
return (r, ex) -> null != ex ? fn.apply(ex) : r;
88+
}
89+
90+
static <T> BiFunction<T, Throwable, Promise<T>> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
91+
return (r, ex) -> ex != null ? Promises.from(fn.apply(ex)) : Promises.success(r);
92+
}
93+
94+
8695
@SuppressWarnings("unchecked")
8796
static <U, V> BiFunction<U, V, U> selectFirst() {
8897
return (BiFunction<U, V, U>)SELECT_FIRST;

src/main/java/net/tascalate/concurrent/decorators/AbstractCompletionStageDecorator.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.function.Function;
2525

2626
import net.tascalate.concurrent.Promise;
27+
import net.tascalate.concurrent.Promises;
2728

2829
/**
2930
* Helper class to create a concrete {@link Promise} subclass via delegation
@@ -184,6 +185,26 @@ public <U> Promise<U> thenComposeAsync(Function<? super T, ? extends CompletionS
184185
public Promise<T> exceptionally(Function<Throwable, ? extends T> fn) {
185186
return wrap(delegate.exceptionally(fn));
186187
}
188+
189+
public Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
190+
return wrap(Promises.exceptionallyApplyAsync(delegate, fn));
191+
}
192+
193+
public Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
194+
return wrap(Promises.exceptionallyApplyAsync(delegate, fn, executor));
195+
}
196+
197+
public Promise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
198+
return wrap(Promises.exceptionallyCompose(delegate, fn));
199+
}
200+
201+
public Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
202+
return wrap(Promises.exceptionallyComposeAsync(delegate, fn));
203+
}
204+
205+
public Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
206+
return wrap(Promises.exceptionallyComposeAsync(delegate, fn, executor));
207+
}
187208

188209
public Promise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
189210
return wrap(delegate.whenComplete(action));

src/main/java/net/tascalate/concurrent/decorators/AbstractDependentPromiseDecorator.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,31 @@ public DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn, bo
381381
return wrap(delegate.exceptionally(fn, enlistOrigin));
382382
}
383383

384+
@Override
385+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, boolean enlistOrigin) {
386+
return wrap(delegate.exceptionallyAsync(fn, enlistOrigin));
387+
}
388+
389+
@Override
390+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor, boolean enlistOrigin) {
391+
return wrap(delegate.exceptionallyAsync(fn, executor, enlistOrigin));
392+
}
393+
394+
@Override
395+
public DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin) {
396+
return wrap(delegate.exceptionallyCompose(fn, enlistOrigin));
397+
}
398+
399+
@Override
400+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, boolean enlistOrigin) {
401+
return wrap(delegate.exceptionallyComposeAsync(fn, enlistOrigin));
402+
}
403+
404+
@Override
405+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor, boolean enlistOrigin) {
406+
return wrap(delegate.exceptionallyComposeAsync(fn, executor, enlistOrigin));
407+
}
408+
384409
@Override
385410
public DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action, boolean enlistOrigin) {
386411
return wrap(delegate.whenComplete(action, enlistOrigin));
@@ -585,6 +610,31 @@ public DependentPromise<T> exceptionally(Function<Throwable, ? extends T> fn) {
585610
return (DependentPromise<T>)super.exceptionally(fn);
586611
}
587612

613+
@Override
614+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
615+
return (DependentPromise<T>)super.exceptionallyAsync(fn);
616+
}
617+
618+
@Override
619+
public DependentPromise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
620+
return (DependentPromise<T>)super.exceptionallyAsync(fn, executor);
621+
}
622+
623+
@Override
624+
public DependentPromise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
625+
return (DependentPromise<T>)super.exceptionallyCompose(fn);
626+
}
627+
628+
@Override
629+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
630+
return (DependentPromise<T>)super.exceptionallyComposeAsync(fn);
631+
}
632+
633+
@Override
634+
public DependentPromise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
635+
return (DependentPromise<T>)super.exceptionallyComposeAsync(fn, executor);
636+
}
637+
588638
@Override
589639
public DependentPromise<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
590640
return (DependentPromise<T>)super.whenComplete(action);

src/main/java/net/tascalate/concurrent/decorators/AbstractPromiseDecorator.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import java.util.Set;
2020
import java.util.concurrent.CancellationException;
2121
import java.util.concurrent.CompletionException;
22+
import java.util.concurrent.CompletionStage;
2223
import java.util.concurrent.Executor;
2324
import java.util.concurrent.TimeUnit;
25+
import java.util.function.Function;
2426
import java.util.function.Supplier;
2527

2628
import net.tascalate.concurrent.DependentPromise;
@@ -165,4 +167,30 @@ public Promise<T> onTimeout(Supplier<? extends T> supplier, Duration duration) {
165167
public Promise<T> onTimeout(Supplier<? extends T> supplier, Duration duration, boolean cancelOnTimeout) {
166168
return wrap(delegate.onTimeout(supplier, duration, cancelOnTimeout));
167169
}
170+
171+
@Override
172+
public Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn) {
173+
return wrap(delegate.exceptionallyAsync(fn));
174+
}
175+
176+
@Override
177+
public Promise<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor) {
178+
return wrap(delegate.exceptionallyAsync(fn, executor));
179+
}
180+
181+
@Override
182+
public Promise<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> fn) {
183+
return wrap(delegate.exceptionallyCompose(fn));
184+
}
185+
186+
@Override
187+
public Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn) {
188+
return wrap(delegate.exceptionallyComposeAsync(fn));
189+
}
190+
191+
@Override
192+
public Promise<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> fn, Executor executor) {
193+
return wrap(delegate.exceptionallyComposeAsync(fn, executor));
194+
}
195+
168196
}

0 commit comments

Comments
 (0)