observables reactive libs review observable/design pattern observables streams javarx demo...
TRANSCRIPT
Observables
Reactive LibsReview Observable/Design Pattern
Observables StreamsJavaRx Demo
ScalaRxShell Demo
RxLibs
Microsoft open source https://rx.codeplex.com/
Open source implementations of ReactiveX: https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxScala
Netflix open source: http://techblog.netflix.com/2013/02/rxjava-netflix-api
.html Additions on ReactiveX, competition to akka
Observable/Observer not reactive
Java Design pattern. Not useful for async or distributed systems. Pre 2000.
package com.example;
import java.util.Observable;import java.util.Observer;
//models customer going to coffeeshop. can change name. leave observerpublic class MyObserver implements Observer{
private String name=null;private boolean atCoffeeShop=false;
MyObserver(String n){ this.name=n;}
@Overridepublic void update(Observable o, Object arg) {
// TODO Auto-generated method stubSystem.out.println("calling update callback for:"+name);
}
}
Observable
package com.example;
import java.util.Observable;
public class CoffeeShop extends Observable{
public void enterCoffeeShop(MyObserver obs){ addObserver(obs);}
public void notifyCustomers(){setChanged();notifyObservers();}}
Main.java
package com.example;
public class Main{public static void main(String []args){CoffeeShop cs = new CoffeeShop();cs.addObserver(new MyObserver("cust1"));cs.addObserver(new MyObserver("cust2"));cs.addObserver(new MyObserver("cust3"));cs.notifyCustomers();}}
Output:calling update callback for:cust3calling update callback for:cust2calling update callback for:cust1
Run instr:
Download zip: https://github.com/dougc333/TestCode
Unarchive, cd TestCode-master/TestObservable, mvn compile
$ mvn exec:java -Dexec.mainClass=com.example.Main
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
calling update callback for:cust3
calling update callback for:cust2
calling update callback for:cust1
RxJava
NOT ASYNC
the Coffeeshop/Observable notifies all the observers via callback function. JavaRx, JavaRxScala add to this design pattern for event streams and to make async programming possible.
EventStreams=Subscriptions Async: Try/onNext,onComplete No Locks, Threads, etc...abstracted away Note: code style cleaner than Observer/Observable. Everything in
subscription class. No separate driver program needed
http://docs.couchbase.com/prebuilt/java-sdk-2.0-beta/topics/observables.html
RxJava
Create an observerable stream using .just(1,2,3)
Add a subscriber(lazy eval), similar to observer but add the duality of iterables. Iterable/Observer stream programming. Iterables block/bad perf. JavaRx adds threads + async onNext <-> next() onComplete ↔ hasNext() onError ↔ throws exception
RxJava Create stream, print
package com.example;
import rx.Observable; public class TestObservable{ public static void main(String []args){
System.out.println("asdf");Observable.just(5,6,7,8).subscribe(new MySubscriber<Integer>());//endless stream //Observable.just(5,6,7,8).repeat().subscribe(new
MySubscriber<Integer>());
}}
Subscriber
import rx.Subscriber;class MySubscriber<Integer> extends Subscriber<Integer>{
@Overridepublic void onCompleted() {
// TODO Auto-generated method stubSystem.out.println("onCompleted");
}
@Overridepublic void onError(Throwable throwable) {
// TODO Auto-generated method stub System.err.println(Error: " + throwable.getMessage());
}
@Overridepublic void onNext(Object arg0) {
// TODO Auto-generated method stub System.out.println("onNext: " + arg0);
}
}
Run instr:
cd TestObservable/TestJavaRx mvn clean;mvn compile $ mvn exec:java -
Dexec.mainClass=com.example.TestObservable
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
onNext: 5
onNext: 6
onNext: 7
onNext: 8
onComplete
RxJava Create
static <T> Observable<T>create(Observable.OnSubscribe<T> f)
Returns an Observable that will execute the specified function when a Subscriber subscribes to it.
Create a separate class
package com.example;
import rx.*;
//implement logic when to call onNext(), onError(), onComplete() by using create()//demo onlypublic class CreateObservable<Integer> implements Observable.OnSubscribe<Integer>{
@Overridepublic void call(Subscriber<? super Integer> arg0) { // TODO Auto-generated method stub Subscriber subscriber = (Subscriber) arg0; try{ if(!subscriber.isUnsubscribed()){ for(int i=0;i<5; i++){ subscriber.onNext(i); } subscriber.onCompleted(); } }catch(Exception e){ subscriber.onError(e); }}}
Add subscribe. No drivers!!!
package com.example;
import rx.*;import rx.functions.Action1;
public class ObservableCreate {
public static void main(String args[]){ Observable.create(new CreateObservable<Integer>()).subscribe(new Action1<Integer>() {@Override public void call(Integer integer) { System.out.println("onNext: " + integer); }}); } }
Run from eclipse
Run function Action1 everytime subscriber subscribes. Lazy eval, have to call subscribe to start data processing
RxJava API Example
Some things are easier in RxJava, create a counter once per second. No locks, no threads. Errors and cancellation(unsubscribe) built into the API. Less custom code and less testing.
Timer.java
package com.example;
import rx.*;import rx.functions.Action1;
import java.util.concurrent.*;
public class Timer { static CountDownLatch latch = new CountDownLatch(5); public static void main(String args[]) throws InterruptedException{Observable.interval(1,TimeUnit.SECONDS).subscribe(new Action1<Long>(){ public void call(Long counter){ latch.countDown(); System.out.println("Timer Secs:"+counter); }});
latch.await(); }}
RxJava Map Java7
Uses functions to replace the x=>f(x) notation Modify the timer example to use a map to print
out the thread it is operating on Use the testing code. The countdown latch for interval sequences
when another thread creates the sequence. Interval is threaded, see scheduler operator
table:https://github.com/ReactiveX/RxJava/wiki/Scheduler#using-schedulers
Timer threads
The observable does the work in one thread and the results via the subscriber are displayed in another thread.
class RxThread[T](o:Observable[T]) { def execAsync[T] = { o.subscribeOn(Schedulers.newThread) .observeOn(AndroidSchedulers.mainThread()) .materialize }}
/** * Convert implicitly a Java Observable in a Scala Observable. */object RxThread {implicit def Observable2Notification[T](o: Observable[T]) = new RxThread(o)}
Add func
public static void debugTimer() throws InterruptedException{ Observable.interval(1,TimeUnit.SECONDS).map(new Func1<Long,Long>(){ @Override public Long call(Long i){ System.out.println(Thread.currentThread().getName()); return i; } }).subscribe(new Action1<Long>(){ public void call(Long counter){ latch.countDown(); System.out.println("Timer Secs:"+counter); }});
latch.await(); }
How about a sequence?
public static void debugSeq() { Observable.just(1,2,3,4,5).map(new Func1<Integer,Integer>(){ @Override public Integer call(Integer i){ System.out.println(Thread.currentThread().getName()); return i; } }).subscribe(new Action1<Integer>(){ @Override public void call(Integer i){ System.out.println("onNext: " + i); } }); }
RxJava Twitter Ex. Building APIs
http://java.dzone.com/articles/turning-twitter4j-rxjavas
Turning Twitter4J into Observable. Creates API for stream processing/multiuser nonblocking.
Goal: API for user, rolling count of tweets
Making RxJava Async and Parallel
Trick from lecture: if the return type is <T> this is blocking. If Observable<T> or Future<T> then this is async.
Look at BlockingObservable return types. Marble diagram=>parallel
JavaRx parallel
JavaRx controls thread pools using schedulers as describe in lecture when EM compared ExecutionContext from Promises/Futures to Observables.
Just using flatMap doesn't guarantee multiple threads. A flatMap returns Observable<T> which is the first criteria for parallelism
Schedulers add parallelism
Debug:Thread.getCurrentThread().getName(), getCount()
Debug threads in JavaRx/Java adding to map() using Func1
Debug in Rx/Scala adding .debug() to package.scala
http://www.grahamlea.com/2014/07/rxjava-threading-examples/
Multiple ways to add threads
Docs not clear, look at the JavaRx test code Test code does this: Creating your own threads
In the observable call? OnNext()?
Blog does this: Using the thread pool from the scheduler
Add spark executors or create your own executor framework using zookeeper(TBD)
Rx/Scala
Scala wrapper around a RxJava https://github.com/ReactiveX/RxScala
Scala REPL for Observables Not avail from websearch Change $TOOL_PATH under $SCALA_HOME/bin
or copy the jars from suggestions/lib_managed/com.netflix.rxjava and rxjava-scala into $SCALA_HOME/lib dir.
JavaRx
The APIs are different between JavaRx/JavaRxScala/JavaRxNET
From lecture: Create a stream, notify subscribers on change to
represent processing, schedulers manage thread pools vs.
ExecutionContext in Futures, apply ops to streams which return Observables
Scala REPL bug
scala> import rx.lang.scala._
scala> val ob = Observable(1,2,3,4)
java.lang.NoSuchMethodError: scala.collection.JavaConverters$.asJavaIterableConverter(Lscala/collection/Iterable;)Lscala/collection/convert/Decorators$AsJava;
at rx.lang.scala.Observable$.apply(Observable.scala:1924)
Upgrade to latest scala version; 2.11.2; 2 I/Fs, RxScala
scala> import rx.lang.scala._
import rx.lang.scala._
scala> val ob = Observable(1,2,3,4)
ob: rx.lang.scala.Observable[Int] = rx.lang.scala.Observable$$anon$9@750cdd5e
scala>
Importing the wrong lib, RxJava
scala> import rx._
import rx._
scala> val foo = Observable.just(1,2,3,4)
foo: rx.Observable[(Int, Int, Int, Int)] = rx.Observable@18a8422d
scala>
Upgrade to latest scala version; 2.11.2
scala> import rx.lang.scala._
import rx.lang.scala._
scala> val ob = Observable(1,2,3,4)
ob: rx.lang.scala.Observable[Int] = rx.lang.scala.Observable$$anon$9@750cdd5e
scala>
Import the netflix jars(no scheduler)
Download from maven central, use the .20.4 versions not the 0.15.0 versions in the hw
rxjava-async-util-0.20.4.jar rxjava-computation-expressions-0.20.4.jar rxjava-core-0.15.0.jar rxjava-core-0.20.4.jar rxjava-scala-0.15.0.jar rxjava-scala-0.20.4.jar
Subscribe to the Observable, much easier than Java7
scala> foo.subscribe(x=>println(x))
1
2
3
4
res0: rx.lang.scala.Subscription = rx.lang.scala.subscriptions.Subscription$$anon$1@4f91659c
Observables
Repeat Rx in Scala Observables require subscribers to send
notifications to when data is ready in the Observable. An observable is the dual of an iterator but can return 0 or many events or an Error. Key is the 0 event.
Doesn't have to be async An observable interface contains:
onNext onError onCompleted