Hands-On Reactive Programming in Spring 5
上QQ阅读APP看书,第一时间看更新

JDK 9

Likewise, the value of specification was seen by the JDK implementing team too. Not long after the first release of the specification, Doug Lee created a proposal to add the aforementioned interface in JDK 9. The proposal was supported by the fact that the current Stream API offers just a pull model, and a push model was a missing point here:

"…t here is no single best fluent async/parallel API. CompletableFuture/CompletionStage best supports continuation style programming on futures, and java.util.Stream best supports (multi-stage, possibly-parallel) “pull” style operations on the elements of collections. Until now, one missing category was “push” style operations on items as they become available from an active source."
Note that under the hood, the Java Stream API uses Spliterator,  which is nothing more than a modified version of   Iterator, capable of parallel execution. As we might remember, the   Iterator  is not designed for pushing but for pulling over the   Iterator#next method. Similarly,   Spliterator has the  tryAdvance method, which is a combination of the    Iterator's  hasNext  and   next  methods. Consequently, we may conclude that in general the Stream API is pulling-based.

The primary goal of the proposal was to specify interfaces for reactive streams inside JDK. According to the proposal, all interfaces defined in the Reactive Streams specification are provided within the java.util.concurrent.Flow class as static sub-classes. On the one hand, that improvement is significant because Reactive Streams becomes a JDK standard. On the other hand, many vendors have already relied on the specification provided within the org.reactivestreams.* package. Since most vendors (such as RxJava) support several versions of JDK, it is impossible to just implement these interfaces along with the previous ones. Consequently, this improvement manifests an additional requirement to be compatible with JDK 9+ and to somehow convert one specification to another.

Fortunately, the Reactive Streams specification provides an additional module for that purpose, which allows the conversion of Reactive Streams types to JDK Flow types:

...                                                                // (1)
import org.reactivestreams.Publisher; //
import java.util.concurrent.Flow; //
... //

Flow.Publisher jdkPublisher = ...; // (2)
Publisher external = FlowAdapters.toPublisher(jdkPublisher) // (2.1)
Flow.Publisher jdkPublisher2 = FlowAdapters.toFlowPublisher( //
external // (2.2)
); //

The key is as follows:

  1. These are the import definitions. As might be noticed from the imports' statements, we have the import of the Publisher from the original Reactive Streams library and the import of the Flow, which is the access point to all interfaces of Reactive Streams, but ported to JDK 9.
  2. This is the Flow.Publisher instance definition. Here we define the instance of Publisher from the JDK 9. In turn, at point (2.1), we use the FlowAdapters.toPublisher method from the original Reactive Streams library to convert Flow.Publisher to org.reactivestreams.Publisher. Also, for demo purposes, at line (2.2) we use the FlowAdapters.toFlowPublisher method to convert org.reactivestreams.Publisher back to Flow.Publisher.

The preceding example shows how we may easily convert Flow.Publisher to org.reactivestreams.Publisher. It should be noted that the example is unrelated to the real business use-case because there were no well known reactive libraries written from scratch on top of the JDK 9 Flow API at the time this book was published. Consequently, there was no need to migrate from the Reactive Streams specification as the external library that supports JDK 6 and higher. However, in the future, everything will most likely change, and new iterations of reactive libraries will definitely be written on top of the Reactive Streams specification and ported to JDK 9.

Note that the adapter functionality is delivered as a separate library. To see all available libraries, please see the following link: http://www.reactive-streams.org/#jvm-interfaces-completed.