Skip to content

Commit d5a5ca5

Browse files
committed
Explain onComplete vs. onSuccess + onFailure
Simplify the code by replacing onComplete + if-ar.succeeded-else with either onComplete(res, e) or with other processing. Avoiding onComplete + if-ar.succeeded-else results in more concise and understandable code because it avoids the additional nesting of the if-else clause. Extend the `exampleFuture*` code to discuss all possibilities how onComplete and onSuccess/onFailure might be used. Remove unused exampleFuture2 from lines 173-186. A new exampleFuture2 is created in line 145.
1 parent 56a122a commit d5a5ca5

File tree

2 files changed

+120
-100
lines changed

2 files changed

+120
-100
lines changed

vertx-core/src/main/asciidoc/futures.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ You cannot interact directly with the result of a future, instead you need to se
1212
{@link examples.CoreExamples#exampleFuture1}
1313
----
1414

15+
Instead of using `onComplete` with `if (ar.succeeded()) { … } else { … }` you can use the `onSuccess` and `onFailure` handlers:
16+
17+
[source,$lang]
18+
----
19+
{@link examples.CoreExamples#exampleFuture2}
20+
----
21+
22+
Frequently the future variable can be avoided. Often the lambda parameter type is not needed by compiler and code readers, allowing to replace `(FileProps fileProps)` with `fileProps`. In a lambda code block with a single statement the semicolon and the curly braces can be removed. This yields a more concise code:
23+
24+
[source,$lang]
25+
----
26+
{@link examples.CoreExamples#exampleFuture3}
27+
----
28+
29+
`.onSuccess` and `.onFailure` can be combined into the two parameter method `.onComplete`. This is slightly faster and takes slightly less memory, but might be less readable:
30+
31+
[source,$lang]
32+
----
33+
{@link examples.CoreExamples#exampleFuture4}
34+
----
35+
1536
[CAUTION]
1637
====
1738
Do not confuse _futures_ with _promises_.

vertx-core/src/main/java/examples/CoreExamples.java

Lines changed: 99 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License 2.0 which is available at
@@ -22,14 +22,17 @@
2222
import io.vertx.core.json.JsonObject;
2323
import io.vertx.core.net.NetClient;
2424
import io.vertx.core.net.NetServer;
25+
import io.vertx.core.net.NetSocket;
2526
import io.vertx.core.net.SocketAddress;
2627
import io.vertx.core.spi.VertxMetricsFactory;
2728
import io.vertx.core.spi.VertxTracerFactory;
2829
import io.vertx.core.spi.cluster.ClusterManager;
2930
import io.vertx.core.transport.Transport;
3031

3132
import java.util.Arrays;
33+
import java.util.Objects;
3234
import java.util.concurrent.TimeUnit;
35+
import java.util.stream.Collectors;
3336

3437
/**
3538
* Created by tim on 08/01/15.
@@ -73,19 +76,17 @@ public void example7(Vertx vertx) {
7376
vertx.executeBlocking(() -> {
7477
// Call some blocking API that takes a significant amount of time to return
7578
return someAPI.blockingMethod("hello");
76-
}).onComplete(res -> {
77-
System.out.println("The result is: " + res.result());
78-
});
79+
})
80+
.onSuccess(result -> System.out.println("The result is: " + result));
7981
}
8082

8183
public void workerExecutor1(Vertx vertx) {
8284
WorkerExecutor executor = vertx.createSharedWorkerExecutor("my-worker-pool");
8385
executor.executeBlocking(() -> {
8486
// Call some blocking API that takes a significant amount of time to return
8587
return someAPI.blockingMethod("hello");
86-
}).onComplete(res -> {
87-
System.out.println("The result is: " + res.result());
88-
});
88+
})
89+
.onSuccess(result -> System.out.println("The result is: " + result));
8990
}
9091

9192
public void workerExecutor2(WorkerExecutor executor) {
@@ -127,7 +128,7 @@ public void clusteredVertxBuilder(VertxOptions options, ClusterManager clusterMa
127128
.buildClustered();
128129
}
129130

130-
public void exampleFuture1(Vertx vertx, Handler<HttpServerRequest> requestHandler) {
131+
public void exampleFuture1(Vertx vertx) {
131132
FileSystem fs = vertx.fileSystem();
132133

133134
Future<FileProps> future = fs.props("/my_file.txt");
@@ -142,6 +143,36 @@ public void exampleFuture1(Vertx vertx, Handler<HttpServerRequest> requestHandle
142143
});
143144
}
144145

146+
public void exampleFuture2(Vertx vertx) {
147+
FileSystem fs = vertx.fileSystem();
148+
149+
Future<FileProps> future = fs.props("/my_file.txt");
150+
151+
future
152+
.onSuccess((FileProps fileProps) -> {
153+
System.out.println("File size = " + fileProps.size());
154+
})
155+
.onFailure((Throwable e) -> {
156+
System.out.println("Failure: " + e.getMessage());
157+
});
158+
}
159+
160+
public void exampleFuture3(Vertx vertx) {
161+
FileSystem fs = vertx.fileSystem();
162+
163+
fs.props("/my_file.txt")
164+
.onSuccess(fileProps -> System.out.println("File size = " + fileProps.size()))
165+
.onFailure(e -> System.out.println("Failure: " + e.getMessage()));
166+
}
167+
168+
public void exampleFuture4(Vertx vertx) {
169+
FileSystem fs = vertx.fileSystem();
170+
171+
fs.props("/my_file.txt")
172+
.onComplete(fileProps -> System.out.println("File size = " + fileProps.size()),
173+
e -> System.out.println("Failure: " + e.getMessage()));
174+
}
175+
145176
public void promiseCallbackOrder(Future<Void> future) {
146177
future.onComplete(ar -> {
147178
// Do something
@@ -170,61 +201,55 @@ public void exampleFutureComposition1(Vertx vertx) {
170201
});
171202
}
172203

173-
public void exampleFuture2(Vertx vertx, Handler<HttpServerRequest> requestHandler) {
174-
FileSystem fs = vertx.fileSystem();
204+
public void exampleFutureComposition2(Vertx vertx) {
175205

176-
Future<FileProps> future = fs.props("/my_file.txt");
206+
FileSystem fs = vertx.fileSystem();
177207

178-
future.onComplete((AsyncResult<FileProps> ar) -> {
179-
if (ar.succeeded()) {
180-
FileProps props = ar.result();
181-
System.out.println("File size = " + props.size());
182-
} else {
183-
System.out.println("Failure: " + ar.cause().getMessage());
184-
}
185-
});
208+
Future<Void> future = fs
209+
.createFile("/foo")
210+
// When the file is created (fut1), execute this:
211+
.compose(v -> fs.writeFile("/foo", Buffer.buffer()))
212+
// When the file is written (fut2), execute this:
213+
.compose(v -> fs.move("/foo", "/bar"));
186214
}
187215

188-
public void exampleFutureAll1(HttpServer httpServer, NetServer netServer) {
216+
public Future<?> exampleFutureAll1(HttpServer httpServer, NetServer netServer) {
189217
Future<HttpServer> httpServerFuture = httpServer.listen();
190218

191219
Future<NetServer> netServerFuture = netServer.listen();
192220

193-
Future.all(httpServerFuture, netServerFuture).onComplete(ar -> {
194-
if (ar.succeeded()) {
195-
// All servers started
196-
} else {
221+
return Future.all(httpServerFuture, netServerFuture)
222+
.onFailure(e -> {
197223
// At least one server failed
198-
}
199-
});
224+
});
200225
}
201226

202227
public void exampleFutureAll2(Future<?> future1, Future<?> future2, Future<?> future3) {
203228
Future.all(Arrays.asList(future1, future2, future3));
204229
}
205230

206-
public void exampleFutureAny1(Future<String> future1, Future<String> future2) {
207-
Future.any(future1, future2).onComplete(ar -> {
208-
if (ar.succeeded()) {
209-
// At least one is succeeded
210-
} else {
231+
public Future<String> exampleFutureAny1(Future<String> future1, Future<String> future2) {
232+
return Future.any(future1, future2)
233+
.map(result -> future1.succeeded() ? future1 : future2) // At least one is succeeded
234+
.onFailure(e -> {
211235
// All failed
212-
}
213-
});
236+
});
214237
}
215238

216239
public void exampleFutureAny2(Future<?> f1, Future<?> f2, Future<?> f3) {
217240
Future.any(Arrays.asList(f1, f2, f3));
218241
}
219242

220-
public void exampleFutureJoin1(Future<?> future1, Future<?> future2, Future<?> future3) {
221-
Future.join(future1, future2, future3).onComplete(ar -> {
222-
if (ar.succeeded()) {
223-
// All succeeded
224-
} else {
225-
// All completed and at least one failed
226-
}
227-
});
243+
public Future<String> exampleFutureJoin1(Future<String> future1, Future<String> future2, Future<String> future3) {
244+
CompositeFuture compositeFuture = Future.join(future1, future2, future3);
245+
246+
return compositeFuture
247+
.map(x -> {
248+
// All completed, each is either succeeded or failed
249+
return compositeFuture.<String>list().stream()
250+
.filter(Objects::nonNull) // failed have null
251+
.collect(Collectors.joining(", "));
252+
});
228253
}
229254

230255
public void exampleFutureJoin2(Future<?> future1, Future<?> future2, Future<?> future3) {
@@ -294,6 +319,16 @@ public void start(Promise<Void> startPromise) throws Exception {
294319
}
295320
});
296321

322+
// Or
323+
future
324+
.onSuccess(x -> startPromise.complete())
325+
.onFailure(startPromise::fail);
326+
327+
// Or
328+
future
329+
.onComplete(x -> startPromise.complete(),
330+
startPromise::fail);
331+
297332
// Or
298333
future
299334
.<Void>mapEmpty()
@@ -334,28 +369,14 @@ public void example9(Vertx vertx) {
334369

335370
}
336371

337-
public void example10(Vertx vertx) {
338-
vertx
372+
public Future<String> example10(Vertx vertx) {
373+
return vertx
339374
.deployVerticle(new MyOrderProcessorVerticle())
340-
.onComplete(res -> {
341-
if (res.succeeded()) {
342-
System.out.println("Deployment id is: " + res.result());
343-
} else {
344-
System.out.println("Deployment failed!");
345-
}
346-
});
375+
.onSuccess(deploymentID -> System.out.println("Deployment id is: " + deploymentID));
347376
}
348377

349378
public void example11(Vertx vertx, String deploymentID) {
350-
vertx
351-
.undeploy(deploymentID)
352-
.onComplete(res -> {
353-
if (res.succeeded()) {
354-
System.out.println("Undeployed ok");
355-
} else {
356-
System.out.println("Undeploy failed!");
357-
}
358-
});
379+
vertx.undeploy(deploymentID);
359380
}
360381

361382
public void example12(Vertx vertx) {
@@ -516,83 +537,61 @@ public void configureBSDOptions(Vertx vertx, boolean reusePort) {
516537
vertx.createHttpServer(new HttpServerOptions().setReusePort(reusePort));
517538
}
518539

519-
public void tcpServerWithDomainSockets(Vertx vertx) {
540+
public Future<NetServer> tcpServerWithDomainSockets(Vertx vertx) {
520541
NetServer netServer = vertx.createNetServer();
521542

522543
// Only available when running on JDK16+, or using a native transport
523544
SocketAddress address = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
524545

525-
netServer
546+
return netServer
526547
.connectHandler(so -> {
527-
// Handle application
548+
// Handle application
528549
})
529-
.listen(address)
530-
.onComplete(ar -> {
531-
if (ar.succeeded()) {
532-
// Bound to socket
533-
} else {
534-
// Handle failure
535-
}
536-
});
550+
.listen(address);
537551
}
538552

539-
public void httpServerWithDomainSockets(Vertx vertx) {
553+
public Future<HttpServer> httpServerWithDomainSockets(Vertx vertx) {
540554
HttpServer httpServer = vertx.createHttpServer();
541555

542556
// Only available when running on JDK16+, or using a native transport
543557
SocketAddress address = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
544558

545-
httpServer
559+
return httpServer
546560
.requestHandler(req -> {
547561
// Handle application
548562
})
549-
.listen(address)
550-
.onComplete(ar -> {
551-
if (ar.succeeded()) {
552-
// Bound to socket
553-
} else {
554-
// Handle failure
555-
}
556-
});
563+
.listen(address);
557564
}
558565

559-
public void tcpClientWithDomainSockets(Vertx vertx) {
566+
public Future<NetSocket> tcpClientWithDomainSockets(Vertx vertx) {
560567
NetClient netClient = vertx.createNetClient();
561568

562569
// Only available when running on JDK16+, or using a native transport
563570
SocketAddress addr = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
564571

565572
// Connect to the server
566-
netClient
567-
.connect(addr)
568-
.onComplete(ar -> {
569-
if (ar.succeeded()) {
570-
// Connected
571-
} else {
572-
// Handle failure
573-
}
574-
});
573+
return netClient
574+
.connect(addr);
575575
}
576576

577-
public void httpClientWithDomainSockets(Vertx vertx) {
577+
private Future<Void> process(Buffer buffer, String parameter) {
578+
return Future.succeededFuture();
579+
}
580+
581+
public Future<Void> httpClientWithDomainSockets(Vertx vertx) {
578582
HttpClient httpClient = vertx.createHttpClient();
579583

580584
// Only available when running on JDK16+, or using a native transport
581585
SocketAddress addr = SocketAddress.domainSocketAddress("/var/tmp/myservice.sock");
582586

583587
// Send request to the server
584-
httpClient.request(new RequestOptions()
588+
return httpClient.request(new RequestOptions()
585589
.setServer(addr)
586590
.setHost("localhost")
587591
.setPort(8080)
588592
.setURI("/"))
589-
.compose(request -> request.send().compose(HttpClientResponse::body))
590-
.onComplete(ar -> {
591-
if (ar.succeeded()) {
592-
// Process response
593-
} else {
594-
// Handle failure
595-
}
596-
});
593+
.compose(request -> request.send())
594+
.compose(HttpClientResponse::body)
595+
.compose(buffer -> process(buffer, "some parameter")); // Process response
597596
}
598597
}

0 commit comments

Comments
 (0)