From 95f82b52bd68c28fe05c4cf0d2c9aaa88f358ced Mon Sep 17 00:00:00 2001 From: Julien Viet Date: Wed, 2 Oct 2019 22:23:50 +0200 Subject: [PATCH] Extend Future#compose to allow remapping errors - closes #3144 --- src/main/java/io/vertx/core/Future.java | 37 +++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/vertx/core/Future.java b/src/main/java/io/vertx/core/Future.java index 613f22e40..3bdea6321 100644 --- a/src/main/java/io/vertx/core/Future.java +++ b/src/main/java/io/vertx/core/Future.java @@ -166,7 +166,31 @@ public interface Future extends AsyncResult { * @return the composed future */ default Future compose(Function> mapper) { - if (mapper == null) { + return compose(mapper, Future::failedFuture); + } + + /** + * Compose this future with a {@code successMapper} and {@code failureMapper} functions.

+ * + * When this future (the one on which {@code compose} is called) succeeds, the {@code successMapper} will be called with + * the completed value and this mapper returns another future object. This returned future completion will complete + * the future returned by this method call.

+ * + * When this future (the one on which {@code compose} is called) fails, the {@code failureMapper} will be called with + * the failure and this mapper returns another future object. This returned future completion will complete + * the future returned by this method call.

+ * + * If any mapper function throws an exception, the returned future will be failed with this exception.

+ * + * @param successMapper the function mapping the success + * @param failureMapper the function mapping the failure + * @return the composed future + */ + default Future compose(Function> successMapper, Function> failureMapper) { + if (successMapper == null) { + throw new NullPointerException(); + } + if (failureMapper == null) { throw new NullPointerException(); } Promise ret = Promise.promise(); @@ -174,14 +198,21 @@ public interface Future extends AsyncResult { if (ar.succeeded()) { Future apply; try { - apply = mapper.apply(ar.result()); + apply = successMapper.apply(ar.result()); } catch (Throwable e) { ret.fail(e); return; } apply.setHandler(ret); } else { - ret.fail(ar.cause()); + Future apply; + try { + apply = failureMapper.apply(ar.cause()); + } catch (Throwable e) { + ret.fail(e); + return; + } + apply.setHandler(ret); } }); return ret.future();