Fatal Exception: java.lang.OutOfMemoryError

OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available

March 16, 2016 | GitHub: ksza / rx_tmjug

The fundamentals of Reactive Streams in Java. A hands on experience

Thinking in Reactive Programming, with examples - RxJava

Reactive Programming

March 16, 2016 | GitHub: ksza / rx_tmjug

  • is programming with asynchronous data streams
  • anything can be a stream: user inputs, data structures, etc
  • a generous toolbox of functions to create, filter & combine streams

March 16, 2016 | GitHub: ksza / rx_tmjug

Why ReactiveX?

ReactiveX is more than an API, it's an idea and a breakthrough in programming. It has inspired several other APIs, frameworks, and even programming languages.

Reactive Revolution

  1. The Reactive Streams API, heavily influenced by RxJava
  2. Doug Lea - request to include RS idiom in Java 9

March 16, 2016 | GitHub: ksza / rx_tmjug

Adopting Reactive Programming

The hardest part of the learning journey is thinking in Reactive

... we'll try a kata

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx

  • What's Rx
  • Exercise: Explore some simple Rx operators

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx

... a Reactive Extension for the JVM

March 16, 2016 | GitHub: ksza / rx_tmjug

The Observer pattern done right

ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern, and functional programming

1. Intro to Rx

  • Extends the observer pattern
  • Supports sequences of data and/or event
  • Compose sequences together declaratively using operators
  • Abstracts away: low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx - Simple Observable

obs = Observable.just(1, 2, 3, 4, 5);
obs.subscribe(onNext, onError, onComplete);

1

2

3

4

5

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx - Simple Observable

obs.subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer value) { /* on emition */ }
}, new Action1<Throwable>() {
    @Override
    public void call(Throwable throwable) { /* on error */ }
}, new Action0() {
    @Override
    public void call() { /* on complete */ }
});

March 16, 2016 | GitHub: ksza / rx_tmjug

Observable.just(1, 2, 3, 4, 5)
          .map(new Func1<Integer, String>() {
              @Override
              public String call(Integer number) {
                  return number.toString();
              }
          });

1. Intro to Rx - Map Operator

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx - Map Operator

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx - Filter Operator

(Chaining)

Observable obs = Observable.just(1, 2, 3, 4, 5)
          .filter(new Func1<Integer, Boolean>() {
              @Override
              public Boolean call(Integer number) {
                  return number % 2 == 0;
              }
          })
          .map(new Func1<Integer, String>() {
              @Override
              public String call(Integer number) {
                  return number.toString();
              }
          });

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx

March 16, 2016 | GitHub: ksza / rx_tmjug

1. Intro to Rx

  • Observables are immutable
  • Compose functions into processing chains
  • Avoid callback hell
  • Structured code, feels like the right way!

March 16, 2016 | GitHub: ksza / rx_tmjug

public void fetchUserDetails() {
    // first, request the users...
    mService.requestUsers(new Callback<GithubUsersResponse>() {
        @Override
        public void success(final GithubUsersResponse githubUsersResponse, final Response response) {
            // Request Users request completed
            final List<GithubUserDetail> githubUserDetails = new ArrayList<GithubUserDetail>();
            // next, loop over each item in the response
            for (GithubUserDetail githubUserDetail : githubUsersResponse) {
                // request a detail object for that user
                mService.requestUserDetails(githubUserDetail.mLogin, new Callback<GithubUserDetail>() {
                    @Override
                    public void success(GithubUserDetail githubUserDetail, Response response) {
                        // User Detail request completed for user
                        githubUserDetails.add(githubUserDetail);
                        if (githubUserDetails.size() == githubUsersResponse.mGithubUsers.size()) {
                            // update UI with user details 
                        }
                    }

                    @Override
                    public void failure(RetrofitError error) {
                        // Request User Detail Failed
                    }
                });
            }
        }

        @Override
        public void failure(RetrofitError error) { /* Request User Failed!!!! */ }
    });
}
public void rxFetchUserDetails() {
    // request the users
    mService.rxRequestUsers().concatMap(Observable::from)
    .concatMap((GithubUser githubUser) ->
        // request the details for each user
        mService.rxRequestUserDetails(githubUser.mLogin)
    )
    // accumulate them as a list
    .toList()
    // define which threads information will be passed on
    .subscribeOn(Schedulers.newThread())
    .observeOn(JavaFxScheduler.getInstance())
    // post them on an eventbus
    .subscribe(githubUserDetails -> { /* update UI with user details */ });
}

Exercise 1: Intro to Rx

git clone git@github.com:ksza/rx_tmjug.git
cd rx_tmjug
git checkout ex1
git checkout -b ex1
  • Explore the ExampleUnitTest class
  • Rewrite the "testObservable" method using TestSubscriber

March 16, 2016 | GitHub: ksza / rx_tmjug

2. Lambda expression

"... they provide a clear and concise way to represent one method interface using an expression ... "

-- Java 8

March 16, 2016 | GitHub: ksza / rx_tmjug

2. Lambda expression

/* no arguments, single statement */  () -> 42
/* one argument */                    number -> number * 2
/* multiple arguments */              (i, j) -> i * j
/* multiple arguments types */        (int i, long j) -> i * j

/* multiple statements */
(int i, long j) -> { long result = i * j; return result; }

March 16, 2016 | GitHub: ksza / rx_tmjug

2. Less code using with lambdas

Observable.just(1, 2, 3, 4, 5)
          .map(new Func1<Integer, String>() {
              @Override
              public String call(Integer number) {
                  return number.toString();
              }
          });

becomes

Observable.just(1, 2, 3, 4, 5)
          .map(i -> i.toString());

March 16, 2016 | GitHub: ksza / rx_tmjug

2. Lambda expressions - Method Reference

obs = Observable.just("1", "2", "3")

/* lambda enhanced code */
obs.map(nr -> Integer.parseInt(nr))

/* using method reference */
obs.map(Integer::parseInt)
  • sometimes, a lambda expression does nothing but call an existing method

March 16, 2016 | GitHub: ksza / rx_tmjug

Exercise 2: Less code with lambdas

Neat huh?! Let's get to work

  • Play around with the IDE features to expand/replace lambda expressions
  • Write a new test for transforming Integers into Strings

March 16, 2016 | GitHub: ksza / rx_tmjug

Exercise 3: Explore Rx Operators

  • Please make all tests in ExploreSimpleOperatorsTest pass using only Rx operators!
  • Fix the tests sequentially

March 16, 2016 | GitHub: ksza / rx_tmjug

4. Reactive HTTP with Retrofit

"Retrofit turns your HTTP API into a Java interface"

March 16, 2016 | GitHub: ksza / rx_tmjug

4. Reactive HTTP with Retrofit

public interface OmdbApi {
    @GET("/?y=&plot=short&r=json")
    Observable<OmdbMovie> findByTitle(@Query("t") String t);
}
...
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.omdbapi.com")
        .build();

OmdbApi api = retrofit.create(OmdbApi.class);

March 16, 2016 | GitHub: ksza / rx_tmjug

Exercise 4: Reactive HTTP with Retrofit

git add -A && git commit -m "progress"
git checkout ex2
git checkout -b ex2
  • Explore & execute tests for the provided API

March 16, 2016 | GitHub: ksza / rx_tmjug

Exercise 5: Easy networking with reactive streams

  • Search movies by title using the api and display results in popup

March 16, 2016 | GitHub: ksza / rx_tmjug

5. Schedulers

  • By default, an Observable and the operators, will work on the same thread on which its the subscribe method is called
  • subscribeOn: Schedulers.computation(), Schedulers.io(), etc
  • observeOn: JavaFxScheduler.getInstance(), etc

March 16, 2016 | GitHub: ksza / rx_tmjug

March 16, 2016 | GitHub: ksza / rx_tmjug

6. Transforming Observables

  • RxBinding: Bind to your views and ui events in a reactive way
  • Use of flatMap and multithread 
git add -A && git commit -m "progress"
git checkout ex3
git checkout -b ex3

March 16, 2016 | GitHub: ksza / rx_tmjug

6. FlatMap

March 16, 2016 | GitHub: ksza / rx_tmjug

Returns an Observable that emits items based on applying a function that you supply to each item emitted by the source Observable, where that function returns an Observable, and then merging those resulting Observables and emitting the results of this merger.

6. FlatMap

March 16, 2016 | GitHub: ksza / rx_tmjug

6. Multithread ?

RxTextView.textChanges(searchText)
          .flatMap(title -> omdbApi.searchByTitle(title))
          .subscribeOn(Schedulers.io());

RxTextView.textChanges(searchText)
          .flatMap(
            title -> omdbApi.searchByTitle(title)
                            .subscribeOn(Schedulers.io())
          );

March 16, 2016 | GitHub: ksza / rx_tmjug

6. Unsubscribe

  • Fix memory leaks 
  1. Subscription.unsubscribe()
  2. CompositeSubscription 

March 16, 2016 | GitHub: ksza / rx_tmjug

7. Optimal "hot search"

git add -A && git commit -m "progress"
git checkout ex4
git checkout -b ex4
  • MovieSerchService#last_title_should_match_search
    should pass

March 16, 2016 | GitHub: ksza / rx_tmjug

7. Optimal "hot search"

To improve:

  • avoid too many requests
  • handle errors
  • responses are not ordered

March 16, 2016 | GitHub: ksza / rx_tmjug

7. Limiting throughput

March 16, 2016 | GitHub: ksza / rx_tmjug

7. Handling errors

March 16, 2016 | GitHub: ksza / rx_tmjug

7. Handling errors

March 16, 2016 | GitHub: ksza / rx_tmjug

7. flatMap = merge(map)

  • non blocking
  • fail fast

March 16, 2016 | GitHub: ksza / rx_tmjug

7. flatMap multithread

March 16, 2016 | GitHub: ksza / rx_tmjug

7. concatMap

  • Order is guaranteed
  • Blocking!

March 16, 2016 | GitHub: ksza / rx_tmjug

7. concatMap

March 16, 2016 | GitHub: ksza / rx_tmjug

7. switchMap

  • Subscribe for the last only
  • Unsubscribe/cancel the previous

March 16, 2016 | GitHub: ksza / rx_tmjug

7. switchMap

March 16, 2016 | GitHub: ksza / rx_tmjug

When the Producer is faster than the consumer

March 16, 2016 | GitHub: ksza / rx_tmjug

8. Backpressure

March 16, 2016 | GitHub: ksza / rx_tmjug

8. Backpressure

8. Backpressure

March 16, 2016 | GitHub: ksza / rx_tmjug

February 19, 2016 | GitHub: 3pillarlabs / rx_android_workshop

9. Fetch movie details

ToDo:

  • fetch the movie details using OmdbApi#getByTitle
  • update the details vie using MovieDetailsView#updateDetails

Thank You!

March 16, 2016 | GitHub: ksza / rx_tmjug

RxJava for tmJug

By Karoly Szanto

RxJava for tmJug

  • 403