observables reactive libs review observable/design pattern observables streams javarx demo...

42
Observables Reactive Libs Review Observable/Design Pattern Observables Streams JavaRx Demo ScalaRxShell Demo

Upload: tracey-lee

Post on 16-Dec-2015

245 views

Category:

Documents


1 download

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 Instr:

Run from eclipse

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(); }}

Run Inst;

Run in eclipse

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); } }); }

Run inst;

Comment out either debugTimer() or debugSeq() , run Timer.java in Eclipse or maven

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

Marble=>parallelism

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

Repl lib path

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

RxScala

Homework apply() (for maps, flatMap) Add what on top of adding subscribers to

observables?

Subjects

For async programming, a subject is like a promise. A promise contains a future just as a future has to wait for a promise to write the data

A subject contains an Observable<T> or Observer<T>?