Sei sulla pagina 1di 56

FACILITATING THE SPREAD OF KNOWLEDGE AND INNOVATION IN PROFESSIONAL SOFTWARE DEVELOPMENT

Reactive
Programming
in Java eMag Issue 48 - Feb 2017

ARTICLE ARTICLE ARTICLE

RxJava by Building Reactive Testing


Example Applications with Akka RxJava
Actors and Java 8
RxJava by Example
In the ongoing evolution of paradigms for simplifying concurrency under load, the
most promising addition is reactive programming, a specification that provides tools
for handling asynchronous streams of data and for managing flow-control, making it
easier to reason about overall program design.

Testing RxJava
You are ready to explore reactive opportunities in
your code but you are wondering how to test out the
reactive idiom in your codebase. In this article Java
Champion Andres Almiray provides techniques and
tools for testing RxJava.

Reactor by Example
Reactor, like RxJava 2, is a fourth generation
reactive library launched by Spring custodian
Pivotal. It builds on the Reactive Streams
specification, Java 8, and the ReactiveX vocabulary.
In this article, we draw a parallel between Reactor
and RxJava, and showcase the common elements as
well as the differences.

Refactoring to Reactive:
Anatomy of a JDBC migration
Reactive programming offers built-in solutions for
Building Reactive some of the most difficult challenges in program-
ming, including concurrency management and flow
Applications with Akka control. So you might ask - how do I get there; can I
Actors and Java 8 introduce it in phases? In this article we transform a
Akka and Java 8 make it possible to create distrib- legacy application to a reactive model using RxJava.
uted microservice-based systems that just a few
years ago were the stuff of dreams. Actor based
systems enable developers to create quickly evolv-
ing microservice architectures that can elastically
scale systems to support huge volumes of data.

FOLLOW US CONTACT US
GENERAL FEEDBACK feedback@infoq.com
ADVERTISING sales@infoq.com
EDITORIAL editors@infoq.com

facebook.com @InfoQ google.com linkedin.com


/InfoQ /+InfoQ company/infoq
VICTOR GRAZI
is the Java queue lead at InfoQ. Inducted as an Oracle
Java Champion in 2012, Victor works in the financial
industry on core platform tools, and as a technical
consultant and Java evangelist. He is also a frequent
presenter at technical conferences. Victor hosts the
“Java Concurrent Animated” and “Bytecode Explorer”
open source projects.

A LETTER FROM
THE EDITOR
As resource consumption requirements increase and dy- Testing RxJava - Andres Almiray
namic content generation takes on new dimensions in We’re ready to explore reactive opportunities in our code
CPU utilization and data sizes, industry has responded but wondering how to test the reactive idiom in our
with non-blocking concurrency in the form of reactive codebase. In this piece, Java Champion Andres Almiray
programming. provides techniques and tools for testing RxJava.

With reactive programming, previously error-prone op-


erations like parking threads and communicating flow Reactor by Example - Simon Basle
control between consumer and provider become trivial. Reactor is Pivotal’s fourth-generation reactive library. It
builds on the Reactive Streams spec, Java 8, and Reac-
There is a learning curve, however, and as we travel the tiveX. In this piece, we showcase what Pivotal’s Reactor
road to mastery, we will find ourselves groping for ves- framework brings to the reactive table.
tiges of traditional programming practices such as test-
ing and refactoring.
Refactoring to Reactive: Anatomy of a JDBC migra-
For this Reactive Java emag, InfoQ has curated a series of tion - Nicolae Marasoiu
articles to help developers hit the ground running with Reactive programming offers built-in solutions for
a comprehensive introduction to the fundamental reac- some of the most difficult challenges in programming,
tive concepts, followed by a case study/strategy for mi- including concurrency management and flow control.
grating your project to reactive, some tips and tools for We might ask how we get there. Can we introduce it in
testing reactive, and practical applications using Akka phases? In this piece, we transform a legacy application
actors. to the reactive model using RxJava.

RxJava by Example - Victor Grazi Building Reactive Applications with Akka Actors and
We start with a gentle progression of examples designed Java 8
to help climb the learning curve. The reactive specifica- Akka and Java 8 make it possible to create distributed
tion provides tools for handling asynchronous streams microservice-based systems that just a few years ago
of data and for managing flow control, making it easier were the stuff of dreams. Actor-based systems allow
to reason about overall program design. developers to create quickly evolving microservice ar-
chitectures that can elastically scale systems to support
We start with the basics and ramp up to flow control and huge volumes of data.
backpressure.
Reactive programming provides the tools for program-
ming highly scalable systems for microservices, Android
applications, and other load and CPU-intensive applica-
tions. We hope this emag will help launch your reactive
career!
Read online on InfoQ

RxJava by Example

by Victor Grazi

In the ongoing evolution of programming paradigms for simplifying


concurrency under load, we have seen the adoption of java.util.
concurrent, Akka streams, CompletableFuture, and frameworks like
Netty. Most recently, reactive programming has been enjoying a burst
of popularity thanks to its power and its robust tool set.

Reactive programming is a algebra with its scalar quantities handling, as in “this is what is
specification for dealing with to linear algebra with its vectors, supposed to happen and here
asynchronous streams of data, matrices, and tensors, essentially are the exceptions.” In reactive,
providing tools for transforming streams of data that are treated exceptions are first-class citizens,
and combining streams and for as a unit. Unlike objects in tradi- treated every bit as such. Since
managing flow control, making it tional programming, the funda- streams are generally  asynchro-
easier to reason about your over- mental unit of reactive reasoning nous, it doesn’t make sense to
all program design. is the stream of events. Events throw an exception, so any ex-
can come in the form of objects, ception is instead passed as an
But easy it is not, and there is defi- data feeds, mouse movements, event in the stream.
nitely a learning curve. It reminds or even exceptions. The word
the mathematicians among us of “exception” expresses the tradi- This article will consider the fun-
the leap from learning standard tional notion of an exceptional damentals of reactive program-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 5


KEY TAKEAWAYS
Reactive programming is a specification for dealing with asynchronous
streams of data.
Reactive provides tools for transforming and combining streams and for
managing flow control.
Marble diagrams provide an interactive canvas for visualizing reactive
constructs.
An Observable resembles the Java Streams API but the resemblance is purely
superficial.
Attach an Observable to hot streams to attenuate and process asynchronous
data feeds.

ming, with a pedagogical eye on Before you try out some exam- we’ll be using in the code sam-
internalizing the important con- ples, include the RxJava depen- ples later in this article.
cepts. dencies in your codebase. You
can load it from Maven using the Observable.just produces an
The first thing to keep in mind dependency: (Code 1) Observable that emits a single
is that in reactive everything is generic instance, followed by a
a stream. The Observable is the The Observable class has doz- complete. For example: (Code 2)
fundamental unit that wraps a ens of static factory methods and
stream. Streams can contain zero operators, each in a wide variety That creates a new Observable
or more events, may or may not of flavors for generating new that emits a single event before
complete, and may or may not Observables, or for attaching completing, the string “Howdy!”
issue an error. Once a stream them to processes of interest.
completes or issues an error, it is Observables are immutable, so We can assign that Observ-
essentially done, although there operators always produce a new able to an Observable variable.
are tools for retrying or substi- Observable. To understand our (Code 3)
tuting different streams when an code examples, let’s review the
exception occurs. basic Observable operators that

<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
<version>2.0.5</version>
</dependency>
Code 1
Observable.just(“Howdy!”)
Code 2
Observable<String> hello = Observable.just(“Howdy!”);
Code 3
Observable<String> howdy = Observable.just(“Howdy!”);
howdy.subscribe(System.out::println);
Code 4
Observable.just(“Hello”, “World”)
.subscribe(System.out::println);
Code 5

6 Reactive Programming in Java // eMag Issue 48 - Feb 2017


Let’s try supplying a list and see
List<String> words = Arrays.asList(
“the”, what happens. (Code 6)
“quick”,
“brown”, This outputs an abrupt:
“fox”,
“jumped”, [the, quick, brown, fox,
“over”, jumped, over, the,
“the”, lazy, dog]
“lazy”,
“dog” We were expecting each word
); as a separate emission, but we
got a single emission consisting
Observable.just(words)
of the whole list. To correct that,
.subscribe(System.out::println);
we invoke the more appropriate
Code 6 fromIterable method. (Code 7)
Observable.fromIterable(words)
.subscribe(System.out::println); The method converts an iterable
Code 7 to a series of events, one per ele-
ment. (Note that in RxJava 1 there
Observable.range(1, 5).subscribe was a single overloaded from
(System.out::println);
method. This has been replaced
outputs:
with several flavors of from  in-
1
2 cluding fromIterable and fro-
3 mArray.)
4
5 Executing that provides the more
Code 8 desirable multiline output:
the
quick
brown
fox
jumped
over
the
lazy
dog
It would be nice to get some
numbering on that — again, a
job for observables.
Figure 1
Before we code that, let’s in-
vestigate two operators, range
and zip. range(i, n) creates
But that by itself won’t get us Like all Observable methods, a stream of n numbers starting
very far, because just like the pro- the just keyword is overloaded with i. (Code 8)
verbial tree that falls in a forest, and so we can also say: (Code 5)
if nobody is around to hear it, it Our problem of adding num-
does not make a sound. An Ob- That puts out: bering  would be solved if we
servable must have a subscrib- had a way to combine the range
Hello
er to do anything with the events stream with our word stream.
World
it emits. Thankfully, Java now has
lambdas, which allow us to ex- just is overloaded for up to 10 RxMarbles is a great site for
press our observables in a con- input parameters. Notice the smoothing the reactive learning
cise declarative style: (Code 4) output is on two separate lines, curve, in any language.  The site
indicating two separate output features interactive JavaScript
That emits a gregarious “Howdy!” events. renderings for many of the re-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 7


Observable.fromIterable(words)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, count)->String.format(“%2d. %s”, count, string))
.subscribe(System.out::println);
Code 9
Observable. fromIterable(words)
.flatMap(word -> Observable.fromArray(word.split(“”)))
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string))
.subscribe(System.out::println);
Code 10
Observable.fromIterable(words)
.flatMap(word -> Observable.fromArray(word.split(“”)))
.distinct()
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string))
.subscribe(System.out::println);
Code 11

active operations. Each uses the ing String.format as our zip into an array of its component
common “marbles” reactive idi- transformation. (Code 9) characters. We will then flatMap
om to depict one or more source those to create a new Observ-
streams and the result stream Which outputs: able that consists of all of the
produced by the operator. Time characters of all of the words.
1. the
passes from left to right, and (Code 10)
2. quick
marbles on the timeline rep- 3. brown
resents events. You can click and 4. fox The output of that is:
drag the source marbles to see 5. jumped
how they affect the result. 1. t ...
6. over
2. h 30. l
7. the
3. e 31. a
A quick perusal reveals the zip 8. lazy
4. q 32. z
operation — just what the doc- 9. dog
5. u 33. y
tor ordered. Let’s look at the mar- 6. i 34. d
ble diagram to understand it bet- Looking good! 7. c 35. o
ter: (Figure 1) 8. k 36. g
Notice that the  zip and zip-
zip combines the elements of With operators stop pulling from All words are present and ac-
the source stream with the el- all of the streams once any of the counted for, but there’s too much
ements of a supplied stream, streams has completed. That is data. We only want the distinct
using a pairwise “zip” transfor- why we were not intimidated by letters so we do this: (Code 11)
mation mapping that you can the Integer.MAX_VALUE  upper
supply in the form of a lambda. limit. That produces:
When either of those streams 1. t
completes, the zipped stream Now, let’s say we want to list not 14. f
2. h
completes, so any remaining the words but the letters com- 15. x
3. e
events from the other stream posing those words. This is a 16. j
4. q
17. m
would be lost. zip accepts up to job for flatMap, which takes the 5. u
18. p
nine source streams and zip op- emissions (objects, collections, 6. i
19. d
erations. There is a correspond- or arrays) from an Observable 7. c
20. v
ing zipWith operator that zips and maps those elements to 8. k
21. l
a provided stream with the exist- individual Observables, then 9. b
22. a
ing stream. flattens the emissions from all of 10. r
23. z
11. o
those into a single Observable. 24. y
12. w
Coming back to our example, we 25. g
13. n
can use range and zipWith to For our example, we will use
prepend our line numbers, us- split to transform each word

8 Reactive Programming in Java // eMag Issue 48 - Feb 2017


.flatMap(word -> Observable.fromIterable(word.split(“”)))
.distinct()
.sorted()
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string))
.subscribe(System.out::println);

Code 12

List<String> words = Arrays.asList(


“the”,
“quick”,
“brown”,
“fox”,
“jumps”,
“over”,
“the”,
“lazy”,
“dog”
);

Observable.fromIterable(words)
.flatMap(word -> Observable.fromArray(word.split(“”)))
.distinct()
.sorted()
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string))
.subscribe(System.out::println);
Code 13

As a child, I was taught that the That yields: nothing more than ways to iter-
“quick brown fox” phrase con- ate collections and produce new
tains every letter in the English 1. a 14. n collections. They are finite, stat-
alphabet but we see that there 2. b 15. o ic, and do not provide for reuse.
are only 25 letters here, not the 3. c 16. p Even when forked by the Streams
full 26. Let’s sort them to locate 4. d 17. q parallel operator, they go off
5. e 18. r
the missing one. (Code 12) and do their own fork and join,
6. f 19. s
and only return when done,
7. g 20. t
That produces: 8. h 21. u leaving the program with little
1. a 9. i 22. v control. Reactive, in contrast, in-
20. u troduces the concepts of timing,
2. b 10. j 23. w
21. v throttling, and flow control, and
3. c 11. k 24. x
22. w they can attach to “infinite” pro-
... 12. l 25. y
23. x
17. q 13. m 26. z cesses that conceivably never
24. y
18. r end. The output is not a collec-
25. z
19. t That’s a lot better! tion but is available for us to deal
with, however we require.
Looks like S is missing. Correct- So far, this all looks similar to the
ing the “quick brown fox” phrase Java Streams API introduced in Let’s take a look at some more
to the actual one (replacing Java 8. The resemblance is strict- marble diagrams to get a better
“jumped” with “jumps”) produces ly coincidental, because reactive picture.
the expected output. (Code 13) adds so much more.
The merge operator merges up to
Java Streams and lambda expres- nine source streams into the final
sions were valuable language ad- output, preserving order. There is
ditions but they are, in essence, no need to worry about race con-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 9


ditions; all events are flattened onto a
single thread, including any exception
and completion events.

The debounce operator treats all


events within a specified time delay as
a single event, emitting only the last in
each such series: (Figure 2)
Figure 2
The difference in time between the
top 1 and the bottom 1 is the time de-
lay. In the 2, 3, 4, 5 pairs, each element
comes more quickly than the time
delay from the previous, so they are
considered one and debounced away.
If we move the top 5 a little bit to the
right so that it falls outside that delay
window, it starts a new debounce win-
Figure 3
dow: (Figure 3)

One interesting operator is the dubi-


ously named “ambiguous” operator
amb and its array incarnation ambAr-
ray.

amb is a conditional operator that se-


lects the first stream to emit from
among all its input streams, and sticks
with that stream, ignoring all the
others. In the following, the second
stream is the first to pump, so the re-
sult selects that stream and stays with
it. (Figure 4) Figure 4
Sliding the 20 in the first stream over
to the left makes the top stream the
earliest producer, thereby altering the
output: (Figure 5)

This is useful, for example, if we have a


process that needs to attach to a feed,
perhaps reaching to several message
topics or, say, to Bloomberg and Re-
uters, and we don’t care which — we
just need to get the earliest one and
stay with it.

Figure 5
Tick tock
Now we have the tools to combine
timed streams to produce a mean-
ingful hybrid. In the next example,
we consider a feed that pumps every
second during the week but, to save
CPU cycles, only pumps every three
seconds during the weekend. We can

10 Reactive Programming in Java // eMag Issue 48 - Feb 2017


private static boolean isSlowTickTime() {
return LocalDate.now().getDayOfWeek() == DayOfWeek.SATURDAY ||
LocalDate.now().getDayOfWeek() == DayOfWeek.SUNDAY;
}
Code 14
private static long start = System.currentTimeMillis();
public static Boolean isSlowTickTime() {
return (System.currentTimeMillis() - start) % 30_000 >= 15_000;
}
Code 15

Observable<Long> fast = Observable.interval(1, TimeUnit.SECONDS);


Observable<Long> slow = Observable.interval(3, TimeUnit.SECONDS);
Code 16
Observable<Long> clock = Observable.merge(
slow.filter(tick-> isSlowTickTime()),
fast.filter(tick-> !isSlowTickTime())
);
Code 17

clock.subscribe(tick-> System.out.println(new Date()));

Code 18

use that hybrid “metronome” to Those readers following along in filtering to schedule and  merge
produce market-data ticks at the an IDE who do not want to wait them.
desired rate. until next weekend/week to see
this work may substitute the fol- We will use the Observable.
First let’s create a boolean meth- lowing implementation, which interval operation, which
od that checks the current time ticks fast for 15 seconds and then generates a tick every specified
and returns “true” for weekends slow for 15 seconds. (Code 15) number of time units (counting
and “false” for weekdays. (Code sequential Longs beginning with
14) Let’s create two Observables, 0). (Code 16)
fast and slow, and then apply
fast will emit an event every
second, slow will emit every
three seconds. (We will ignore
the Long value of the event, as
we are only interested in the tim-
ings.)

Now we can produce our syn-


copated clock by merging those
two Observables and applying
a filter to each that tells the fast
stream to tick on the weekdays
(or for 15 seconds) and the slow
one to tick on the weekends (or
alternate 15 seconds). (Code 17)

Finally, let’s add a subscription


to print the time. Launching this
will print the system date and
time according to our required
schedule. (Code 18)

Reactive Programming in Java // eMag Issue 48 - Feb 2017 11


We will also need a keep alive to prevent this from timing. The distinguishing qualities of cold Observ-
exiting, so add the following to the end of the meth- ables is that they only pump when there is a sub-
od (and handle the InterruptedException). scriber, and all subscribers receive the exact set of
historical data, regardless when they subscribe. Hot
Thread.sleep(60_000) Observables, in contrast, pump regardless of the
number of subscribers and generally pump just the
Running that produces this: latest data to all subscribers (unless some caching
strategy is applied). We can convert cold Observ-
Fri Sep 16 03:08:18 BST 2016 ables to hot by performing both of the following
Fri Sep 16 03:08:19 BST 2016 steps:
Fri Sep 16 03:08:20 BST 2016
Fri Sep 16 03:08:21 BST 2016 1. Call the Observable’s publish method to pro-
Fri Sep 16 03:08:22 BST 2016 duce a new ConnectableObservable.
Fri Sep 16 03:08:23 BST 2016
Fri Sep 16 03:08:24 BST 2016
2. Call the ConnectableObservable’s connect
Fri Sep 16 03:08:25 BST 2016
Fri Sep 16 03:08:26 BST 2016
method to start pumping.
Fri Sep 16 03:08:27 BST 2016
Fri Sep 16 03:08:28 BST 2016 This works but does not support flow control. In
Fri Sep 16 03:08:29 BST 2016 general, we would prefer to connect to existing
Fri Sep 16 03:08:30 BST 2016 long-running feeds with a Flowable, which uses a
Fri Sep 16 03:08:31 BST 2016 parallel syntax to an Observable but also provides
Fri Sep 16 03:08:32 BST 2016 backpressure controls:
Fri Sep 16 03:08:35 BST 2016
Fri Sep 16 03:08:38 BST 2016 1. Call the Flowable’s publish method to produce
Fri Sep 16 03:08:41 BST 2016 a new ConnectableFlowable.
Fri Sep 16 03:08:44 BST 2016
. . .
2. Call the  ConnectableFlowable’s con-
nect method to start pumping.
We can see that the first 15 ticks are a second apart,
followed by 15 seconds of ticks that are three sec- To attach to an existing feed, we could (if we felt so
onds apart, in alternation as required. inclined) add a listener to our feed that propagates
ticks to subscribers by calling their onNext method
on each tick. Our implementation would need to
Attaching to an existing feed ensure that subscribers are still subscribed or stop
This is all very useful for creating Observables from pumping to them, and would need to respect back-
scratch to pump static data. But how do we attach pressure semantics. Thankfully, Flowable’s  cre-
an Observable to an existing feed so we can take ate method performs all that work automatically. For
advantage of the reactive flow control and stream our example, let’s assume we have a SomeFeed mar-
manipulation? ket-data service that issues price ticks and a SomeL-
istener method that listens for those price ticks as
RxJava 2 introduced some new classes we should be- well as lifecycle events. There is an implementation
come acquainted with before proceeding. of these on GitHub if you’d like to try it at home.

Our feed accepts a listener, which supports the fol-


Cold and hot Observables and lowing API. (Code 19)
Flowables
In previous RxJava versions, Observable was
Our PriceTick has acces-
equipped with flow-control methods, even for small
sors for date, instrument,
streams where it would be irrelevant. To conform to
and price, and a method
the reactive specification, RxJava 2 removes flow
for signaling the last tick:
control from the Observable class and introduc-
es the Flowable class, essentially an Observable
Let’s look at an example
that provides flow control.
that connects an Observ-
able to a live feed using a
So far, we have discussed cold Observables: they
Flowable. (Code 20)
provide static data, although we may still regulate

12 Reactive Programming in Java // eMag Issue 48 - Feb 2017


public void priceTick(PriceTick event);
public void error(Throwable throwable);
Code 19
1 SomeFeed<PriceTick> feed = new SomeFeed<>();
2 Flowable<PriceTick> flowable = Flowable.create(emitter -> {
3 SomeListener listener = new SomeListener() {
4 @Override
5 public void priceTick(PriceTick event) {
6 emitter.onNext(event);
7 if (event.isLast()) {
8 emitter.onComplete();
9 }
10 }
11
12 @Override
13 public void error(Throwable e) {
14 emitter.onError(e);
15 }
16 };
17 feed.register(listener);
18 }, BackpressureStrategy.BUFFER);
19 flowable.subscribe(System.out::println);
20
Code 20
21 ConnectableFlowable<PriceTick> hotObservable = flowable.publish();
22 hotObservable.connect();
Code 21
23 hotObservable.subscribe((priceTick) ->
24 System.out.printf(“%s %4s %6.2f%n”, priceTick.getDate(),
25 priceTick.getInstrument(), priceTick.getPrice()));
Code 22

This is taken almost verbatim • BackpressureStrategy. and all subscribers would receive
from the Flowable Javadoc. The ERROR emits a Missing- the same set of historical feeds,
Flowable wraps the steps of BackpressureException if which is probably not what we
creating a listener (line 3) and the downstream can’t keep want.
registering to the service (line up.
17). Subscribers are automati- To convert this to a hot observ-
cally attached by the Flowable. • BackpressureStrategy. able so that all subscribers re-
The events generated by the ser- DROP drops the incoming ceive all notifications as they
vice are delegated to the listener onNext value if the down- occur in real time, we must call
(line 6). Line 18 tells the observer stream can’t keep up. publish and connect, as de-
to buffer all notifications until a scribed earlier. (Code 21)
subscriber consumes them. Oth- • BackpressureStrategy.
er backpressure choices are: LATEST keeps the latest on- Finally, we can subscribe and dis-
Next value and overwrites play our price ticks. (Code 22)
• BackpressureStrategy. it with newer ones until the
MISSING applies no back- downstream can consume it.
pressure. If the stream can’t
keep up, it may throw a All of this produces a cold Flow-
MissingBackpressureEx- able. As with any cold observ-
ception or IllegalState- able, it would produce no ticks
Exception. until the first observer subscribes

Reactive Programming in Java // eMag Issue 48 - Feb 2017 13


Read online on InfoQ

Testing RxJava

Andres Almiray is a Java/Groovy developer and Java Champion with more than 17 years of
experience in software design and development. He has been involved in web and desktop
application development since the early days of Java. He is a true believer in open source and
has participated in popular projects like Groovy, JMatter, Asciidoctor, and more. He is a founding
member and current project lead of the Griffon framework and is spec lead for JSR 377.

You’ve read about RxJava; you’ve played with the samples on the
internet, for example in RxJava by Example, and now you have made
a commitment to explore reactive opportunities in your own code. But
now you are wondering how to test out the new capabilities that you
might find in your codebase.
Reactive programming requires tions, built right into the core subscriptions will, by default, run
a shift in how to reason about a rxjava dependency. on the calling thread, if no partic-
particular problem, because we ular Scheduler is supplied. This
need to focus not on individual means we can setup a Subscrip-
data items but on data flowing as First Steps tion and assert its state immedi-
streams of events. These events Let’s revisit the words example ately after the subscription takes
are often produced and con- from the last article and explore place: (Code 2)
sumed from different threads, how we can test it out. Let’s be-
and so when writing tests we gin by setting up the base test Notice that we used an explicit
must keep aware of concurrency harness using JUnit as our test- List<String> to accumulate our
concerns. Fortunately RxJava2 ing framework: (Code 1) results, along with a real sub-
provides built-in support for test- scriber. Given the simple nature
ing Observables and Subscrip- Our first test will follow a naive of this test you may think that
approach, given the fact that

14 Reactive Programming in Java // eMag Issue 48 - Feb 2017


KEY TAKEAWAYS
RxJava includes built-in, test-friendly solutions.
Use TestSubscriber to verify Observables.
Use TestSubscriber to have strict control of time.
The Awaitility library provides additional control of test context.

using an explicit accumulator as import io.reactivex.Observable;


such is good enough, but remem- import io.reactivex.observers.TestObserver;
ber that production grade ob- import io.reactivex.plugins.RxJavaPlugins;
servables may encapsulate errors import io.reactivex.schedulers.Schedulers;
or produce unexpected events; import org.junit.Test;
the simple subscriber plus accu- import java.util.*;
mulator combo is not sufficient to import static java.util.concurrent.TimeUnit.
SECONDS;
cover those cases. But don’t fret,
import static org.awaitility.Awaitility.await;
RxJava provides a TestObserver
import static org.junit.Assert.assertThat;
type that can be used in such cas- import static org.hamcrest.Matchers.*;
es. Let’s refactor the previous test
using this type (Code 3)
public class RxJavaTest {
TestObserver replaces the cus- private static final List<String> WORDS =
tom accumulator, but it also pro- Arrays.asList(
vides some additional behavior. “the”,
For example it’s capable of tell- “quick”,
ing us how many events were “brown”,
received and the data related to “fox”,
“jumped”,
each event. It can also assert that
“over”,
the subscription was successfully
“the”,
completed and that no errors ap- “lazy”,
peared during the consumption “dog”
of the Observable. The current );
Observable under test does not }
produce any errors, but as we Code 1
learned back in RxJava by Exam-
@Test
ple Observables treat exceptions
public void testInSameThread() {
exactly the same as data events.
// given:
We can simulate an error by con- List<String> results = new ArrayList<>();
catenating an exception event in Observable<String> observable = Observable.
the following way (Code 4) fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
All is well in our limited use case. (string, index) -> String.format(“%2d. %s”,
But actual production code can index, string));
vary greatly, so let’s consider
some more complex production // when:
cases. observable.subscribe(results::add);

// then:
Custom Schedulers assertThat(results, notNullValue());
Quite often you’ll find cases in assertThat(results, hasSize(9));
assertThat(results, hasItem(“ 4. fox”));
production code where Observ-
}
ables are executed on a specific
thread, or “scheduler” in Rx par-
Code 2

Reactive Programming in Java // eMag Issue 48 - Feb 2017 15


@Test
public void testUsingTestObserver() {
// given:
TestObserver<String> observer = new TestObserver<>();
Observable<String> observable = Observable.fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, index) -> String.format(“%2d. %s”, index, string));

// when:
observable.subscribe(observer);

// then:
observer.assertComplete();
observer.assertNoErrors();
observer.assertValueCount(9);
assertThat(observer.values(), hasItem(“ 4. fox”));
}
Code 3

@Test
public void testFailure() {
// given:
TestObserver<String> observer = new TestObserver<>();
Exception exception = new RuntimeException(“boom!”);

Observable<String> observable = Observable.fromIterable(WORDS)


.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, index) -> String.format(“%2d. %s”, index, string))
.concatWith(Observable.error(exception));

// when:
observable.subscribe(observer);

// then:
observer.assertError(exception);
observer.assertNotComplete();
}
Code 4
@Test
public void testUsingComputationScheduler() {
// given:
TestObserver<String> observer = new TestObserver<>();
Observable<String> observable = Observable.fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, index) -> String.format(“%2d. %s”, index, string));

// when:
observable.subscribeOn(Schedulers.computation())
.subscribe(observer);

await().timeout(2, SECONDS)
.until(observer::valueCount, equalTo(9));

// then:
observer.assertComplete();
observer.assertNoErrors();
assertThat(observer.values(), hasItem(“ 4. fox”));
}
Code 5

16 Reactive Programming in Java // eMag Issue 48 - Feb 2017


lance. Many Observable opera- While this approach may be ac- out to 9 events before the 2 sec-
tions take an optional Scheduler ceptable for the trivial code we ond timeout elapses.
parameter as an additional ar- have shown, it may not be prac-
gument. RxJava defines a set of tical for actual production code. Awaitility plays nicely with Ham-
named Schedulers that can be What if the producer takes a long crest matchers, Java 8 lambdas,
used at any time. Some of these time to create all the data? This and method references, thus re-
are io and computation, (which will make the test a slow one, in- sulting in concise and readable
are shared threads) and new- creasing build times. There may conditions. There are also ready
Thread. You can also supply your be other timing issues as well. made extensions for popular
own custom Scheduler imple- Fortunately TestObserver pro- JVM languages such as Groovy
mentation. Let’s change the ob- vides a set of methods that can and Scala.
servable code by specifying the force the test to wait for the ter-
computation Scheduler. (Code 5) mination event. Here’s how it can The final strategy we’ll cov-
be done: (Code 7) er makes use of the extension
You’ll quickly discover there’s mechanism that RxJava exposes
something wrong with this test If that were not enough I’d now as part of its API. RxJava defines
once you run it. The subscriber like to point your attention to a a series of extension points that
performs its assertions on the handy library named Awaitility. enable you to tweak almost ev-
test thread however the Observ- Simply put, Awaitility is a DSL ery aspect of its default behav-
able produces values on a back- that allows you to express expec- ior. This extension mechanism
ground thread (the computation tations about an asynchronous effectively allows us to supply
thread). This means the subscrib- system in a concise and easy to tailor made values for a particu-
er’s assertions may be executed read manner. You can include the lar RxJava feature. We’ll take ad-
before the Observable has pro- Awaitility dependency using Ma- vantage of this mechanism to let
duced all relevant events, result- ven: (Code 8) our test inject a specific Sched-
ing in a failing test. uler regardless of the one speci-
Or using Gradle: fied by the production code. The
There are a few strategies we can behavior we’re looking for is en-
testCompile ‘org.
choose to turn the test green: capsulated in the RxJavaPlugins
awaitility:
• Turn the Observable into a awaitility:2.0.0’
class. Assuming our production
blocking Observable. code relies on the computation()
The entry point of the Awaitility scheduler we’re going to over-
• Force the test to wait until a
DSL is the org.awaitility.Awaitil- ride its default value, returning
certain condition is met.
ity.await() method see lines 13- a Scheduler that makes event
• Switch the computation 14 in the example below). From processing happen in the same
scheduler for an immediate there you can define conditions thread as the caller code; this
one. that must be met in order to let is the Schedulers.trampoline()
the test continue. You may dec- scheduler. Here’s how the test
We’ll cover each strategy starting orate conditions with timeouts looks now: (Code 10)
with the one that requires less ef- and other temporal constraints,
fort: turning the Observable into for example minimum, maximum The production code is unaware
a blocking Observable. This tech- or duration range. Revisiting the that the computation() sched-
nique works regardless of the previous test with Awaitility in uler is an immediate one during
Scheduler in use. The assump- tow results in the following code testing. Please take note that you
tion is that data is produced in (Code 9) must reset the hook otherwise
a background thread, causing the immediate scheduler setting
subscribers to be notified in that This version does not change the may leak, resulting in broken
same background thread. nature of the Observable in any tests all over the place. The usage
way, which allows you to test un- of a try/finally block obscures the
What we’d like to do is force all altered production code without intention of the test code a bit,
events to be produced and the any modification. This version of but fortunately we can refactor
Observable to complete before the test awaits at most 2 seconds out this behavior using a JUnit
the next statement in the test is for the Observable to performs rule, making the test slimmer and
evaluated. This is done by calling its job by checking the state of more readable as a result. Here’s
blockingIterable() on the Observ- the subscriber. If everything goes one possible implementation for
able itself. (Code 6) well, the subscriber’s state checks such a rule (Code 11)

Reactive Programming in Java // eMag Issue 48 - Feb 2017 17


@Test
public void testUsingBlockingCall() {
// given:
Observable<String> observable = Observable.fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, index) -> String.format(“%2d. %s”, index, string));

// when:
Iterable<String> results = observable
.subscribeOn(Schedulers.computation())
.blockingIterable();

// then:
assertThat(results, notNullValue());
assertThat(results, iterableWithSize(9));
assertThat(results, hasItem(“ 4. fox”));
}
Code 6
@Test
public void testUsingComputationScheduler() {
// given:
TestObserver<String> observer = new TestObserver<>();
Observable<String> observable = Observable.fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),

(string, index) -> String.format(“%2d. %s”, index, string));

// when:
observable.subscribeOn(Schedulers.computation())
.subscribe(observer);

observer.awaitTerminalEvent(2, SECONDS);

// then:
observer.assertComplete();
observer.assertNoErrors();
assertThat(observer.values(), hasItem(“ 4. fox”));
}
Code 7
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
Code 8

We override two other schedul- look back what we have accom- • Any Observable can be
er producing methods for good plished so far: turned into a blocking Ob-
measure, making this rule more servable, thus enabling us
generic for other testing pur- • Subscribers process data in to synchronously wait for
poses down the road. Usage of the same thread as long as events to be produced, re-
this rule in a new testcase class there’s no specific Sched- gardless of the Scheduler
is straightforward, we simply de- uler in use. This means we used by the observable.
clare a field with the new type can make assertions on a
annotated with @Rule, like so subscriber right after it sub- • RxJava exposes an extension
(Code 12) scribes to an Observable. mechanism that enables de-
velopers to override its de-
In the end we get the same be- • TestObserver can accumulate faults, and inject those right
havior as before but with less events and provide additional into the production code.
clutter. Let’s take a moment to assertions on its state.

18 Reactive Programming in Java // eMag Issue 48 - Feb 2017


1 @Test
2 public void testUsingComputationScheduler_awaitility() {
3 // given:
4 TestObserver<String> observer = new TestObserver<>();
5 Observable<String> observable = Observable.fromIterable(WORDS)
6 .zipWith(Observable.range(1, Integer.MAX_VALUE),
7 (string, index) -> String.format(“%2d. %s”, index, string));
8
9 // when:
10 observable.subscribeOn(Schedulers.computation())
11 .subscribe(observer);
12
13 await().timeout(2, SECONDS)
14 .until(observer::valueCount, equalTo(9));
15
16 // then:
17 observer.assertComplete();
18 observer.assertNoErrors();
19 assertThat(observer.values(), hasItem(“ 4. fox”));
20 }
Code 9
1 @Test
2 public void testUsingRxJavaPluginsWithImmediateScheduler() {
3 // given:
4 RxJavaPlugins.setComputationSchedulerHandler(scheduler -> Schedulers.
trampoline());
5 TestObserver<String> observer = new TestObserver<>();
6 Observable<String> observable = Observable.fromIterable(WORDS)
7 .zipWith(Observable.range(1, Integer.MAX_VALUE),
8 (string, index) -> String.format(“%2d. %s”, index, string));
9 try {
10
11 // when:
12 observable.subscribeOn(Schedulers.computation())
13 .subscribe(observer);
14
15 // then:
16 observer.assertComplete();
17 observer.assertNoErrors();
18 observer.assertValueCount(9);
19 assertThat(observer.values(), hasItem(“ 4. fox”));
20 } finally {
21 RxJavaPlugins.reset();
22 }
23 }
Code 10
• Awaitility can be used to test data? In other words, what if it look at a subscriber’s state while
out concurrent code using a were possible to programmat- the Observable is still active, in
DSL. ically debug the Observable in other words, we’ll use a white box
place? We’ll see a technique for testing technique. Once again,
Each one of these techniques doing that next. it’s RxJava to the rescue, with its
comes in handy in different sce- TestScheduler class. This partic-
narios, however all them are con- ular Scheduler enables you to
nected by a common thread (pun Playing with Time specify exactly how time passes
intended): the test code waits for So far we’ve tested observables inside of it. You can for example
the Observable to complete be- and subscriptions in a black box advance time by half a second, or
fore making assertions on the manner. Now we’ll have a look at make it leap 5 seconds. We’ll start
subscriber’s state. What if there another technique that allows us by creating an instance of this
was a way to inspect the Observ- to manipulate time in such a way new Scheduler and then pass it
able’s behavior as it produces the that we can pop the hood and to the test code (Code 13)

Reactive Programming in Java // eMag Issue 48 - Feb 2017 19


private static class ImmediateSchedulersRule implements TestRule {
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
RxJavaPlugins.setIoSchedulerHandler(scheduler ->
Schedulers.trampoline());
RxJavaPlugins.setComputationSchedulerHandler(scheduler ->
Schedulers.trampoline());
RxJavaPlugins.setNewThreadSchedulerHandler(scheduler ->
Schedulers.trampoline());

try {
base.evaluate();
} finally {
RxJavaPlugins.reset();
}
}
};
}
}
Code 11
@Rule
public final ImmediateSchedulersRule schedulers = new ImmediateSchedulersRule();

@Test
public void testUsingImmediateSchedulersRule() {
// given:
TestObserver<String> observer = new TestObserver<>();
Observable<String> observable = Observable.fromIterable(WORDS)
.zipWith(Observable.range(1, Integer.MAX_VALUE),
(string, index) -> String.format(“%2d. %s”, index, string));

// when:
observable.subscribeOn(Schedulers.computation())
.subscribe(observer);

// then:
observer.assertComplete();
observer.assertNoErrors();
observer.assertValueCount(9);
assertThat(observer.values(), hasItem(“ 4. fox”));
}
Code 12
The “production” code changed as the scheduler has not moved We next advance time to 9 sec-
a little, as we’re now using an at this point and so no values onds from now. Mind you that
interval that is tied to the Sched- should have been produced by this means moving to exactly
uler to produce the numbering the observable nor received by 9 seconds from the scheduler’s
(line 6) instead of a range. This the subscriber. start, (and not advancing 9 sec-
has the side-effect of producing onds after already advancing
numbers starting with 0 instead Next we move time by one whole 1 before, which would result
of the original 1. Once the Ob- second (line 20), this should in the scheduler looking at 10
servable and the test scheduler cause the Observable to produce seconds after it’s start). In other
are configured we immediately the first value, and that’s exactly words, advanceTimeBy() moves
assert that the subscriber has no what the next set of assertions the scheduler’s time relative to
values (line 16), and has not com- checks (lines 23-25). its current position, whereas ad-
pleted or generated any errors vanceTimeTo()moves the sched-
(line 17). This is a sanity check uler’s time in an absolute fash-

20 Reactive Programming in Java // eMag Issue 48 - Feb 2017


1 @Test
2 public void testUsingTestScheduler() {
3 // given:
4 TestScheduler scheduler = new TestScheduler();
5 TestObserver<String> observer = new TestObserver<>();
6 Observable<Long> tick = Observable.interval(1, SECONDS, scheduler);
7
8 Observable<String> observable = Observable.fromIterable(WORDS)
9 .zipWith(tick,
10 (string, index) -> String.format(“%2d. %s”, index, string));
11
12 observable.subscribeOn(scheduler)
13 .subscribe(observer);
14
15 // expect:
16 observer.assertNoValues();
17 observer.assertNotComplete();
18
19 // when:
20 scheduler.advanceTimeBy(1, SECONDS);
21
22 // then:
23 observer.assertNoErrors();
24 observer.assertValueCount(1);
25 observer.assertValues(“ 0. the”);
26
27 // when:
28 scheduler.advanceTimeTo(9, SECONDS);
29 observer.assertComplete();
30 observer.assertNoErrors();
31 observer.assertValueCount(9);
32 }
Code 13

private static class TestSchedulerRule implements TestRule {


private final TestScheduler testScheduler = new TestScheduler();

public TestScheduler getTestScheduler() {


return testScheduler;
}

@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
RxJavaPlugins.setIoSchedulerHandler(scheduler -> testScheduler);
RxJavaPlugins.setComputationSchedulerHandler(scheduler ->
testScheduler);
RxJavaPlugins.setNewThreadSchedulerHandler(scheduler ->
testScheduler);

try {
base.evaluate();
} finally {
RxJavaPlugins.reset();
}
}
};
}
}
Code 14

Reactive Programming in Java // eMag Issue 48 - Feb 2017 21


@Rule
public final TestSchedulerRule testSchedulerRule = new TestSchedulerRule();

@Test
public void testUsingTestSchedulersRule() {
// given:
TestObserver<String> observer = new TestObserver<>();

Observable<String> observable = Observable.fromIterable(WORDS)


.zipWith(Observable.interval(1, SECONDS),
(string, index) -> String.format(“%2d. %s”, index, string));

observable.subscribeOn(Schedulers.computation())
.subscribe(observer);

// expect
observer.assertNoValues();
observer.assertNotComplete();

// when:
testSchedulerRule.getTestScheduler().advanceTimeBy(1, SECONDS);

// then:
observer.assertNoErrors();
observer.assertValueCount(1);
observer.assertValues(“ 0. the”);

// when:
testSchedulerRule.getTestScheduler().advanceTimeTo(9, SECONDS);
observer.assertComplete();
observer.assertNoErrors();
observer.assertValueCount(9);
}
Code 15
ion. We make another round of the previous code to be rewritten ming capabilities to Java. Ver-
assertions (lines 29-31) to ensure in a more reusable form. First the sion 2.0 has been redesigned
the Observable has produced new rule: (Code 14) to better align its API with the
all data and that the subscriber Reactive Streams specification,
has consumed it all as well. One Followed by the actual test code which provides a standard for
more thing to note about the us- (in a new testcase class), to use asynchronous stream processing
age of TestScheduler is that real our test rule: (Code 15) with non-blocking back pressure,
time moves immediately, which targeting Java and JavaScript
means our test does not have to And there you have it. The usage runtimes. I highly encourage you
wait 9 seconds to complete. of a TestScheduler injected via to review the API changes made
RxJavaPlugins allow you to write since version 2.0; you can find
As you can see using this sched- the test code without altering a detailed description of these
uler is quite handy but it requires the composition of the original changes at the RxJava wiki.
you to supply the scheduler to the Observable yet it gives you the
Observable under test. This will means to modify time and make In terms of testing you’ll see
not play well with Observables assertions at specific points that the core types (Observable,
that use a specific scheduler. But during the execution of the ob- Maybe, and Single) now sport a
wait a second, we saw earlier servable itself. All the techniques handy method named test() that
how we can switch a scheduler showed in this article should give creates a TestObserver instance
without affecting production you enough options to test out for you on the spot. You may now
code using RxJavaPlugins, but RxJava enabled code. chain method calls on TestOb-
this time supplying a TestSched- server and there are some new
uler instead of an immediate assertion methods found on this
scheduler. We can even go so far The Future type, as well.
as to apply the same technique RxJava is one of the first librar-
of a custom JUnit rule, allowing ies to provide reactive program-

22 Reactive Programming in Java // eMag Issue 48 - Feb 2017


Read online on InfoQ

Reactor by Example

Simon Basle is a software-development aficionado, especially interested in reactive


programming, software design aspects (OOP, design patterns, software architecture), rich clients,
what lies beyond code (continuous integration, (D)VCS, best practices), and a bit of computer
science in the form of concurrent programming. He works at Pivotal on Reactor.

RxJava recap ods that create Observables This article will draw a parallel
Reactor, like RxJava 2, is a from static and dynamic sources. between Reactor and what you
fourth-generation reactive li- already learned about RxJava,
brary. Spring custodian Pivotal Observable is the push source and showcase the common ele-
launched Reactor, which builds and Observer is the simple ments as well as the differences.
on the Reactive Streams specifi- interface for consuming this
cation, Java 8, and the ReactiveX source via the act of subscribing.
vocabulary. Its design is the re- Keep in mind that the contract Reactor’s types
sult of a savant mix of designs of an Observable is to notify its Reactor’s two main types are the
and core contributors from pre- Observer of zero or more data Flux<T> and Mono<T>. A Flux is
vious versions and RxJava. items through onNext, option- the equivalent of an RxJava Ob-
ally followed by either an onEr- servable, capable of emitting
In the previous articles in this ror or onComplete terminating zero or more items, and then
eMag, “RxJava by Example”  and event. optionally either completing or
“Testing RxJava”, you learned error-ing.
about the basics of reactive To test an Observable, RxJava
programming: how data is con- provides a TestSubscriber, A Mono, on the other hand, can
ceptualized as a stream, the Ob- which is a special flavor of Ob- emit once at most. It corresponds
servable class and its various server that allows you to assert to both Single and Maybe types
operators, and the factory meth- events in your stream. on the RxJava side. Thus an asyn-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 23


KEY TAKEAWAYS
Reactor is a reactive-streams library that targets Java 8 and provides an Rx-
conforming API.
It uses the same approach and philosophy as RxJava despite some API
differences.
It is a fourth-generation reactive library that allows operator fusion, like
RxJava 2.
Reactor is a core dependency in the reactive-programming-model support of
Spring Framework 5.

chronous task that only wants Build on Rx, with It mainly deals with the concept
to signal completion can use a Reactive Streams at of reactive-pull backpressure
Mono<Void>. every stage (more on that later) and how to
As expressed in “RxJava by Ex- interoperate between several
This simple distinction between ample”, RxJava bears some su- implementing reactive sources.
two types makes things easy to perficial resemblance to the It doesn’t cover operators at all,
grasp while providing meaning- Java 8 Streams API, in terms of focusing instead exclusively on
ful semantics in a reactive API: concepts. Reactor looks a lot the stream’s lifecycle.
by just looking at the returned like RxJava, but this is of course
reactive type, you can know if a in no way a coincidence. The in- A key differentiator for Reactor is
method is more of a “fire and for- tention is to provide a Reactive its RS-first approach. Both Flux
get” or “request-response” (Mono) Streams-native library that ex- and Mono are RS Publisher im-
kind of thing or if it deals with poses an Rx-conforming oper- plementations and conform to
multiple data items as a stream ator API for asynchronous logic reactive-pull backpressure.
(Flux). composition. So while Reactor
is rooted in Reactive Streams, it In RxJava 1, only a subset of oper-
Both Flux and Mono make use seeks general API alignment with ators support backpressure, and
of this semantic by coercing the RxJava where possible. even though RxJava 1 has adapt-
relevant type when using oper- ers to RS types, its Observable
ators. For instance, calling sin- doesn’t implement these types
gle() on a Flux<T> will return Reactive libraries and directly. That is easily explained
a Mono<T>, whereas concatenat- Reactive Streams by the fact that RxJava 1 predates
ing two Monos together using adoption the RS specification; it served as
concatWith will produce a Flux. Reactive Streams (henceforth one of the foundational works
Similarly, some operators will abbreviated “RS”) is, according during the specification’s design.
make no sense on a Mono (for ex- the initiative, means “to pro-
ample take(n), which produces vide a standard for asynchro- That means that each time you
n > 1 results), whereas other op- nous stream processing with use these adapters you are left
erators will only make sense on a non-blocking backpressure.” It with a Publisher, which again
Mono (e.g. or(otherMono)). is a set of textual specifications doesn’t have any operator. In or-
along with a TCK and four sim- der to do anything useful from
One aspect of the Reactor design ple interfaces (Publisher, Sub- there, you’ll probably want to go
philosophy is to keep the API scriber, Subscription, and back to an Observable, which
lean, and this separation into two Processor) that will be integrat- means using yet another adapt-
reactive types is a good middle ed in Java 9. er. This visual clutter can be det-
ground between expressiveness rimental to readability, especially
and API surface. when an entire framework like

24 Reactive Programming in Java // eMag Issue 48 - Feb 2017


Spring 5 directly builds on top of An API similar but not calling concatWith twice) into
Publisher. equal to RxJava’s a single use, only instantiating
The ReactiveX and RxJava vocab- the operator’s inner classes once
Another RxJava 1 difference to ularies of operators can be over- (which is called “macro-fusion”).
keep in mind when migrating to whelming at times and some That includes some data-source-
Reactor or RxJava 2 is that in the operators have confusing names based optimization that greatly
RS specification, null values are for historical reasons. Reactor helps Mono offset the cost of im-
not authorized. This might turn aims to have a more compact plementing Publisher. It is also
out important if your codebase API and to deviate in some cas- capable of sharing resources like
uses null to signal some special es — for example, to choose bet- inner queues between several
cases. ter names — but overall the two compatible operators (called “mi-
APIs look a lot alike. In fact, the cro-fusion”). These capabilities
RxJava 2 was developed after latest iterations of RxJava 2 ac- make Reactor a fourth-genera-
the RS specification and thus di- tually borrow some vocabulary tion reactive library. But that is a
rectly implements Publisher in from Reactor, a hint of the ongo- topic for a future article.
its new Flowable type. But in- ing close collaboration between
stead of focusing exclusively on the two projects. Some operators Let’s take a closer look at a few
RS types, RxJava 2 also keeps the and concepts first appear in one Reactor operators. You will notice
legacy RxJava 1 types (Observ- library or the other but often end the contrast with some of the ex-
able, Completable, and Sin- up in both. amples in the earlier articles in
gle) and introduces the RxJava’s our eMag.
Optional, Maybe. Although they For instance, Flux has the same
still provide the semantic differ- familiar just factory method (al-
entiation we talked about earlier, beit having only two just vari- A few operator examples
these types have the drawback ants: one element and a vararg). This section contains snippets of
of not implementing RS interfac- But from has been replaced by code, and you’re encouraged to
es. Note that unlike in RxJava 1, several explicit variants, most no- try them and experiment further
Observable does not support tably fromIterable. Flux also with Reactor. To that effect, you
the backpressure protocol in has all the usual suspects in term should open your IDE of choice
RxJava 2 (a feature now exclu- of operators: map, merge, con- and create a test project with
sively reserved to Flowable). It cat, flatMap, take, etc. Reactor as a dependency.To do
has been kept for the purpose of so in Maven, add the following
providing a rich and fluent API One RxJava operator name that to the dependencies section of
for cases, such as user-interface Reactor eschewed was the puz- your pom.xml: (Code 1)
event-ing, where backpressure is zling amb operator, which has
impractical or impossible. Com- been replaced with the more Let’s play with the examples used
pletable, Single, and Maybe appropriately named firstEmit- in the previous articles in this
by design have no need for back- ting. Additionally, to intro- eMag.
pressure support; they will offer a duce greater consistency in the
rich API and defer any workload API, toList has been renamed Similarly to how you would cre-
until subscribed. collectList. In fact, all col- ate your first Observable in Rx-
lectXXX operators now aggre- Java, you can create a Flux using
Reactor is once again leaner gate values into a specific type the just(T…) and fromIter-
in this area, sporting Mono and of collection but still produce able(Iterable<T>) Reactor
Flux types that both implement a Mono of said collection, while factory methods. Remember that
Publisher and are backpres- toXXX methods are reserved for given a List, just would only
sure-ready. There’s a relatively type conversions that take you emit the list as one whole, single
small overhead for Mono to be- out of the reactive world — for emission, while fromIterable
have as a Publisher, but it is example, toFuture(). will emit, as its name suggests,
mostly offset by other Mono opti- each element from the iterable
mizations. We’ll see in a later sec- One more way Reactor can be list. (Code 2)
tion what backpressure means leaner, this time in terms of class
for Mono. instantiation and resource us- Like in the corresponding RxJava
age, is fusion: Reactor is capable examples, this prints: (Code 3)
of merging multiple sequential
uses of certain operators (e.g.

Reactive Programming in Java // eMag Issue 48 - Feb 2017 25


<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
To do the same in Gradle, edit the dependencies section to add reactor, similarly to
this:
dependencies {
compile “io.projectreactor:reactor-core:3.0.3.RELEASE”
}
Code 1

public class ReactorSnippets {


private static List<String> words = Arrays.asList(
“the”,
“quick”,
“brown”,
“fox”,
“jumped”,
“over”,
“the”,
“lazy”,
“dog”
);

@Test
public void simpleCreation() {
Flux<String> fewWords = Flux.just(“Hello”, “World”);
Flux<String> manyWords = Flux.fromIterable(words);

fewWords.subscribe(System.out::println);
System.out.println();
manyWords.subscribe(System.out::println);
}
}
Code 2
Hello
World
the
quick
brown
fox
jumped
over
the
lazy
dog
Code 3
@Test
public void findingMissingLetter() {
Flux<String> manyLetters = Flux
.fromIterable(words)
.flatMap(word -> Flux.fromArray(word.split(“”)))
.distinct()
.sort()
.zipWith(Flux.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string));

manyLetters.subscribe(System.out::println);
}
Code 4

26 Reactive Programming in Java // eMag Issue 48 - Feb 2017


@Test
public void restoringMissingLetter() {
Mono<String> missing = Mono.just(“s”);
Flux<String> allLetters = Flux
.fromIterable(words)
.flatMap(word -> Flux.fromArray(word.split(“”)))
.concatWith(missing)
.distinct()
.sort()
.zipWith(Flux.range(1, Integer.MAX_VALUE),
(string, count) -> String.format(“%2d. %s”, count, string));

allLetters.subscribe(System.out::println);
}
Code 5

@Test
public void shortCircuit() {
Flux<String> helloPauseWorld =
Mono.just(“Hello”)
.concatWith(Mono.just(“world”)
.delaySubscriptionMillis(500));

helloPauseWorld.subscribe(System.out::println);
}
Code 6
1. a
2. b
...
18. r
19. t
20. u
...
25. z
Code 7
1. a
2. b
...
18. r
19. s
20. t
...
26. z
Code 8
1. a
2. b
...
18. r
19. s
20. t
...
26. z
In order to output the individual This adds the missing S just be- because the test terminates too
letters in the “quick brown fox” fore we filter out duplicates and early. In snippets and tests where
sentence, you also need flat- sort/count the letters: (Code 8) you only sort of write a main class
Map (as you did in “RxJava by Ex- like this, you’ll usually want to re-
ample”), but in Reactor, you use The previous article noted the vert to blocking behavior. To do
fromArray instead of from. You resemblance between the Rx vo- that, you could create a Count-
then want to filter out duplicate cabulary and the Java Streams DownLatch and call countDown
letters and sort what’s left over API and, in fact, when the data is in your subscriber (both in onEr-
using distinct and sort. Final- readily available from memory, ror and onComplete). But that’s
ly, you want to output an index Reactor, like Java Streams, acts not very reactive, is it? And what
for each distinct letter, which in simple push mode (see the if you forget to count down, be-
can be done using zipWith and backpressure section below to cause of error for instance?
range: (Code 4) understand why). More complex
and truly asynchronous snippets A second way to solve that issue
This helps us notice missing S, as wouldn’t work with this pattern is to use one of the operators
expected: (Code 7) of just subscribing in the main that revert to the non-reactive
thread, primarily because control world. Specifically, toIterable
One way of fixing that is to cor- would return to the main thread and toStream will both produce
rect the original words array, but and then exit the application as a blocking instance. Let’s use to-
we could also manually add the S soon as the subscription is done. Stream in an example: (Code 9)
value to the Flux of letters using For instance: (Code 6)
concat/concatWith and a Mono: As you would expect, this prints
(Code 5) This snippet prints “Hello” but “Hello”, pauses, then prints
fails to print the delayed “world” “world’ and terminates.

Reactive Programming in Java // eMag Issue 48 - Feb 2017 27


@Test
public void blocks() {
Flux<String> helloPauseWorld =
Mono.just(“Hello”)
.concatWith(Mono.just(“world”)
.delaySubscriptionMillis(500));

helloPauseWorld.toStream()
.forEach(System.out::println);
}
Code 9

@Test
public void firstEmitting() {
Mono<String> a = Mono.just(“oops I’m late”)
.delaySubscriptionMillis(450);
Flux<String> b = Flux.just(“let’s get”, “the party”, “started”)
.delayMillis(400);

Flux.firstEmitting(a, b)
.toIterable()
.forEach(System.out::println);
}
Code 10

<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-starter-web-reactive</artifactId>
</dependency>
Code 11

As we mentioned above, Reac- don’t want to wait four seconds es like Func1, Func2, Action0,
tor renamed RxJava’s amb() op- in a unit test! Fortunately, as we’ll Action1, etc. were required in-
erator to firstEmitting, which see in a later section, Reactor stead. In RxJava 2, these classes
more clearly hints at the opera- comes with powerful testing ca- mirror java.util.function
tor’s purpose: selecting the first pabilities that nicely cover this the way Reactor 2 used to do
Flux to emit. The following ex- case. when it still had to support Java
ample creates a Mono, delays it by 7.
450 ms, and creates a Flux that Having sampled how Reactor
emits its values with a 400 ms compares for a few common op- The Reactor API also embraces
pause before each value. When erators, let’s zoom back and have types introduced in Java 8. Most
firstEmitting() them togeth- a look at other differentiating as- of the time-related operators will
er, the first value from the Flux pects of the library. refer to durations (e.g. timeout,
comes in before the Mono val- interval, delay, etc.) so using
ue so it is the Flux that ends up the Java 8 Duration class is ap-
played. (Code 10) A Java 8 foundation propriate.
Reactor targets Java 8 rather
This prints each part of the sen- than previous Java versions. This The Java 8 Streams API and
tence with a 400-ms pause be- again aligns with the goal of re- CompletableFuture can also
tween each section. ducing the API surface: RxJava both be easily converted to a
targets Java 6 where there is no Flux/Mono and vice versa. But
At this point, you might wonder, java.util.function package you shouldn’t usually convert a
what if you’re writing a test for so you can’t take advantage of Stream to a Flux. The level of in-
a Flux that introduces delays classes like Function or Con- direction added by Flux or Mono
of 4000 ms instead of 400? You sumer. Specific, additional class- is a negligible cost when they

28 Reactive Programming in Java // eMag Issue 48 - Feb 2017


decorate more expensive opera- cesses an asynchronous result is ean) and exposing that data as a
tions like I/O or memory-bound already executing. On the other Mono. In that case, the backpres-
operations, but most of the time hand, a Flux or Mono with back- sure signaled upstream is Long.
a Stream doesn’t imply that kind pressure enables a deferred pull- MAX_VALUE, which lets the up-
of latency and it is perfectly okay push interaction: stream work in a fully push fash-
to use the streams API directly. ion.
Note that you’d use the Observ- • “deferred” because nothing
able for these use cases in RxJa- happens before the call to Another interesting aspect of
va 2, as the Observable has no subscribe(); backpressure is how it natural-
backpressure and thus becomes ly limits the amount of objects
a simple push once you’ve sub- • “pull” because at the sub- held in memory by the stream.
scribed. But Reactor is based on scription and request steps, As a Publisher, the source of
Java 8, and the Java 8 Streams the Subscriber will send data is most probably slow (or
API is expressive enough for a signal upstream to the at least slow-ish) at produc-
most use cases. Even though you source and essentially pull ing items, so the request from
can find Flux and Mono factories the next chunk of data; and downstream can very well start
for literal or simple objects, they beyond the number of readily
mostly exist to be combined in • “push” from producer to con- available items. In this case, the
higher-level flows. You typical- sumer from there on, within whole stream naturally falls into
ly wouldn’t want to transform the boundary of the number a push pattern by which it noti-
an accessor like “long get- of requested elements. fies the consumer of new items.
Count()” into a “Mono<Long> But when production acceler-
getCount()” when migrating For Mono, subscribe() is the ates, things nicely fall back into a
an existing codebase to reactive button that you press to say pull model. In both cases, at most
patterns. you’re ready to receive data. For N data (the request() amount)
Flux, this button is request(n), is kept in memory.
which is kind of a generalization
The backpressure story of the former. You can reason about the mem-
One of the main focuses (if not ory used by your asynchronous
the main focus) of the RS spec- Realizing that Mono is a Publish- processing by correlating that
ification and of Reactor itself is er that will usually represent a demand for N with the number
backpressure. The idea of back- costly task (in terms of I/O, laten- W of kilobytes an item consumes:
pressure is that in a push scenar- cy, etc.) is critical to understand- you can then infer that iut will
io where the producer is quicker ing the value of backpressure consume at most W*N memory.
than the consumer, there’s value here: if you don’t subscribe, you In fact, Reactor will usually take
in letting the consumer signal the don’t pay the cost of that task. advantage of knowing N to apply
producer to ask it to slow down Since Mono will often orchestrate optimizations: creating queues
because it’s being overwhelmed. with regular back-pressured bounded accordingly and apply-
This gives the producer a chance Flux within a reactive chain, ing prefetching strategies where
to control its pace rather than possibly combining results from it can automatically request 75%
having to resort to discarding multiple asynchronous sources, of N every time it receives that
data (sampling) or, worse, to risk the availability of this on-de- same three-quarters of it.
a cascading failure. mand subscribe triggering is key
for avoiding blocking. Finally, Reactor operators will
You may wonder how backpres- sometimes change the back-
sure applies to Mono: what kind Having backpressure helps to pressure signal to correlate it
of consumer could possibly be differentiate that last Mono use with the expectations and se-
overwhelmed by a single emis- case from another broad use mantics they represent. One
sion? The short answer is that case: asynchronously aggre- prime example of this behavior
probably none exists. However, gating data from a Flux into a would be buffer(10): for every
there’s still a key difference be- Mono. Operators like reduce and request of N from downstream,
tween how a Mono works and hasElement are capable of con- that operator would request 10 N
how a CompletableFuture suming each item in the Flux, from upstream, which represents
works. The latter is push only: if aggregating some form of data enough data to fill the number
you have a reference to the Fu- about it (respectively, the result of buffers the subscriber is ready
ture, it means the task that pro- of a reduce function and a bool- to consume. This is called “active

Reactive Programming in Java // eMag Issue 48 - Feb 2017 29


backpressure” and it can be put future Spring applications and Although Spring APIs are based
to good use by developers in or- in the APIs these various Spring on Reactor types, the Spring Web
der to explicitly tell Reactor how components expose. More gen- Reactive module lets you use var-
to switch from an input volume erally, they’ll be able to deal ious reactive types for both the
to a different output volume, in with RS Publishers, but most request and response:
micro-batching scenarios for in- of the time these will happen
stance. to be Flux or Mono, bringing in • Mono<T>: As the @Request-
the rich feature set of Reactor. Body, the request entity T
Of course, you will be able to use is asynchronously deseri-
Relation to Spring any reactive library you choose, alized and you can chain
Reactor is the reactive founda- as the framework provides hooks your processing to the re-
tion for the whole Spring ecosys- for  adapting between Reactor sulting Mono afterward. As
tem, and most notably Spring 5 types and RxJava types or even the return type, once the
(through Spring Web Reactive) simpler RS types. Mono emits a value, the T
and Spring Data Kay (which cor- is serialized asynchronous-
responds to Spring Data Com- By the writing of this article, you ly and sent back to the cli-
mons 2.0). can already experiment with ent. You can combine both
Spring Web Reactive in Spring approaches by augmenting
Having a reactive version for Boot by using Spring Boot’s the request Mono and return-
both of these projects is essential 2.0.0.BUILD-SNAPSHOT and ing that augmented chain
in the sense that this allows you the spring-boot-starter- as the resulting Mono.
to write a web application that web-reactive dependency (e.g.
is reactive from start to finish: a by generating such a project on • Flux<T>: Use this in stream-
request comes in, it is asynchro- start.spring.io). (Code 11) ing scenarios (including
nously processed all the way input streaming when as
down to and including the da- This lets you write your @Con- @RequestBody and serv-
tabase, and results come back troller mostly as usual, but er-sent events with a Flux-
asynchronously as well. This al- replaces the underlying Spring <ServerSentEvent> return
lows a Spring application to be MVC traditional layer with a re- type.Single / Observable :
efficient with resources, avoiding active one, replacing many of the This works for Mono and
the usual pattern of dedicating a Spring MVC contracts with reac- Flux respectively but
thread to a request and blocking tive non-blocking ones. By de- switches to a RxJava imple-
it for I/O. fault, this reactive layer is based mentation.
on top of Tomcat 8.5, but you can
So Reactor is going to be used for also elect to use Undertow or • Mono<Void> as a return
the internal reactive plumbing of Netty. type: Request handling

30 Reactive Programming in Java // eMag Issue 48 - Feb 2017


@RestController
public class ExampleController {

private final MyReactiveLibrary reactiveLibrary;

//Note Spring Boot 4.3+ autowires single constructors now


public ExampleController(MyReactiveLibrary reactiveLibrary) {
this.reactiveLibrary = reactiveLibrary;
}

@GetMapping(“hello/{who}”)
public Mono<String> hello(@PathVariable String who) {
return Mono.just(who)
.map(w -> “Hello “ + w + “!”);
}

@GetMapping(“helloDelay/{who}”)
public Mono<String> helloDelay(@PathVariable String who) {
return reactiveLibrary.withDelay(“Hello “ + who + “!!”, 2);
}

@PostMapping(“heyMister”)
public Flux<String> hey(@RequestBody Mono<Sir> body) {
return Mono.just(“Hey mister “)
.concatWith(body
.flatMap(sir -> Flux.fromArray(sir.getLastName().split(“”)))
.map(String::toUpperCase)
.take(1)
).concatWith(Mono.just(“. how are you?”));
}
}
Code 12

completes when the Mono name to a greeting sentence that This returns the string “Hello mis-
completes. is returned to the client. ter T. How are you?”

• Non-reactive return types By doing a GET on /hello/Si- The reactive aspect of Spring
(void and T): These now mon we get “Hello Simon!”  as a Data is also currently being de-
imply that your controller text response. veloped in the Kay release train,
method is synchronous, which for Spring Data Commons
but should be non-blocking The second endpoint is a bit is the 2.0.x branch. There is a first
(short-lived processing). more complicated: it asynchro- milestone build that you can
The request handling fin- nously receives a serialized Sir get by adding the Spring Data
ishes once the method is instance (a class simply made Kay-M1 bill of materials (BOM) to
executed. The returned T is up of a firstName and lastName your pom: (Code 13)
serialized back to the client attributes) and flatMaps it into a
asynchronously. stream of the last name’s letters. For this simplistic example, just
It then takes the first of these let- add the spring-data-commons
Here is a quick example of a ters, maps it to upper case and dependency in your pom (it will
plain-text @Controller that concatenates it into a greeting take the version from the BOM
uses the experimental web reac- sentence. above): (Code 14)
tive module: (Code 12)
So make the following JSON ob- Reactive support in Spring Data
The first endpoint takes a path ject POST to /heyMister: revolves around the new Reac-
variable, transforms it into a { tiveCrudRepository<T, ID>
Mono<String> and maps that “firstName”: “Paul”, interface, which extends Repos-
“lastName”: “tEsT” itory<T, ID>. This interface
}

Reactive Programming in Java // eMag Issue 48 - Feb 2017 31


<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Kay-M1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
Code 13
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
Code 14
@RestController
public class DataExampleController {

private final ReactiveCrudRepository<Sir, String> reactiveRepository;

//Note Spring Boot 4.3+ autowires single constructors now


public DataExampleController(ReactiveCrudRepository<Sir, String> repo) {
this.reactiveRepository = repo;
}

@GetMapping(“data/{who}”)
public Mono<ResponseEntity<Sir>> hello(@PathVariable String who) {
return reactiveRepository.findOne(who)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.status(404).body(null));
}
}
Code 15

exposes CRUD methods, using Assuming a reactive backing Testing Reactor


Reactor input and return types. store (or a mock Reactive- “Testing RxJava” covered tech-
There is also an RxJava 1-based CrudRepository bean), the niques for testing an Observ-
version called RxJava1CrudRe- following (very naive) controller able. As we saw, RxJava comes
pository. For instance, in the would be reactive from start to with a TestScheduler that you
classical blocking CrudRepos- finish: (Code 15) can use with operators that ac-
itory, retrieving one entity by cept a Scheduler as a parameter,
its id would be done using “T Notice how the data-repository to manipulate a virtual clock on
findOne(ID id)”. It becomes usage naturally flows into the re- these operators. It also features
“Mono<T> findOne(ID id)” and sponse path: we asynchronously a TestSubscriber class that
“Observable<T> findOne(ID fetch the entity and wrap it as can be leveraged to wait for the
id)” in ReactiveCrudReposi- a ResponseEntity using map, completion of an Observable
tory and RxJava1CrudReposi- obtaining a Mono we can return and to make assertions about ev-
tory respectively. There are even right away. If the Spring Data re- ery event (number and values for
variants that take a Mono/Single pository cannot find data for this onNext, has onError triggered,
as argument, to asynchronously key, it will return an empty Mono. etc.) In RxJava 2, the TestSub-
provide the key and compose on We make that explicit by using scriber is an RS Subscriber, so
that. defaultIfEmpty and returning you can test Reactor’s Flux and
a 404. Mono with it!

32 Reactive Programming in Java // eMag Issue 48 - Feb 2017


<dependency>
<groupId>io.projectreactor.addons</groupId>
<artifactId>reactor-test</artifactId>
<version>3.0.3.RELEASE</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.5.2</version>
<scope>test</scope>
</dependency>
Code 16

@Component
public class MyReactiveLibrary {

public Flux<String> alphabet5(char from) {


return Flux.range((int) from, 5)
.map(i -> “” + (char) i.intValue());
}

public Mono<String> withDelay(String value, int delaySeconds) {


return Mono.just(value)
.delaySubscription(Duration.ofSeconds(delaySeconds));
}
}
Code 17

@Test
public void testAlphabet5LimitsToZ() {
MyReactiveLibrary library = new MyReactiveLibrary();
StepVerifier.create(library.alphabet5(‘x’))
.expectNext(“x”, “y”, “z”)
.expectComplete()
.verify();
}
Code 18

In Reactor, these two broad fea- implementation, making obso- cate or even consume onNext
tures are combined into the lete the need to explicitly pass events, allowing you to do more
StepVerifier class. It can be the scheduler to operators. The advanced interactions with the
found in the add-on module StepVerifier will then, if nec- value (like using an assertion
reactor-test from the reac- essary, configure the Flux/Mono library). Any AssertionError
tor-addons repository. You can created within the Supplier, thrown by one of these will be
initialize the StepVerifier by turning timed operators into “vir- reflected in the final verification
creating an instance from any tually timed” operators. You can result. Finally, call verify() to
Publisher, using the StepVer- then script stream expectations check your expectations; this will
ifier.create builder. For virtual and time progress: what the truly subscribe to the defined
time, you can use the StepVer- next elements should be, should source via StepVerifier.cre-
ifier.withVirtualTime build- there be an error, should it move ate or StepVerifier.withVir-
er, which takes a Supplier<- forward in time, etc. tualTime.
Publisher>. This will create a
VirtualTimeScheduler and Other methods include verifying Let’s take a few simple examples
enable it as the default scheduler that data match a given Predi- and demonstrate how StepVer-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 33


@Test
public void testAlphabet5LastItemIsAlphabeticalChar() {
MyReactiveLibrary library = new MyReactiveLibrary();
StepVerifier.create(library.alphabet5(‘x’))
.consumeNextWith(c -> assertThat(c)
.as(“first is alphabetic”).matches(“[a-z]”))
.consumeNextWith(c -> assertThat(c)
.as(“second is alphabetic”).matches(“[a-z]”))
.consumeNextWith(c -> assertThat(c)
.as(“third is alphabetic”).matches(“[a-z]”))
.consumeNextWith(c -> assertThat(c)
.as(“fourth is alphabetic”).matches(“[a-z]”))
.expectComplete()
.verify();
}
Code 19

java.lang.AssertionError: expected: onComplete(); actual: onNext({)


and
java.lang.AssertionError: [fourth is alphabetic]
Expecting:
“{“
to match pattern:
“[a-z]”
Code 20

@Test
public void testWithDelay() {
MyReactiveLibrary library = new MyReactiveLibrary();
Duration testDuration =
StepVerifier.withVirtualTime(() -> library.withDelay(“foo”, 30))
.expectSubscription()
.thenAwait(Duration.ofSeconds(10))
.expectNoEvent(Duration.ofSeconds(10))
.thenAwait(Duration.ofSeconds(10))
.expectNext(“foo”)
.expectComplete()
.verify();
System.out.println(testDuration.toMillis() + “ms”);
}
Code 21

ifier works. For these snippets, emits a given value after a given It turns out that both of these
you’ll want to add the following delay (in seconds). tests fail. A look at the StepVer-
test dependencies to your pom: ifier output of each case may
(Code 16) The first test to write ensures that help you spot the bug. (Code 20)
calling alphabet5 from X limits
First, imagine you have reactive the output to X, Y, and Z. With So it looks like this method
class called MyReactiveLibrary StepVerifier it would go like this: doesn’t stop at Z but continues
that produces a few instances of (Code 18) emitting characters along the
Flux that you want to test. (Code ASCII range. We could fix that by
17) The second test to run on alpha- adding a .take(Math.min(5,
bet5 is that every returned value ‘z’ - from + 1)), for instance,
The first method is intended to is an alphabetical character. For or using the same Math.min as
return five letters of the alpha- that we’d like to use a rich asser- the second argument to range.
bet following (and including) tion library like AssertJ: (Code 19)
the given starting letter. The sec- The last test to make involves
ond method returns a Flux that manipulating virtual time: you’ll

34 Reactive Programming in Java // eMag Issue 48 - Feb 2017


SomeFeed<PriceTick> feed = new SomeFeed<>();
Flux<PriceTick> flux =
Flux.create(emitter ->
{
SomeListener listener = new SomeListener() {
@Override
public void priceTick(PriceTick event) {
emitter.next(event);
if (event.isLast()) {
emitter.complete();
}
}

@Override
public void error(Throwable e) {
emitter.error(e);
}};
feed.register(listener);
}, FluxSink.OverflowStrategy.BUFFER);

ConnectableFlux<PriceTick> hot = flux.publish();


Code 22

hot.subscribe(priceTick -> System.out.printf(“%s %4s %6.2f%n”, priceTick


.getDate(), priceTick.getInstrument(), priceTick.getPrice()));

hot.subscribe(priceTick -> System.out.println(priceTick.getInstrument()));


We then connect to the hot flux and let it run for 5 seconds before our test snippet
terminates:
hot.connect();
Thread.sleep(5000);
Code 23

test the delaying method with- but would block for the provided chronous corner cases and let
out actually waiting for the giv- duration. you focus on emitting your val-
en amount of seconds by using ues.
the withVirtualTime builder: StepVerifier comes with many
(Code 21) more methods for describing Use Flux.create and get a
expectations and asserting the FluxSink in the callback that
This tests a Flux that would be state of a Publisher (and if you you can use to emit data via
delayed by 30 seconds in the sce- think about new ones, contribu- next. This custom Flux can be
nario of an immediate subscrip- tions and feedback are always cold; in order to make it hot, you
tion followed by three periods welcome in the GitHub reposito- can use publish() and con-
of 10 seconds in which nothing ry). nect(). Building on the example
happens, an onNext(“foo”), from the previous article with a
and completion. feed of price ticks, we get an al-
Custom hot source most verbatim translation in Re-
The System.out output prints The concepts of hot and cold Ob- actor. (Code 22)
the duration of the verification servables discussed at the end
process (which in my latest run of “RxJava by Example” also apply Before connecting to the
was 8 ms).Note that when using to Reactor. hot Flux, why not subscribe
the create builder instead, the twice?  One subscription will
thenAwait and expectNoEvent To create a custom Flux, instead print the detail of each tick while
methods would still be available of the RxJava AsyncEmitter the other will only print the in-
class, you’d use Reactor’s Flux- strument. (Code 23)
Sink. This will cover all the asyn-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 35


Note that in the example repository, the feed
would also terminate on its own if the is-
Last() method of PriceTick is changed.

FluxSink also lets you check if downstream


has cancelled its subscription via isCan-
celled(). You can also get feedback on the
outstanding requested amount via request-
edFromDownstream(), which is useful if you
want to simply comply with backpressure. Fi-
nally, you can make sure any specific resources
your source uses are released upon Cancel-
lation via setCancellation.

Note that there’s a backpressure implication


when using FluxSink: you must explicitly
provide an OverflowStrategy to let the op-
erator deal with backpressure. This is equiva-
lent to using onBackpressureXXX operators
(e.g. FluxSink.OverflowStrategy.BUFFER is
equivalent to using .onBackpressureBuf-
fer()), which kind of overrides any backpres-
sure instructions from downstream.

Conclusion
Reactor builds on the Rx language but targets
Java 8 and the RS specification. Concepts you
might have learned in RxJava also apply to Re-
actor, despite a few API differences. If you want
to dig deeper into Reactor, try the snippets
presented in this article, which are available in
a GitHub repository. There is also a Lite Rx API
Hands-On workshop that covers more opera-
tors and use cases.

You can reach the Reactor team on Gitter and


provide feedback there or through the GitHub
issues page (and of course, we welcome pull
requests as well).

36
Read online on InfoQ

Refactoring to Reactive:
Anatomy of a JDBC Migration

Nicolae Marasoiu is a passionate software developer with years of experience building high-
performance server-side applications for product and outsourcing companies, from start-ups
to well-established firms. He enjoys contributing in many areas of product development and
inspiring teams in their technical adventures.

Reactive programming is the new kid on the block, offering built-in


solutions for some of the most difficult concepts in programming,
including concurrency management and flow control. But if we work
on an application development team, there’s a good chance we’re not
using reactive and might have questions about it.

This article will transform a real level of abstraction, immuta- actual number of available
(intentionally simple) legacy ap- bility, and fluent style. For ex- threads, while still allowing
plication (with a classic setup ample, the Function<T,Ob- the  code to execute concur-
consisting of a web server and servable<U>> type is rently instead of queuing in
database back end), to a reactive composable, because we can some thread pool.
model, striving for a threefold chain together multiple such
benefit: functions using the flatMap We will do this by having the
operator of the Observable. application react as soon
1. Working in a functional style as it receives each chunk of
will allow us to compose our 2. Building a more resilient ap- information from the data-
code and thus reuse it, while plication allows our server base rather than having the
rendering it clearer and more to sustain a greater number thread wait for that infor-
readable thanks to a higher of concurrent users than the mation. This is a transforma-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 37


KEY TAKEAWAYS
Reactive programming comes with a learning curve and requires experience,
practice, and an open mind to fully grok.
It is possible to incrementally introduce reactive programming in any
application.
Reactive programming and non-blocking libraries like Netty increase
scalability and elasticity and reduce operating and development costs. (See
the The Reactive Manifesto for more context.).
Transformation of streams of future values into other streams of future
values is a powerful programming paradigm that with practice offers great
rewards.
Composability is the hallmark of functional programming; this article
explores monadic composition, using the flatMap operator of the Observable.

tion from a pull mechanism on its journey to its new func- it as a delegating method to a
(doing blocking I/O) to a tional and reactive form. new method that contains the
push mechanism that con- implementation to return an
tinues execution when data Once the tests are done, we can Observable<T>. The delegat-
becomes available or some start with the first refactoring ing method (with the original
event occurs, such as a time- step: replacing method return method signature) calls toB-
out or an exception. types with Observable, Single, locking on the Observable, to
or Completable, all part of RxJa- enforce the original synchronous
3. Building a more respon- va. Specifically, for each method contract, before returning any
sive application allows our that returns a value of type T, we values. Starting as small as possi-
browser view to update even can return Single<T>, an Ob- ble is a great migration strategy
as the first bytes start com- servable<T> with exactly one that helps overcome the learning
ing back from the database. value to emit, or an error. For curve and deliver steady incre-
This is achievable with the List<T>, we will change the re- mental progress. We can apply
streaming Servlet 3.1 API and turn type to Observable<T>, incremental refactoring with Rx-
will become available with while for each void method, Java.
Spring Reactor and the asso- we will return Completable,
ciated web extensions on the which can be converted to Sin- Here is a concrete example. We
Spring stack. gle<Void>. can see all of the code and its his-
tory here, where I take a classical
The examples in this article may Rather than replace all method Spring application tkssharma/
be downloaded from this link. return types in all the layers at Spring-JDBC and convert it to Rx-
the same time, let’s select one Java in two ways: using the RxJD-
We want to endow our program layer and start there. Convert- BC library (in the rx-jdbc branch)
with its new reactive makeover ing a method that returns T into and using the PgAsync library (in
in small steps, using incremental one that returns Single<T>, pgasync branch).
refactoring. one returning List<T> to an
Observable<T>, or a void to Let’s look at the following meth-
Before we start, let’s enrich our a Completable does not need ods from the Spring-JDBC proj-
test suite for the legacy appli- to change that method as it is ect: (Code 1)
cation, because we rely on such known by its client code: instead,
tests for the correctness of the re- we can retain the method’s orig- Following the above migration
factored versions of the program inal signature, but implement strategy, we will retain these

38 Reactive Programming in Java // eMag Issue 48 - Feb 2017


List<Student> getStudents();
Student getStudent(int studentId);
Code 1
public List<Student> getStudents() {
return getStudentStream().toList().toBlocking().single();
Code 2
Observable<Student> getStudentStream();
Single<Student> getStudent(int studentId);
Code 3
public Observable<Student> getStudentStream() {
List<Student> students = getStudentsViaJDBC();
return Observable.from(students);
}
Code 4
method signatures, but make a Blocking call is anathema to an error if no value can in fact be
small change in their implemen- the asynchronous reactive para- successfully emitted.
tation: (Code 2) digm, so ultimately we will want
to remove those from our pro- Our first step, wrapping return
We introduced an extra layer: duction code. types in Observable, does not
(Code 3) change the nature of execution.
Let’s say we have a method It is still synchronous, blocking
With the following implementa- List<Student> getStu- I/O just like JDBC does.
tion: (Code 4) dents(). We would create a
new method Observable<Stu- We have completed step one of
getStudentsViaJDBC is the ini- dent> getStudentStream() our refactoring: changing signa-
tial implementation. and move the implementation to tures from List<Student> get-
it, wrapping the resulting list into Students() to Observable<-
We have effectively created a an Observable using Observ- Student> getStudents().
new reactive layer while retain- able.from(Iterable). The Interestingly, even the method
ing our original non-reactive original method will call the new Student getStudent(), which
signature and then replaced the one and then studentStream. returns just a single student, is
original implementation with a toList().toBlocking().sin- also refactored to Observable<-
call to our new reactive incarna- gle() to convert it back to List. Student> getStudent() or
tion. We will make a few further This is inherently blocking, but potentially to Single<Student>
iterations on this data-access this is okay since the existing im- getStudent(). Furthermore,
layer, and then make the appli- plementation of getStudent- even void methods are refac-
cation reactive upwards, toward Stream is already blocking at this tored to return Completable.
the controller layer, with the final point.
goal of making it reactive end to We can further apply the reactive
end. The biggest obstacle in the reac- paradigm from the top down,
tive learning curve is learning to by wrapping large or small parts
The Observable.toBlocking think in terms of Observables. into a reactive envelope (API) and
method acts as a bridge between We may find it intuitive for a List then further breaking down each
the classic and reactive worlds. It to become a stream (which is, af- part where, for example, we need
is what we need to use to plug ter all, exactly what an Observ- asynchronicity or non-blocking
reactive code (even if only in API) able is) but applying that notion I/O.
into code that is classical in the to individual values is less intui-
large scale, like a servlet in one tive. To conceptualize this, con- To implement the new signature,
end and JDBC at the other. Until sider the traditional Java concept instead of returning student-
those ends are made reactive as of a Future: although it contains List, we return Observable.
well, we need this method. a single value, it can be viewed just(studentList).
as a particular case of a stream
Of course, at the end of our re- of future values, which happens At this point, we’ve introduced
factoring, the synchronous to- to contain just a single value or Observable in a few places but

Reactive Programming in Java // eMag Issue 48 - Feb 2017 39


Observable.defer(
()->Observable.just(actuallyProduceStudentsViaTripToDatabase()
)).
Code 5

@RequestMapping(value = “/student.html”, method = RequestMethod.GET)


public DeferredResult<ModelAndView> showStudents(Model model) {
Observable<ModelAndView> observable = studentDAO.getAllStudents()
.toList()
.map(students -> {
ModelAndView modelAndView = new ModelAndView(“home”);
modelAndView.addObject(“students”, students);
return modelAndView;
});
DeferredResult<ModelAndView> deferredResult = new DeferredResult<>();
observable.subscribe(result -> deferredResult.setResult(result),
e -> deferredResult.setErrorResult(e));
return deferredResult;
}
Code 6

public Observable<Student> getStudents() {


Class<String> stringClass = String.class;
return database
.select(“select id,name from student”)
.getAs(Integer.class, stringClass)
.map(row->{
Student student = new Student();
student.setId(row._1());
student.setName(String.valueOf(row._2()));
return student;
});
}
Code 7

<dependency>
<groupId>com.github.davidmoten</groupId>
<artifactId>rxjava-jdbc</artifactId>
<version>0.7.2</version>
</dependency>
Code 8

public Observable<Student> getStudents() {


return database
.queryRows(“select id,name from student”)
.map(row -> {
Student student = new Student();
int idx = 0;
student.setId(row.getLong(idx++));
student.setName(row.getString(idx++));
return student;
});
}
Code 9

40 Reactive Programming in Java // eMag Issue 48 - Feb 2017


<dependency>
<groupId>com.github.alaisi.pgasync</groupId>
<artifactId>postgres-async-driver</artifactId>
<version>0.9</version>
</dependency>
Code 10
besides simply wrapping and un- the controller method returns proach (using subscribeOn) is
wrapping a list, basically nothing not a completed Result but a one small, intermediate step to-
has changed. But this was an im- promise that when the result ward the goal of fully non-block-
portant step because it has made becomes available, it will be set ing libraries. It simply moves the
our code composable, and we on the previously returned De- subscribe and observe actions
are now ready to make the next ferredResult. If we just modify to different threads: these actions
move and start using some of the controller methods that re- will still block until the results are
the power behind Observable, turn Result to return Deferre- available (only they will block
namely lazy evaluation, which is dResult, that in itself is sufficient other threads), after which they
also available in Java streams. In- to provide a degree of asynchro- will push the results back to the
stead of returning Observable. nicity. (Code 6) subscriber, which further pushes
just(studentList), let’s re- them to a DeferredResult.
turn: (Code 5) We have made an important step
toward asynchronicity but, sur- There are libraries that imple-
Notice that actuallyProduce- prisingly, this method is still wait- ment RxJava on top of JDBC
StudentsViaTripToDatabase ing for the results to come from that use this manner of blocking
is the method we started with, the database, i.e. it is still block- threads (either the calling thread
which returned the List<- ing. Why is that? You may recall or other threads, as configured).
Student>. By wrapping it with that until now, the Observable This approach is currently re-
Observable.defer or Ob- returned by the access layer ex- quired for JDBC, since JDBC is a
servable.fromCallable, we ecutes its subscribe from the blocking API.
obtained a lazy Observable that calling thread so the method, de-
only initiates the query to the spite using the DeferredResult This intermediate step also
database at the moment a sub- approach, will block until the Ob- boosts scalability, allowing us
scriber subscribes to that data. servable delivers the data, con- to support a greater number of
suming thread resources. truly concurrent user operations
At this point, only the data-access (or “flows”) than the number of
layer API has been modified to re- The next step will be to change available threads.
turn Observable; the controller the Observable so that it does
methods are as yet unchanged not block the current thread on Here is the getStudents imple-
so they must consume (subscribe the subscribe call. This can be mentation using the RxJDBC li-
to) the Observable and wait for done in two ways: using the na- brary: (Code 7)
its results in the same thread — tive reactive libraries or using
blocking I/O. But our goal is to Observable.subscribeOn- In order to get the RxJDBC li-
create end-to-end asynchronous (scheduler) and observe- brary, add this dependency in
processing, which means that in- On(scheduler), executing the Maven project: (Code 8)
stead of the controller methods the subscribe method and the
returning an already populated observe methods on different Our third step is to introduce a
Result (with data already avail- schedulers (think of schedulers true reactive library. Several exist,
able for the template rendering), as thread pools). even for relational databases, but
we want to end up with an asyn- you can find more when focusing
chronous Spring MVC supplied The observe methods include on a specific database such as
by the DeferredResult class map, flatMap, and filter — all of PostgreSQL. This is because the
with the async object provided which transform an Observable database-access library is specif-
by Spring MVC. (Spring plans to another Observable — as ic for each low-level protocol of
support for streaming in the well as methods like doOnNext, each database. Here we use the
upcoming Spring Reactive Web, which executes actions each postgres-async-driver project,
powered by the Spring Reactor time a new element is emitted which itself uses RxJava.
ecosystem.) Using this approach, in the stream. This second ap-

Reactive Programming in Java // eMag Issue 48 - Feb 2017 41


public class T {
private Observable<Long> dml(String query, Object... params) {
return database.begin()
.flatMap(transaction ->
executeDmlWithin(transaction, query, params)
.doOnError(e -> transaction.rollback()));
}

private Observable<Long> executeDmlWithin(


Transaction transaction, String query, Object[] params) {
return transaction.querySet(query, params)
.flatMap(resultSet -> {
Long updatedRowsCount = resultSet.iterator().next().getLong(0);
return commitAndReturnUpdateCount(transaction, updatedRowsCount);
});
}

private Observable<Long> commitAndReturnUpdateCount(


Transaction transaction, Long updatedRowsCount) {
return transaction.commit()
.map(__ -> updatedRowsCount);
}
}
Code 11

Here is the getStudents imple- actions, which typically contain This Transaction object will be
mentation again, this time with multiple statements. passed from Java closure to Java
the PgAsync library. (Code 9) closure, as we see above: first,
Here is how a transaction would transaction is available as an
To use the PgAsync library, im- look: (Code 11) argument to the flatMap opera-
port this Maven dependency: tor. There, it is used in three spots:
(Code 10) This is a single-statement trans-
action, but it illustrates how we 1. First, it launches the DML
At this moment we have a tru- can do transactions in an async statement within the trans-
ly reactive (asynchronous, reactive API. Transaction be- action. Here, the result of
event-driven, non-blocking) gin, commit, and rollback are the querySet operation that
back-end implementation. We all monadic functions: they re- executes the DML is also an
also have an end-to-end asyn- turn an Observable and can be Observable that holds the
chronous solution that allows chained with flatMap. result of the DML (general-
us to process more user actions ly a Row with updated row
concurrently (at the I/O flows Let’s travel through the example counts), and is further trans-
level) than actual threads in the above, starting with the signa- formed with flatMap to an-
JVM. ture. The dml execution function other Observable.
takes a DML statement like UP-
Next, let’s work on transactions. DATE or INSERT, along with any 2. The second flatMap then
We will take a scenario where we parameters, and schedules it for uses our transaction object
want to modify data using da- execution. Note that db.begin to commit the transaction.
ta-manipulation-language (DML) returns Observable<Trans- There, the transaction vari-
operations INSERT or UPDATE. In- action>. The transaction is not able is enclosed by a lambda
troducing asynchronicity is com- created right away because it function and is provided as
plicated even for the simplest involves database I/O. So this is an argument to this second
transaction consisting of a single an asynchronous operation such flatMap. This is one way we
DML statement, since we are so that when execution completes, can send data from one part
used to transactions that block it returns a Transaction object of an async flow to anoth-
threads. And it’s even more com- on which  SQL queries followed er: using a variable from the
plicated for more realistic trans- by commit or rollback can sub- lexical scope and using it in
sequently be called as required. a lambda expression creat-

42 Reactive Programming in Java // eMag Issue 48 - Feb 2017


ed at one time but executed On error, rollback is called on the kell have constructs that trans-
at a later time, potentially transaction. The error then bub- parently generate non-blocking
in a different thread. This is bles up the Observable chain implementations from blocking
the significance of lambda (not the call stack) unless it is code: for example, the async
expressions being Java clo- stopped from doing so via spe- high-order functions in C# and
sures: they enclose variables cific Observable operators that Scala. In Java, to my knowledge,
used in the expressions. We say “when this Observable has the most robust way to perform
can send data like this using an error, use this other Observ- non-blocking operations is by
any Java closure, not just able or perhaps try the same using reactive streams, RxJava,
lambdas. one again.” This transactional or non-blocking libraries such as
update is a first example of flat- Netty. However, things remain
3. The third usage of the Map chaining. What we do is pipe pretty explicit, so the entry bar-
transaction variable is multiple steps one to another, in rier can be high. Still, when you
the doOnError, where the an event-driven manner: when need to support more concurrent
transaction is rolled back. the transaction is started, a que- users than the number of threads
Again note how the trans- ry can be issued; when the que- or when your application is I/O-
action variable is passed ry result is available, some result bound and you want to minimize
in three  places via the usual parsing and transaction commit costs, then non-blocking will get
Java lexical scoping, even can be issued; when the trans- you an extra order of magnitude
though some pieces of the action is complete, the result is in scalability, elasticity, and cost
code will be executed syn- used to replace the successful reduction.
chronously (as part of the commit result (which contains
method execution in the call- no information) with the result When discussing elasticity or ro-
ing thread), and others will be (here, the update count). If the bustness, it is helpful to consider
executed later, when some final observable would not have the moment when all threads are
events happen — i.e. when a been Observable<Void> but waiting for I/O. For example, let’s
response comes from the da- Observable<T>, we could have assume a modern JVM can sup-
tabase, asynchronously and packaged T with our result Long port 5,000 threads. This means
on different threads. The val- into a data-transfer object. that when 5,000 calls to various
ue transaction is available web services are waiting on their
in all these contexts. Ideally, In the reactive world, we aim to respective threads in a blocking
shared values should be im- bring a blocking application to a application, simply no more user
mutable, stateless, or thread non-blocking state. (A blocking requests can be processed at
safe. Java only requires them application is one that blocks that stage (they can only queue
to be effectively final but this when performing I/O operations for later processing by some
is not enough for non-primi- such as opening TCP connec- specialized threads dedicated to
tive values. tions.) Most of the legacy Java queuing). That might be fine in a
APIs for opening sockets, talking controlled context such as a cor-
If successful, the transaction to databases (JDBC), and Fil- porate intranet, but is certainly
commit result will be translated eInputStream /FileOutput- not what a start-up needs when
(mapped) to an update count, Stream are all blocking APIs. The 10 times the normal number of
which can be used by callers. same is true about the early im- users suddenly decide to check
Here, in order to transmit the plementations of the Servlet API out their product in a burst.
number of updated/inserted and many other Java constructs.
rows to an outside caller of the One solution to traffic spikes is
transactional method, we cannot Over time, things started to adopt horizontal scalability, bringing
capture the result count by using non-blocking counterparts; for up more servers, but that is not
Java closures, since the callee is example, Servlet 3.x integrated elastic enough and may be ex-
not in the same lexical scope as a few concepts like async and pensive. Again, it all depends on
the caller. In this case,  we need streaming. But in a typical J2EE the I/O of the application. But
to encapsulate the result in the application, we would typically even if HTTP is the only potential-
data type of the resulting Ob- find blocking calls, which is not ly slow I/O an Internet service is
servable. If we need to carry always a bad thing: blocking se- exposed to, and all other I/O ops
multiple results, we can resort to mantics are easier to understand occur with internal databases or
immutable Java classes, arrays, than explicit async APIs. Some highly available low-latency ser-
or unmodifiable Java collections. languages like C#, Scala, and Has- vices, then HTTP will move bytes

Reactive Programming in Java // eMag Issue 48 - Feb 2017 43


only as fast as, say, a slow client processing will kick in. When pro- 3. Use Spring MVC async to
on the other side of the planet. cessing completes, the web layer make it async.
starts rendering. When the web-
It is true that this problem is the page (or the JSON payload) ren- 4. Make the back end
remit of professional load balanc- ders, the HTTP layer is called with non-blocking by using a
ers, but we never know when the the full response payload. specialized library for the
most highly available internal or database that implements a
external service will go down The next step would be stream- non-blocking alternate im-
or when the most low-latency ing: when the database tells plementation.
service actually will only run at the processing layer that there’s
near real time and not hard real more data, the processing layer 5. Wrap that non-blocking im-
time and so will respond slowly accepts it. This acceptance does plementation in RxJava or
because of garbage collection. not necessarily imply that a dedi- another reactive framework
Then, if we’re blocking in only cated thread is being used — for if it’s not already wrapped in
parts of your stack, we’ll have a example, NIO or Linux epoll one.
blocking bubble, which means would be non-blocking. Here, the
that threads will start blocking idea is that a single thread is que- 6. Use Vert.x to make it stream-
on the slowest blocking I/O and rying a hundred thousand con- ing.
bring resources to a halt because nections to the OS to ask wheth-
of, say, a single slow blocking ac- er there is anything new on them. 7. Do the writes.
cess that is requested by 5% of Then the processing layer can do
the traffic and has low business a transformation that outputs 8. Do the (multi-statement)
importance. more semantic units, like “stu- transactions.
dents”. It may be useful at times,
Hopefully, I have convinced like when the data from the da- 9. Verify error handling.
you that making an applica- tabase represents only part of a
tion non-blocking adds value in student, to keep the partial info To run the app, we use the Post-
many situations, so let’s come in the processing-layer buffers. greSQL database. You can install
back to our legacy application. It When a bulk data fetch from the it and set the PostgreSQL user
is blocking in all its layers, HTTP, database has finally obtained password to “mysecretpassword”.
and database access, so let’s start all of the data on that student, Or, more simply, install Docker
from there. Unless all layers on it can be closed and sent to the and run:
a vertical (here, those are HTTP upper layer for rendering. In such
and database access) are being a pipeline, any component can sudo docker run -d
made async, the full flow cannot stream at any granularity: some -p 5432:5432
be async. will just copy bytes from left to -e POSTGRES_
PASSWORD=mysecret
right; others will send full stu-
password -d
There is also a difference be- dent instances or even batches postgres
tween async and non-blocking in of them; while others, like the
that while non-blocking implies DeferredResult of MVC Spring, We execute student.sql to create
async (unless we have language will need the whole result be- the table and insert some sample
constructs), async can always be fore starting to write an HTTP rows.
done for a blocking call by simply response.
moving it to a different thread. Then we install mvn, and then
This has some of the same issues Let’s review the steps of refactor- deploy the war file in Tomcat or
as the initial blocking solution, ing: Jetty.
but can be a step towards the
end goal in an incremental ap- 1. Put Observable in signa- The URLto your locally deployed
proach. For the HTTP side, we are tures. application is here; click on “stu-
already partially covered by the dents”.
current state of the Servlet spec 2. Put  observable.sub-
and Spring MVC, which gives us scribeOn and observable.
async behavior, but not stream- observeOn(scheduler) More on composability
ing. to move blocking computa- We have spoken a lot about
tions (e.g. JDBC calls) to a dif- composability and it pays to un-
Async implies that when the ferent thread pool. derstand those semantics. In the
database finishes responding, particular context of reactive pro-

44 Reactive Programming in Java // eMag Issue 48 - Feb 2017


gramming, I will highlight how a token from inside a resource serv- dation functionality so that if, for
kind of composition functions er (an app server). We can do this example, it cannot access exter-
— let’s call it “sequencing”. That with a library that checks data on nal sites like Google then it could
means that we have a pipeline the token payload or with a net- verify signatures with our own
of processing that, given some work call to an identity provider library and get on with it.
input, produces some output in (IdP) to verify even more details,
a series of steps. Each step can like whether the user is still valid. All these alternative solutions,
be synchronous (for example, or decorators, can be added,
applying some computation to Let’s defined this monadic func- and each of them would still be
transform a value) or asynchro- tion (the return type is a monad, a function from String to Ob-
nous (like going to a web service a type having flatMap on it). servable<Boolean>.
or a database to get some more
Observable<Boolean>
information). The pipeline can So we have low coupling, be-
isValid(String
be pulled by its consumers or token) cause changing from sync to
pushed by its producers. async and back does not affect
We can implement it in memory, the API.
Let’s consider another exam- a CPU-intensive operation that
ple. Suppose we are building a uses some token-decryption li- But, unlike Java’s Future, the
non-blocking web server that brary and validates the signature Observable type is composable:
needs to send data to a back-end and other information like expi- we can call a function that re-
system for processing and then ration date or IDs. turns a standard Response when
return the result in the response. we learn a token is valid but
It also needs to authenticate and Or we can add a trip to Google, if would return an ErrorResponse
authorize the user that makes we use it as an IdP server. otherwise.
the request. We see a few steps
of processing are already emerg- In both cases, the world outside Let’s say we have an Observ-
ing in the pipeline of a request of this function, including the able<String> (which does not
that will lead to a state change in pipeline itself, is not aware of imply that we are waiting for
the back end (and other systems) how the Observable<Boolean> multiple tokens — we can wait
and a response to the end user. is implemented beneath the for just one, which is a form of
covers. It could only call its sub- Future<String>). On this to-
In composing such a pipeline, scriber in the same thread, like ken Observable, we apply flat-
it would be ideal not to need to the in-memory version, in which Map using the isValid function
be aware of the details of any case it is equivalent to a boolean and obtain a boolean observ-
particular step, like whether it is isValid(token) function. Or it able. To this, we apply a flatMap
synchronous or asynchronous or might actually perform I/O with with a lambda function with an
how many retries it performs — Google, parsing the response to “if” statement: if things are val-
and, if asynchronous, from which reach a boolean conclusion. The id, return the Observable<Re-
thread pool it takes or which design is agnostic to the imple- sponse>, otherwise return
non-blocking framework it uses. mentation. another Observable<ErrorRe-
sponse>.
Conversely, when we need to We could also wrap such a func-
change a processing step from tion inside another one, with the That could look like this: (Code
synchronous to asynchronous, same signature (String->Ob- 12)
we should only need to modify servable<Boolean), that adds
the internal implementation of retry mechanisms on top of this You notice that with every flat-
the monadic function, and noth- validation (which would make Map, we start with a value of type
ing outside that. sense for a Google trip in case Observable<T> and obtain an-
an HTTP request becomes lost other Observable<U> where T
To illustrate, let’s say we want to in traffic or has a large latency). and U can be the same or differ-
have a step for validating a JWT Or it would add graceful degra- ent types of parameter.

responseObservable = tokenObservable.flatMap(token -> isValid(token)


.flatMap(valid -> valid? process(request) :
Observable.just(new ErrorResponse(“invalid”)));
Code 12

Reactive Programming in Java // eMag Issue 48 - Feb 2017 45


This composition, then, is an im- it, resulting in a new Observable processing steps and more dec-
portant property: to compose for every such element. When re- orator functionality like retry and
from small components of a cer- sult elements start to appear on fallback mechanisms, is a large
tain shape, larger ones of that the resulting Observables<U>, part of composability.
same shape. But what is that they are (also) emitted as part of
shape? newObservable, in their order
of appearance. Why Observ- Non-blocking under the
In the case of the monad, we can ables<U>? Because if sourceOb- covers
model it as a type that has a type servable emits three elements, At one point, I mentioned that it
parameter T and two functions: then function f applied to each is possible to have more ongo-
flatMap and lift. The latter is of them will generate a total of ing flows than available threads
easy: it converts an instance three Observables. These can by using non-blocking async
of type T to an instance of the be merged or concatenated. I/O libraries: you may wonder
monad. It is the Observable. Merged means that all elements how that is possible. So let’s
just(value) or Option.of- from all three observables are take a closer look at how librar-
Nullable(value), to give two added to newObservable out- ies like Netty work (Netty is the
examples for two monads. put as soon as they emerge. This library used as the non-block-
is what flatMap does: merges the ing I/O workhorse by Vert.x and
How about flatMap? This is three Observable results. The al- PgAsync).
a high-order function that, ternative is to first wait for all the
given an Observable<T> in- elements from the first resulting Java has an API called NIO, which
stance called “source” and a Observable, then concatenate aims at working with multiple
monadic function f(T->Ob- it with the second one, which is connections with fewer threads.
servable<U>), produces ne- what concatMap does: it concat- It works by making certain OS
wObservable = sourceOb- enates the resulting observables. syscalls under the covers. (In the
servable.flatMap(t->f(t)) case of Linux, these can be epoll
of type Observable<U> and This property of the Observable or poll.) For example, let’s as-
signifies, in the case of Observ- type, the ability to generate new sume we have a thousand open
able, that when an element of Observable values with aug- connections. A thread will call an
type T is available on source, mented functionality from one NIO method called selector.
then the function f  is called on Observable value with more select, which is a blocking call,
and return 10 connections that
had queued events like “more
data available”, “connection
closed”, and others since the last
query. The thread doing the que-
ry will typically dispatch the 10
events to other threads so that
it can continue polling, so this
first thread is an infinite loop that
continually queries for events on
open connections. It dispatches
the 10 events for processing to a
thread pool or to an event loop.
Netty has an unbound thread
pool to process these events. The
event processing is CPU-bound
(compute intensive). Any I/O
would be delegated back to NIO.

A great resource that covers all of


these techniques in depth is the
classic Reactive Programming
with RxJava by Tomasz Nurk-
iewicz and Ben Christensen.

46 Reactive Programming in Java // eMag Issue 48 - Feb 2017


Read online on InfoQ

Building Reactive Applications


with Akka Actors and Java 8

Markus Eisele is a Java Champion, former Java EE Expert Group member, founder of JavaLand,
reputed speaker at Java conferences around the world, and a very well-known figure in the
Enterprise Java world. He works as a developer advocate at Lightbend. Find him on Twitter @
myfear.

While the term “reactive” has been around for a long time, only recently
has the industry recognized it as the de facto way forward in system
design, leading to its mainstream adoption. In 2014, Gartner wrote that
the three-tier architecture that used to be so popular was beginning
to show its age. This has become even clearer with the ongoing
modernization efforts driven by enterprise, which has had to start
rethinking the way developers have learned to build applications for
more than a decade.
Microservices are taking the application design and imple- liths; the real value lies in better
software industry by storm and mentation has been forging its resources consumption and ex-
the shock waves are shaking the way through IT systems with treme scalability for unpredict-
traditional development work- unprecedented momentum. able workloads. The traits of the
flow to the core. We’ve seen soft- And even if the term “microser- Reactive Manifesto are quickly
ware-design paradigms change vices” isn’t completely new, our becoming the new Bible for mi-
and project-management meth- industry is realizing that it’s not croservices-based architectures,
odologies evolve — but the only about coupling RESTful as they are essentially distributed
consequent shift towards new endpoints and slicing mono- reactive applications.

Reactive Programming in Java // eMag Issue 48 - Feb 2017 47


KEY TAKEAWAYS
The actor model provides a higher level of abstraction for writing concurrent
and distributed systems, which shields the developer from explicit locking
and thread management.
The actor model provides the core functionality of reactive systems, defined
in the Reactive Manifesto as responsive, resilient, elastic, and message
driven.
Akka is an actor-based framework that is easy to implement with the
available Java 8 lambda support.
Actors allow developers to design and implement systems that focus more on
the core functionality and less on the plumbing.
Actor-based systems are the perfect foundation for quickly evolving
microservices architectures.

The actor model in concurrency and for increasing Actors with Java 8 and
today’s applications resource efficiency. Importantly, Akka
Applications must be highly the actor model also has well-de- Akka is a toolkit and runtime
responsive to retain user inter- fined ways to gracefully handle for building highly concurrent,
est and must evolve quickly to errors and failures, ensuring a distributed, and resilient mes-
remain relevant to meet the level of resilience that isolates is- sage-driven applications on the
ever-changing needs and ex- sues and prevents cascading fail- JVM. Akka’s “actors” allow you to
pectations of the audience. The ures and massive downtime. write concurrent code without
technologies available for build- having to think about low-lev-
ing applications continue to In the past, building highly con- el threads and locks. Other tools
evolve at a rapid pace; science current systems typically in- include Akka Streams and the
has evolved, and the emerging volved a great deal of low-level Akka HTTP layer. Although Akka
requirements cannot rely on wiring and technical program- is written in Scala, there is a Java
yesterday’s tools and method- ming techniques that were dif- API, too. The following examples
ologies. The actor model is one ficult to master. These technical work with Akka 2.4.9 and above
concept that has emerged as an challenges competed for atten- — but the Java with lambda
effective tool for building sys- tion with the core business func- support part of Akka has been
tems that take advantage of the tionality of the system because considered experimental as of its
processing power harnessed by much of the effort had to be fo- introduction in Akka 2.3.0 so ex-
multicore, in-memory, clustered cused on the functional details, pect it to change until its official
environments. requiring a considerable amount release.
of time and effort for plumb-
The actor model provides a rela- ing and wiring. When building The actor is the basic unit of work
tively simple but powerful model systems with actors, things are in Akka. An actor is a container
for designing and implementing done at a higher level of abstrac- for state and behavior, and can
applications that can distribute tion because the plumbing and create and supervise child actors.
and share work across all sys- wiring are already built into the Actors interact with each other
tem resources — from threads actor model. Not only does this through asynchronous messag-
and cores to clusters of servers liberate us from the gory details es, which are processed synchro-
and data centers. It provides an of traditional system implemen- nously, one message at a time.
effective framework for building tation, it also allows for more fo- This model protects an actor’s in-
applications with high levels of cus on core system functionality ternal state, makes it thread safe,
and innovation.

48 Reactive Programming in Java // eMag Issue 48 - Feb 2017


<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.11</artifactId>
<version>2.4.9</version>
</dependency>
Code 1

static class Counter extends AbstractLoggingActor {


static class Message { }

private int counter = 0;

{
receive(ReceiveBuilder
.match(Message.class, this::onMessage)
.build()
);
}

private void onMessage(Message message) {


counter++;
log().info(“Increased counter “ + counter);
}
}
Code 2

public static void main(String[] args) {


ActorSystem system = ActorSystem.create(“sample1”);
ActorRef counter = system.actorOf(Counter.props(), “counter”);

}
Code 3

and implements event-driven An actor’s initial behavior is de- additional information about
behavior that won’t block other fined by implementing the re- how to start the actor. The akka.
actors. To get started, you don’t ceive() method with the help of actor.Props is a configuration ob-
need much more than the Akka a  ReceiveBuilder in the default ject that is used to expose pieces
Maven dependency. (Code 1) constructor. receive() matches in- of context-scoped configuration
coming messages and executes to all pieces of the framework. It
related behavior. The behavior is used in creating our actors; it
Changing actor state for each message is defined us- is immutable so it is thread-safe
Just like we exchange text mes- ing a lambda expression. In the and fully shareable.
sages on mobile devices, we use following example, the Receive- return Props.
messages to invoke an actor. And Builder uses a reference to the in- create(Counter.
also like text messages, the mes- terface method onMessage. The class);
sages between actors must be onMessage method increases a
immutable. The most important counter (internal state) and logs The Props object describes the
part of working with an actor an info message via the Abstract- constructor arguments of the
is to define the messages it can LoggingActor.log method. (Code actor. It is a good practice to en-
receive. (The message is also 2) capsulate it in a factory function
commonly referred to as “proto- that is closer to the actor’s con-
col” because it defines the point With the actor in place, we need structor. The ActorSystem itself
of interaction between actors.) to start it. This is done via the is created in the main method.
Actors receive messages and re- ActorSystem, which controls the (Code 3)
act to them. They can send other lifecycle of the actors inside it.
messages, change their state or But first, we need to supply some
behavior, and create other actors.

Reactive Programming in Java // eMag Issue 48 - Feb 2017 49


counter.tell(new Counter.Message(), ActorRef.noSender());
Code 4
[01/10/2017 10:15:15.400] [sample1-akka.actor.default-dispatcher-4]
[akka://sample1/user/counter] Increased counter 1
Code 5

static class Alarm extends AbstractLoggingActor {


// contract
static class Activity {}
static class Disable {
private final String password;
public Disable(String password) {
this.password = password;
}
}
static class Enable {
private final String password;
public Enable(String password) {
this.password = password;
}
}

// ...
}
Code 6
private final String password;
public Alarm(String password) {
this.password = password;
// ...
}
Code 7
public static Props props(String password) {
return Props.create(Alarm.class, password);
}
Code 8

Both ActorSystem (“sample1”) safety. Messages that are sent to without the correct password, it
and the contained actor “count- actors from different threads are will sound. As an actor, the alarm
er” receive names for navigating shielded from concurrency prob- can react to three messages:
actor hierarchies (more on these lems since the actor framework disable, enable with a password
later). Now the ActorRef can send serializes the message process- (supplied as a payload), and tam-
a message to the actor, for exam- ing. You can find the complete pering. All of them go into the
ple: (Code 4) example online. contract. (Code 6)

Here, the two parameters define The actor gets a preset attribute
the message to be sent and the Changing actor behavior for the password, which is also
sender of the message. (As the You will notice that our simple passed into the constructor.
name implies, noSender indi- example modified the actor state (Code 7)
cates that the sender isn’t used but did not change its behavior,
in this case.) If you run the above and it never sent messages to The aforementioned akka.actor.
example, you get the expected other actors. Consider the case Props configuration object also
output: (Code 5) of a burglar alarm: we can enable needs to know about the pass-
and disable it with a password word attribute in order to pass it
This is a simple example yet it and its sensor detects activity. If a to the actual constructor when
supplies all of our desired thread burglar tries to disable the alarm the actor system starts. (Code 8)

50 Reactive Programming in Java // eMag Issue 48 - Feb 2017


private final PartialFunction<Object, BoxedUnit> enabled;
private final PartialFunction<Object, BoxedUnit> disabled;
Code 9

public Alarm(String password) {


this.password = password;

enabled = ReceiveBuilder
.match(Activity.class, this::onActivity)
.match(Disable.class, this::onDisable)
.build();

disabled = ReceiveBuilder
.match(Enable.class, this::onEnable)
.build();

receive(disabled);
}
}
Code 10

private void onActivity(Activity ignored) {


log().warning(“oeoeoeoeoe, alarm alarm!!!”);
}
Code 11

private void onEnable(Enable enable) {


if (password.equals(enable.password)) {
log().info(“Alarm enable”);
getContext().become(enabled);
} else {
log().info(“Someone failed to enable the alarm”);
}
}
Code 12

The Alarm actor also needs a Note that the call to receive at short warning. The message pay-
behavior for each possible mes- the end sets the default behavior load now contains the password
sage. These behaviors are imple- to “disabled”. All three behaviors that we can access to validate it.
mentations of the receive meth- are implemented using three (Code 12)
od of AbstractActor. The receive existing methods (onActivity,
method should define a series of onDisable, and onEnable). The When it receives a disable mes-
match statements (each of type easiest of these methods to work sage, the actor needs to check
PartialFunction<Object, Boxe- on is onActivity. If there is activi- the password, log a short mes-
dUnit>) that define the messag- ty, the alarm logs a string to the sage about the changed state,
es the actor can handle and the console. Note that there is no and actually change the state
implementation of how to pro- message payload required for ac- to disabled or log a warning
cess the messages. (Code 9) tivity so we just give it the name message that the password was
“ignored”. (Code 11) wrong. (Code 13)
If this signature seems fright-
ening, our code can effectively If the actor receives an enable That completes the actor logic.
sweep it under the rug by using a message, the new state will be We are ready to start the actor
ReceiveBuilder that can be used logged to the console and the system and send it a couple of
as shown earlier. (Code 10) state changed to enabled. If the messages. Note that our secret
password doesn’t match, it logs a password “cat” is passed as a

Reactive Programming in Java // eMag Issue 48 - Feb 2017 51


private void onDisable(Disable disable) {
if (password.equals(disable.password)) {
log().info(“Alarm disabled”);
getContext().become(disabled);
} else {
log().warning(“Someone who didn’t know the password tried to disable it”);
}
}
Code 13

ActorSystem system = ActorSystem.create();


final ActorRef alarm = system.actorOf(Alarm.props(“cat”), “alarm”);
Code 14

alarm.tell(new Alarm.Activity(), ActorRef.noSender());


alarm.tell(new Alarm.Enable(“dogs”), ActorRef.noSender());
alarm.tell(new Alarm.Enable(“cat”), ActorRef.noSender());
alarm.tell(new Alarm.Activity(), ActorRef.noSender());
alarm.tell(new Alarm.Disable(“dogs”), ActorRef.noSender());
alarm.tell(new Alarm.Disable(“cat”), ActorRef.noSender());
alarm.tell(new Alarm.Activity(), ActorRef.noSender());
Code 15

[01/10/2017 10:15:15.400] [default-akka.actor.default-dispatcher-4] [akka://default/


user/alarm] Someone failed to enable the alarm
[01/10/2017 10:15:15.401] [default-akka.actor.default-dispatcher-4] [akka://default/
user/alarm] Alarm enable
[WARN] [01/10/2017 10:15:15.403] [default-akka.actor.default-dispatcher-4] [akka://
default/user/alarm] oeoeoeoeoe, alarm alarm!!!
[WARN] [01/10/2017 10:15:15.404] [default-akka.actor.default-dispatcher-4] [akka://
default/user/alarm] Someone who didn’t know the password tried to disable it
[01/10/2017 10:15:15.404] [default-akka.actor.default-dispatcher-4] [akka://
default/user/alarm] Alarm disabled
Code 16

property to the actor system. Actor hierarchies that it will not process normal
(Code 14) Actors may create other actors. messages until resumed) and no-
When one actor creates another tifies its supervisor of the failure.
Let’s send these messages: (Code actor, the creator is known as the
15) “supervisor” and the created ac- So far, we’ve created actors and
tor is known as the “worker”. Su- assigned them names. Actor
They produce the following out- pervisors may create worker ac- names are used to identify ac-
put: (Code 16) tors for many reasons, the most tors in the hierarchy. The actor
common of which is to delegate that generally interacts the most
You can find the complete work- work to them. with others is the parent of all
ing example online. user-created actors, the guard-
The supervisor also becomes a ian with the path /user. Actors
Until now, we’ve only used indi- caretaker of the workers. Just as created with the primordial sys-
vidual actors to process messag- a parent watches over his or her tem.actorOf() are direct children
es — but like in a business, actors children, the supervisor tends of this guardian and when it ter-
form natural hierarchies. to the wellbeing of its workers. minates, all normal actors in the
If a worker runs into a problem, system will shut down as well.
it suspends itself (which means In the above alarm example, we

52 Reactive Programming in Java // eMag Issue 48 - Feb 2017


created a user actor with the
path /user/alarm.

Since actors are created in a


strictly hierarchical fashion, each
actor inherits a unique sequence
of names by recursively following
the supervision links between
child and parent towards the
root of the actor system. This se-
quence resembles the enclosing
folders in a file system, hence the
adopted name “path” to refer to
it, although actor hierarchy has Figure 1
some fundamental differences
from a file-system hierarchy.

Inside of an actor, you can call • Resume the child, keeping the so-called supervision strat-
getContext().actorO f(props, its accumulated internal state egy. Akka provides two classes
“alarm-child”) to create a new ac- but ignoring the message of supervision strategies: One-
tor named alarm-child as a child that lead to the failure. ForOneStrategy and AllForOneS-
of the alarm actor . The child life- trategy. The former applies the
cycle is bound to the supervising • Restart the child, clearing out obtained directive only to the
actor, which means that if you its accumulated internal state failed child whereas the latter
stop the “alarm” actor, it will also by starting a new instance. applies it to all siblings as well.
stop the child. (Figure 1) Normally, you should use the
• Stop the child permanently OneForOneStrategy, which is the
This hierarchy also has a sig- and send all future messages default if none is explicitly spec-
nificant influence on how ac- for the child to the dead-letter ified. It is defined by overriding
tor-based systems handle fail- box. the SupervisorStrategy method.
ures. The quintessential feature (Code 19)
of actor systems is that tasks are • Escalate the failure, thereby
split up and delegated until they failing the supervisor itself. The first parameter defines the
become small enough to be han- maxNrOfRetries, which is the
dled in one piece. In doing so, not Let’s examine this with an ex- number of times a child actor
only is the task itself clearly struc- ample: A NonTrustWorthyChild may restart before the Super-
tured but the resulting actors can receives Command messages visor stops it (a negative value
be reasoned about in terms of: and increases an internal counter indicates no limit). The withinTi-
with each message. If the mes- meRange parameter defines the
• which messages they should sage count is divisible by four, duration of the window for max-
process, it throws a RuntimeException, NrOfRetries. As defined above,
which it escalates to the Super- the strategy is to try 10 times
• how they should react nor- visor. There’s nothing really new within 10 seconds. The Decider-
mally, and here, as the command message Builder works exactly as the Re-
has no payload. (Code 17) ceiveBuilder to define matches
• how failures should be han- on occurring exceptions and
dled. The Supervisor starts the Non- how to react to them. In this case,
TrustWorthyChild in its construc- if there are 10 retries within 10
If one actor does not have the tor and forwards all command seconds the Supervisor stops the
means for dealing with a cer- messages that it receives directly NonTrustWorthyChild and sends
tain situation, it sends a corre- to the child. (Code 18) all remaining messages to the
sponding failure message to its dead-letter box.
supervisor, asking for help. The When the Supervisor actor starts,
supervisor has four options for the resulting hierarchy will be / The actor system is started with
reacting to a failure: user/supervisor/child. Before this the Supervisor actor. (Code 20)
can be done, we need to define

Reactive Programming in Java // eMag Issue 48 - Feb 2017 53


public class NonTrustWorthyChild extends AbstractLoggingActor {

public static class Command {}


private long messages = 0L;

{
receive(ReceiveBuilder
.match(Command.class, this::onCommand)
.build()
);
}

private void onCommand(Command c) {


messages++;
if (messages % 4 == 0) {
throw new RuntimeException(“Oh no, I got four commands, can’t handle more”);
} else {
log().info(“Got a command “ + messages);
}
}

public static Props props() {


return Props.create(NonTrustWorthyChild.class);
}
}
Code 17

public class Supervisor extends AbstractLoggingActor {


{
final ActorRef child = getContext().actorOf(NonTrustWorthyChild.props(), “child”);

receive(ReceiveBuilder
.matchAny(command -> child.forward(command, getContext()))
.build()
);

}
//…
}
Code 18

@Override
public SupervisorStrategy supervisorStrategy() {
return new OneForOneStrategy(
10,
Duration.create(10, TimeUnit.SECONDS),
DeciderBuilder
.match(RuntimeException.class, ex -> stop())
.build()
);
}
Code 19

ActorSystem system = ActorSystem.create();


final ActorRef supervisor = system.actorOf(Supervisor.props(), “supervisor”);
When the system is up, we start to send 10 command messages to the Supervisor. Note,
that the message “Command” was defined in the NonTrustWorthyChild.
for (int i = 0; i < 10; i++) {
supervisor.tell(new NonTrustWorthyChild.Command(), ActorRef.noSender());
}
Code 20

54 Reactive Programming in Java // eMag Issue 48 - Feb 2017


[01/10/2017 12:33:47.540] [default-akka.actor.default-dispatcher-3] [akka://default/
user/supervisor/child] Got a command 1
[01/10/2017 12:33:47.540] [default-akka.actor.default-dispatcher-3] [akka://default/
user/supervisor/child] Got a command 2
[01/10/2017 12:33:47.540] [default-akka.actor.default-dispatcher-3] [akka://default/
user/supervisor/child] Got a command 3
[01/10/2017 12:33:47.548] [default-akka.actor.default-dispatcher-4] [akka://default/
user/supervisor] Oh no, I got four commands, I can’t handle any more
java.lang.RuntimeException: Oh no, I got four commands, I can’t handle any more
...
[01/10/2017 12:33:47.556] [default-akka.actor.default-dispatcher-3] [akka://
default/user/supervisor/child] Message [com.lightbend.akkasample.sample3.
NonTrustWorthyChild$Command] from Actor[akka://default/deadLetters] to
Actor[akka://default/user/supervisor/child#-1445437649] was not delivered.
[1] dead letters encountered.
Code 21

The output shows that after four measure downtime not in hours basic level with the asynchro-
messages, the exception esca- but seconds. Actor-based sys- nous exchange of messages be-
lates to the Supervisor and the tems allow us to create quickly tween actors. If you send me a
remaining messages are sent to evolving microservice architec- message, you have to consider
the deadLetters box. If the Su- tures that can scale and run with- the possible outcomes: what do
pervisorStrategy would have out stopping. you do when you get the reply
been defined to restart() instead you expect… or don’t!? This goes
of stop(), the Supervisor would It’s the actor model that provides all the way towards implement-
have started a new instance of the core functionality of reactive ing strategies for handling nodes
the NonTrustWorthyChild actor systems, defined in the Reactive that leave and join a cluster.
instead. (Code 21) Manifesto as responsive, resil-
ient, elastic, and message driven. Thinking in terms of actors is in
We can turn off or adjust this log- many ways much more intuitive
ging with configuration settings The fact that actor systems can for us when designing systems.
akka.log-dead-letters and akka. scale horizontally, from a sin- The way actors interact is more
log-dead-letters-during-shut- gle node to clusters with many natural to us since it has, on a
down. nodes, provides us with the flex- simplistic level, much in com-
ibility to scale our systems for mon with how humans interact.
You can follow up with the com- massive load. It is also possible to This allows us to design and im-
plete example online and play implement systems with the ca- plement systems in ways that let
around with the SupervisorStrat- pability to scale elastically — that us focus more on the core func-
egy. is, scale the capacity of systems, tionality of the systems and less
either manually or automatically, on the plumbing.
to adequately support the peaks
Summary and valleys of system activity.
With Akka and Java 8, it is now
possible to create distributed, With actors and actor systems,
microservices-based systems failure detection and recovery
that just a few years ago were is an architectural feature, not
the stuff of dreams. Enterprises something that can be patched
across all industries now desire on later. Out of the box, we get
the ability to create systems that actor-supervision strategies for
can evolve at the speed of the handling problems with subor-
business and cater to the whims dinate worker actors up to the
of users. We can now elastically actor-system level, with clusters
scale systems that support mas- of nodes that actively monitor
sive numbers of users and pro- the state of the cluster — where
cess huge volumes of data. We dealing with failures is baked
can now harden systems with into the DNA of actors and actor
a level of resilience that lets us systems. This starts at the most

Reactive Programming in Java // eMag Issue 48 - Feb 2017 55


PREVIOUS ISSUES

46
Architectures You’ve
Always Wondered About

This eMag takes a look back at five of the most pop-


ular presentations from the Architectures You’ve Al-
ways Wondered About track at QCons in New York,
London and San Francisco, each presenter adding a
new insight into the biggest challenges they face, and
how to achieve success. All the companies featured
have large, cloud-based, microservice architectures,
which probably comes as no surprise.

45
A Preview of C# 7

47 The Current State of


NoSQL Databases

This eMag focuses on the current state of NoSQL databas-


es. It includes articles, a presentation and a virtual panel
discussion covering a variety of topics ranging from highly
The C# programming language was first released to
the public in 2000. and since that time the language
has evolved through 6 releases to add everything
from generics to lambda expressions to asynchro-
nous methods and string interpolation. In this eMag
we have curated a collection of new and previously
content that provides the reader with a solid intro-
duction to C# 7 as it is defined today.

44
distributed computations, time series databases to what it
takes to transition to a NoSQL database solution. Cloud Lock-In

Technology choices are made, and because of a va-


riety of reasons--such as multi-year licensing cost,
tightly coupled links to mission-critical systems,
long-standing vendor relationships--you feel “locked
into” those choices. In this InfoQ eMag, we explore the
topic of cloud lock-in from multiple angles and look
for the best ways to approach it.

Potrebbero piacerti anche