The document provides an overview of RxJava and its advantages over traditional Java streams and callbacks. It discusses key RxJava concepts like Observables, Observers, and Subscriptions. It demonstrates how to create Observables, subscribe to them, and compose operations like filter, map, and zip. It shows how to leverage schedulers to control threading. The document also provides examples of using RxJava with HTTP requests and the Twitter API to asynchronously retrieve user profiles and tweets. It highlights scenarios where RxJava is useful, like handling asynchronous operations, and discusses some pitfalls like its learning curve and need to understand backpressure.
4. Pre Java 8 data processing
interface Iterator<T> {
T next();
boolean hasNext();
void remove();
}
5. Pre Java 8 data processing
List<Employee> employees = service.getEmployees();
Map<Integer, List<Employee>> ageDistribution = new HashMap<>();
for (Employee employee : employees) {
if (employee.getAge() > 25){
List<Employee> thisAge = ageDistribution.get(employee.getAge());
if (thisAge != null){
thisAge.add(employee);
} else{
List<Employee> createThisAge = new ArrayList<>();
createThisAge.add(employee);
ageDistribution.put(employee.getAge(), createThisAge);
}
}
}
System.out.println(ageDistribution);
6. Java 8 Stream ...
● Connects data source and client
● Do not hold any data
● Implements map / filter / reduce pattern
● Enforces functional style of data processing
7. Stream collectors
List<Employee> employees = service.getEmployees();
Map<Integer, List<Employee>> ageDistribution = new HashMap<>();
for (Employee employee : employees) {
if (employee.getAge() > 25) {
List<Employee> thisAge = ageDistribution.get(employee.getAge());
if (thisAge != null){
thisAge.add(employee);
} else {
List<Employee> createThisAge = new ArrayList<>();
createThisAge.add(employee);
ageDistribution.put(employee.getAge(), createThisAge);
}
}
}
System.out.println(ageDistribution);
13. Spliterator interface
public interface Spliterator<T> {
boolean tryAdvance(Consumer<? super T> action);
Spliterator<T> trySplit();
long estimateSize();
int characteristics();
}
14. class RandomSpliterator implements Spliterator<String> {
public boolean tryAdvance(Consumer<? super String> action) {
action.accept(UUID.randomUUID().toString());
return true;
}
// for parallel streams
public Spliterator<String> trySplit() {
return null;
}
public long estimateSize() { return Long.MAX_VALUE; };
public int characteristics() { return NONNULL | DISTINCT; }
}
26. Observable
● Central class in RxJava library
● It’s big: ~ 10k lines of code (with comments)
● It’s complex: ~ 100 static methods, ~ 150 non-static
27. Subscription sub =
Observable
.create(s -> {
s.onNext("A");
s.onNext("B");
s.onCompleted();
})
.subscribe(m -> log.info("Message received: " + m),
e -> log.warning("Error: " + e.getMessage()),
() -> log.info("Done!"));
Output:
Message received: A
Message received: B
Done!
28. Observable<Integer> empty = Observable.empty();
Observable<Integer> never = Observable.never();
Observable<Integer> error = Observable.error(exception);
Observable useful for tests
never() - never emit anything (no data, no errors)
29. public static <T, Resource> Observable<T> using(
final Func0<Resource> resourceFactory,
final Func1<Resource, Observable<T>> observableFactory,
final Action1<Resource> disposeAction
){ }
Observable from resource
39. Schedulers
public final class Schedulers {
public static Scheduler immediate() {...}
public static Scheduler trampoline() {...}
public static Scheduler newThread() {...}
public static Scheduler computation() {...}
public static Scheduler io() {...}
public static TestScheduler test() {...}
public static Scheduler from(Executor executor) {...}
}
47. Backpressure
Backpreasure is a way to slow down emission of elements
It can act on observing side
Strategies:
● Buffering items (buffer, window)
● Skipping items (sampling, throttling, etc)
● Request for specific number of elements
49. Stream API vs RxJava
RxJava:
● allows to process data in chosen thread, this is useful for IO,
computations, specialized threads (GUI threads),
● allows synchronization on clocks and application events,
● works in push mode, producer initiates data transfer, but consumer may
control data flow via backpressure.
Stream API:
● tuned for hot data processing,
● good for parallel computation,
● has rich set of collectors for data.
50. Shakespeare Plays Scrabble Benchmark (throughput)
Non-Parallel Streams 44.995 ± 1.718 ms/op
Parallel Streams 14.095 ± 0.616 ms/op
RxJava 310.378 ± 9.688 ms/op
RxJava (2.0.0-RC4) 156.334 ± 8.423 ms/op
Performance
Based on JMH benchmark by Jose Paumard
51. Scenarios where RxJava shines
● Observables are better callbacks (easily wrap callbacks)
● Observables are highly composable (on contrast with callbacks)
● Provide async stream of data (on contrast with CompletableFuture)
● Observables can handle errors (have retry / backup strategies)
● Give complete control over running threads
● Good for managing IO rich application workflows
● Perfect for Android development (no Java 8 required, retrolambda compatible)
● Netflix uses RxJava for most their internal APIs
53. Stream API and RxJava are friends!
You can easily build Observable from Stream
Iterator<T> iterator = ...;
Observable<T> observable = Observable.from(() -> iterator);
You can map Observable to Stream by implementing adapter
public static<T> Iterator<T> of(Observable<? extends T> ob){
class Adapter implements Iterator<T>, Consumer<T> {
...
}
return new Adapter();
}
54. External libraries that work with RxJava
● hystrix - latency and fault tolerance bulkheading library
● camel RX - to reuse Apache Camel components
● rxjava-http-tail - allows you to follow logs over HTTP
● mod-rxvertx - extension for VertX that provides support Rx
● rxjava-jdbc - use RxJava with JDBC to stream ResultSets
● rtree - immutable in-memory R-tree and R*-tree with RxJava
● and many more ...
55. RxJava is not new
JDeferred
CompletableFuture<T>
Scala.Rx
Scala Actors
Spring Integration
56. What’s around?
● Google Agera - reactive streams for Android by Google
● Project Reactor - flow API implementation by Pivotal & Spring
● Akka-Streams - Akka based streams
● Monix - Scala based implementation of Reactive Streams
● Vert.x, Lagom - if you want more than streams
59. Twitter API
Twitter Stream API (WebSocket alike):
● Doc: https://dev.twitter.com/streaming/overview
● Library: com.twitter:hbc-core:2.2.0
Twitter REST API:
● GET https://api.twitter.com/1.1/users/show.json?screen_name=jeeconf
● GET https://api.twitter.com/1.1/search/tweets.json?q=from:jeeconf
60. Let’s look at entities
class Tweet {
String text;
int favorite_count;
String author;
int author_followers;
}
class Profile {
String screen_name;
String name;
String location;
int statuses_count;
int followers_count;
}
class UserWithTweet {
Profile profile;
Tweet tweet;
}
77. ● API is big (150+ methods to remember)
● Requires to understand underlying magic
● Hard to debug
● Don’t forget about back pressure
Conclusions: pitfalls
78. ● It is functional, it is reactive*
● Good for integration scenarios
● Allows to control execution threads
● Easy to compose workflows
● Easy to integrate into existing solutions
● Easy Ok to test
* RxJava is inspired by FRP (Functional Reactive Programming), but doesn’t implement it
Conclusions: strength
79. ● RxJava 2.0 in few weeks!
● RxJava 2.0 is better and faster
● RxJava 2.0 is Java 9 Flow API compatible
● We will see more and more reactive streams
Conclusions: future