Provide an overview of Promises in Java and show how powerful they are for solving complex issues with little code.
Communications is error prone. Connections time out, servers fail to respond, returned data can be incomplete or corrupted. Bnd, the OSGi tooling project, has an HttpClient class which is used for communications including with remote repositories like Maven/Nexus and P2 repositories. The Bnd CI builds started having significant failures due to communications problems with the Eclipse download servers, so with some light code restructuring, I was able to add retry support to HttpClient using the Promises package from OSGi. This session will take a look at the Promises package and how it was easily used to recover from communications failures.
3. 3
• A Promise object holds the eventual result of a potentially asynchronous
task.
• A Promise is either unresolved or resolved.
• An unresolved Promise does not have the result of the associated task
available while a resolved Promise has the result of the associated task
available.
• A resolved Promise can be either resolved with a value, which means
the associated task completed successfully and supplied a result, or
resolved with a failure, which means the associated task completed
unsuccessfully and supplied an exception.
9. Chaining Promises
9
• Promises can be chained
• Methods on Promise can return a new Promise chained to the original promise
• Each promise in the chain is used to resolve the next promise in the chain with
some possible mutation of the result/failure
10. Chaining Example
10
Promise<String> name = getDownloadName();
Promise<URL> mirror = name.flatMap(p -> getMirror(p));
Promise<File> file = mirror.flatMap(p -> getFile(p));
Since we probably do not need the intermediate Promises, we can collapse
the chain into a single statement:
Promise<File> file = getDownloadName()
.flatMap(this::getMirror)
.flatMap(this::getFile);
12. Bnd
12
• Bnd is open source tooling to build OSGi bundles
• Bnd provides Eclipse, Maven, and Gradle plugins
• Bnd has support for Maven/Nexus, Eclipse P2, and other remote artifact
repositories
• https://github.com/bndtools/bnd
13. Bnd’s HttpClient
13
• For communications, Bnd has its own HttpClient class
• This is for historical reasons and to minimize dependencies on 3rd party
communications packages
• Recent reliability issues with P2 repositories on Eclipse’s download site caused
us to add retry support to the HttpClient class
• The HttpClient class already had synchronous and asynchronous request
methods
• The asynchronous request method already returns a Promise
14. Changes to add Recovery support
14
• Change async method to add retry support
• Retry count with delay
• Timeout for connection and read hangs
• Server side 5XX errors and IOException failures
• Change sync method to use async method which now has retry support
• Uses a Promise blocking method to synchronously wait for result
• Through the “magic” of Promise chaining, we can further add checksum
validation and checksum failure retry logic
18. CompletableFuture
18
• Introduced in Java 8 and expanded in Java 9
• A promise type in the Java platform but…
• Has a large and unwieldy API
• Odd method names
• Combines resolving promise with using promise
• Mutable
• Promise is a one-way latch – one-time resolve
• CompletableFuture can be resolved repeatedly - obtrude