{"id":16376221,"url":"https://github.com/balamaci/rxjava-walkthrough","last_synced_at":"2025-06-25T18:32:22.999Z","repository":{"id":139271192,"uuid":"67806863","full_name":"balamaci/rxjava-walkthrough","owner":"balamaci","description":"RxJava playground","archived":false,"fork":false,"pushed_at":"2020-10-13T08:57:13.000Z","size":158,"stargazers_count":193,"open_issues_count":3,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-01T22:52:44.039Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/balamaci.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-09T14:42:30.000Z","updated_at":"2024-12-09T16:59:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"a0b840ad-4508-4fbe-a6e7-35d596482041","html_url":"https://github.com/balamaci/rxjava-walkthrough","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/balamaci/rxjava-walkthrough","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balamaci%2Frxjava-walkthrough","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balamaci%2Frxjava-walkthrough/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balamaci%2Frxjava-walkthrough/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balamaci%2Frxjava-walkthrough/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/balamaci","download_url":"https://codeload.github.com/balamaci/rxjava-walkthrough/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balamaci%2Frxjava-walkthrough/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261930862,"owners_count":23231970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T03:23:59.725Z","updated_at":"2025-06-25T18:32:22.978Z","avatar_url":"https://github.com/balamaci.png","language":"Java","readme":"# RxJava 2.x\n\nView at [Github page](https://balamaci.github.io/rxjava-walkthrough/)\n\nalso available for [reactor-core](https://github.com/balamaci/reactor-core-playground) \n\n## Contents \n \n   - [Flowable, Single and Observable](#flowable)\n   - [Simple Operators](#simple-operators)\n   - [Merging Streams](#merging-streams)\n   - [Hot Publishers](#hot-publishers)\n   - [Schedulers](#schedulers)\n   - [FlatMap Operator](#flatmap-operator)\n   - [Error Handling](#error-handling)\n   - [Backpressure](#backpressure)\n   - [Articles and books](#articles)\n\n## Reactive Streams\nReactive Streams is a programming concept for handling asynchronous \ndata streams in a non-blocking manner while providing backpressure to stream publishers.\nIt has evolved into a [specification](https://github.com/reactive-streams/reactive-streams-jvm) that is based on the concept of **Publisher\u0026lt;T\u0026gt;** and **Subscriber\u0026lt;T\u0026gt;**.\nA **Publisher** is the source of events **T** in the stream, and a **Subscriber** is the consumer for those events.\nA **Subscriber** subscribes to a **Publisher** by invoking a \"factory method\" in the Publisher that will push\nthe stream items **\u0026lt;T\u0026gt;** starting a new **Subscription**:\n\n```java\npublic interface Publisher\u003cT\u003e {\n    public void subscribe(Subscriber\u003c? super T\u003e s);\n}\n```\n\nWhen the Subscriber is ready to start handling events, it signals this via a **request** to that **Subscription**\n \n```java\npublic interface Subscription {\n    public void request(long n); //request n items\n    public void cancel();\n}\n```\n\nUpon receiving this signal, the Publisher begins to invoke **Subscriber::onNext(T)** for each event **T**. \nThis continues until either completion of the stream (**Subscriber::onComplete()**) \nor an error occurs during processing (**Subscriber::onError(Throwable)**).\n\n```java\npublic interface Subscriber\u003cT\u003e {\n    //signals to the Publisher to start sending events\n    public void onSubscribe(Subscription s);     \n    \n    public void onNext(T t);\n    public void onError(Throwable t);\n    public void onComplete();\n}\n```\n\n## Flowable and Observable\nRxJava provides more types of event publishers: \n   - **Flowable** Publisher that emits 0..N elements, and then completes successfully or with an error\n   - **Observable** like Flowables but without a backpressure strategy. They were introduced in RxJava 1.x\n   \n   - **Single** a specialized emitter that completes with a value successfully either an error.(doesn't have onComplete callback, instead onSuccess(val))\n   - **Maybe** a specialized emitter that can complete with / without a value or complete with an error.\n   - **Completable** a specialized emitter that just signals if it completed successfully or with an error.\n\nCode is available at [Part01CreateFlowable.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part01CreateFlowable.java)\n\n### Simple operators to create Streams\n```java\nFlowable\u003cInteger\u003e flowable = Flowable.just(1, 5, 10);\nFlowable\u003cInteger\u003e flowable = Flowable.range(1, 10);\nFlowable\u003cString\u003e flowable = Flowable.fromArray(new String[] {\"red\", \"green\", \"blue\"});\nFlowable\u003cString\u003e flowable = Flowable.fromIterable(List.of(\"red\", \"green\", \"blue\"));\n```\n\n\n### Flowable from Future\n\n```java\nCompletableFuture\u003cString\u003e completableFuture = CompletableFuture\n            .supplyAsync(() -\u003e { //starts a background thread the ForkJoin common pool\n                    log.info(\"CompletableFuture work starts\");  \n                    Helpers.sleepMillis(100);\n                    return \"red\";\n            });\n\nSingle\u003cString\u003e single = Single.from(completableFuture);\nsingle.subscribe(val -\u003e log.info(\"Stream completed successfully : {}\", val));\n```\n\n\n### Creating your own stream\n\nWe can use **Flowable.create(...)** to implement the emissions of events by calling **onNext(val)**, **onComplete()**, **onError(throwable)**\n\nWhen subscribing to the Observable / Flowable with flowable.subscribe(...) the lambda code inside **create(...)** gets executed.\nFlowable.subscribe(...) can take 3 handlers for each type of event - onNext, onError and onCompleted.\n\nWhen using **Observable.create(...)** you need to be aware of [backpressure](#backpressure) and that Observables created with 'create' are not BackPressure aware\n\n```java \nObservable\u003cInteger\u003e stream = Observable.create(subscriber -\u003e {\n    log.info(\"Started emitting\");\n\n    log.info(\"Emitting 1st\");\n    subscriber.onNext(1);\n\n    log.info(\"Emitting 2nd\");\n    subscriber.onNext(2);\n\n    subscriber.onComplete();\n});\n\n//Flowable version same Observable but with a BackpressureStrategy\n//that will be discussed separately.\nFlowable\u003cInteger\u003e stream = Flowable.create(subscriber -\u003e {\n    log.info(\"Started emitting\");\n\n    log.info(\"Emitting 1st\");\n    subscriber.onNext(1);\n\n    log.info(\"Emitting 2nd\");\n    subscriber.onNext(2);\n\n    subscriber.onComplete();\n}, BackpressureStrategy.MISSING);\n\nstream.subscribe(\n       val -\u003e log.info(\"Subscriber received: {}\", val),\n       err -\u003e log.error(\"Subscriber received error\", err),\n       () -\u003e log.info(\"Subscriber got Completed event\")\n);\n```\n\n### Streams are lazy \nStreams are lazy meaning that the code inside create() doesn't get executed without subscribing to the stream.\nSo event if we sleep for a long time inside create() method(to simulate a costly operation),\nwithout subscribing to this Observable, the code is not executed and the method returns immediately.\n\n```java\npublic void observablesAreLazy() {\n    Observable\u003cInteger\u003e observable = Observable.create(subscriber -\u003e {\n        log.info(\"Started emitting but sleeping for 5 secs\"); //this is not executed\n        Helpers.sleepMillis(5000);\n        subscriber.onNext(1);\n    });\n    log.info(\"Finished\"); \n}\n===========\n[main] - Finished\n```\n\n### Multiple subscriptions to the same Observable / Flowable \nWhen subscribing to an Observable/Flowable, the create() method gets executed for each Subscriber, the events \ninside **create(..)** are re-emitted to each subscriber independently. \n\nSo every subscriber will get the same events and will not lose any events - this behavior is named **'cold observable'**\nSee [Hot Publishers](#hot-publisher) to understand sharing a subscription and multicasting events.\n \n```java\nObservable\u003cInteger\u003e observable = Observable.create(subscriber -\u003e {\n   log.info(\"Started emitting\");\n\n   log.info(\"Emitting 1st event\");\n   subscriber.onNext(1);\n\n   log.info(\"Emitting 2nd event\");\n   subscriber.onNext(2);\n\n   subscriber.onComplete();\n});\n\nlog.info(\"Subscribing 1st subscriber\");\nobservable.subscribe(val -\u003e log.info(\"First Subscriber received: {}\", val));\n\nlog.info(\"=======================\");\n\nlog.info(\"Subscribing 2nd subscriber\");\nobservable.subscribe(val -\u003e log.info(\"Second Subscriber received: {}\", val));\n```\n\nwill output\n\n```\n[main] - Subscribing 1st subscriber\n[main] - Started emitting\n[main] - Emitting 1st event\n[main] - First Subscriber received: 1\n[main] - Emitting 2nd event\n[main] - First Subscriber received: 2\n[main] - =======================\n[main] - Subscribing 2nd subscriber\n[main] - Started emitting\n[main] - Emitting 1st event\n[main] - Second Subscriber received: 1\n[main] - Emitting 2nd event\n[main] - Second Subscriber received: 2\n```\n\n## Observable / Flowable lifecycle\n\n### Operators\nBetween the source Observable / Flowable and the Subscriber there can be a wide range of operators and RxJava provides \nlots of operators to chose from. Probably you are already familiar with functional operations like **filter** and **map**. \nso let's use them as example:\n\n```java\nFlowable\u003cInteger\u003e stream = Flowable.create(subscriber -\u003e {\n        subscriber.onNext(1);\n        subscriber.onNext(2);\n        ....\n        subscriber.onComplete();\n    }, BackpressureStrategy.MISSING);\n    .filter(val -\u003e val \u003c 10)\n    .map(val -\u003e val * 10)\n    .subscribe(val -\u003e log.info(\"Received: {}\", val));\n```\n\nWhen we call _Flowable.create()_ you might think that we're calling onNext(..), onComplete(..) on the Subscriber at the end of the chain, \nnot the operators between them.\n\nThis is not true because **the operators themselves are decorators for their source** wrapping it with the operator behavior \nlike an onion's layers. \nWhen we call **.subscribe()** at the end of the chain, **Subscription propagates through the layers back to the source,\neach operator subscribing itself to it's wrapped source Observable / Flowable and so on to the original source, \ntriggering it to start producing/emitting items**.\n\n**Flowable.create** calls **---\u0026gt; filterOperator.onNext(val)** which if val \u0026gt; 10 calls **---\u0026gt; \nmapOperator.onNext(val)** does val = val * 10 and calls **---\u0026gt; subscriber.onNext(val)**. \n\n[Found](https://tomstechnicalblog.blogspot.ro/2015_10_01_archive.html) a nice analogy with a team of house movers, with every mover doing it's thing before passing it to the next in line \nuntil it reaches the final subscriber.\n\n![Movers](https://1.bp.blogspot.com/-1RuGVz4-U9Q/VjT0AsfiiUI/AAAAAAAAAKQ/xWQaOwNtS7o/s1600/animation_2.gif) \n \n### Canceling subscription\nInside the create() method, we can check is there are still active subscribers to our Flowable/Observable.\n\nThere are operators that also unsubscribe from the stream so the source knows to stop producing events.  \nIt's a way to prevent to do extra work(like for ex. querying a datasource for entries) if no one is listening\nIn the following example we'd expect to have an infinite stream, but because we stop if there are no active subscribers, we stop producing events.   \n\n**take(limit)** is a simple operator. It's role is to count the number of events and then unsubscribes from it's source \nonce it received the specified amount and calls onComplete() to it's subscriber.\n\n```java\nObservable\u003cInteger\u003e observable = Observable.create(subscriber -\u003e {\n\n    int i = 1;\n    while(true) {\n        if(subscriber.isDisposed()) {\n             break;\n        }\n\n        subscriber.onNext(i++);\n        \n        //registering a callback when the downstream subscriber unsubscribes\n        subscriber.setCancellable(() -\u003e log.info(\"Subscription canceled\"));\n    }\n});\n\nobservable\n    .take(5) //unsubscribes after the 5th event\n    .subscribe(val -\u003e log.info(\"Subscriber received: {}\", val),\n               err -\u003e log.error(\"Subscriber received error\", err),\n               () -\u003e log.info(\"Subscriber got Completed event\") //The Complete event \n               //is triggered by 'take()' operator\n\n==================\n[main] - Subscriber received: *1*\n[main] - Subscriber received: *2*\n[main] - Subscriber received: *3*\n[main] - Subscriber received: *4*\n[main] - Subscriber received: *5*\n[main] - Subscriber got Completed event\n[main] - Subscription canceled\n```\n\n\n## Simple Operators\nCode is available at [Part02SimpleOperators.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part02SimpleOperators.java)\n\n### delay\nDelay operator - the Thread.sleep of the reactive world, it's pausing each emission for a particular increment of time.\n\n```java\nCountDownLatch latch = new CountDownLatch(1);\nFlowable.range(0, 2)\n        .doOnNext(val -\u003e log.info(\"Emitted {}\", val))\n        .delay(5, TimeUnit.SECONDS)\n        .subscribe(tick -\u003e log.info(\"Tick {}\", tick),\n                   (ex) -\u003e log.info(\"Error emitted\"),\n                   () -\u003e {\n                          log.info(\"Completed\");\n                          latch.countDown();\n                   });\nlatch.await();\n\n==============\n14:27:44 [main] - Starting\n14:27:45 [main] - Emitted 0\n14:27:45 [main] - Emitted 1\n14:27:50 [RxComputationThreadPool-1] - Tick 0\n14:27:50 [RxComputationThreadPool-1] - Tick 1\n14:27:50 [RxComputationThreadPool-1] - Completed\n```\n\nThe **.delay()**, **.interval()** operators uses a [Scheduler](#schedulers) by default which is why we see it executing\non a different thread _RxComputationThreadPool-1_ which actually means it's running the operators and the subscribe operations \non another thread and so the test method will terminate before we see the text from the log unless we wait for the completion of the stream. \nThis is the role of the **CountdownLatch**.\n\n### interval\nPeriodically emits a number starting from 0 and then increasing the value on each emission.\n\n```java\nlog.info(\"Starting\");\nFlowable.interval(5, TimeUnit.SECONDS)\n       .take(4)\n       .subscribe(tick -\u003e log.info(\"Subscriber received {}\", tick),\n                  (ex) -\u003e log.info(\"Error emitted\"),\n                  () -\u003e log.info(\"Subscriber got Completed event\"));\n\n==========\n12:17:56 [main] - Starting\n12:18:01 [RxComputationThreadPool-1] - Subscriber received: 0\n12:18:06 [RxComputationThreadPool-1] - Subscriber received: 1\n12:18:11 [RxComputationThreadPool-1] - Subscriber received: 2\n12:18:16 [RxComputationThreadPool-1] - Subscriber received: 3\n12:18:21 [RxComputationThreadPool-1] - Subscriber received: 4\n12:18:21 [RxComputationThreadPool-1] - Subscriber got Completed event\n```\n\n\n\n### scan\nTakes an **initial value** and a **function(accumulator, currentValue)**. It goes through the events\nsequence and combines the current event value with the previous result(accumulator) emitting downstream the function's\nresult for each event(the initial value is used for the first event)\n\n```java\nFlowable\u003cInteger\u003e numbers = \n                Flowable.just(3, 5, -2, 9)\n                    .scan(0, (totalSoFar, currentValue) -\u003e {\n                               log.info(\"TotalSoFar={}, currentValue={}\", \n                                            totalSoFar, currentValue);\n                               return totalSoFar + currentValue;\n                    });\n\n=============\n16:09:17 [main] - Subscriber received: 0\n16:09:17 [main] - TotalSoFar=0, currentValue=3\n16:09:17 [main] - Subscriber received: 3\n16:09:17 [main] - TotalSoFar=3, currentValue=5\n16:09:17 [main] - Subscriber received: 8\n16:09:17 [main] - TotalSoFar=8, currentValue=-2\n16:09:17 [main] - Subscriber received: 6\n16:09:17 [main] - TotalSoFar=6, currentValue=9\n16:09:17 [main] - Subscriber received: 15\n16:09:17 [main] - Subscriber got Completed event\n```\n\n### reduce\nreduce operator acts like the scan operator but it only passes downstream the final result \n(doesn't pass the intermediate results downstream) so the subscriber receives just one event\n\n```java\nFlowable\u003cInteger\u003e numbers = Flowable.just(3, 5, -2, 9)\n                            .reduce(0, (totalSoFar, val) -\u003e {\n                                         log.info(\"totalSoFar={}, emitted={}\",\n                                                        totalSoFar, val);\n                                         return totalSoFar + val;\n                            });\n                            \n=============                            \n17:08:29 [main] - totalSoFar=0, emitted=3\n17:08:29 [main] - totalSoFar=3, emitted=5\n17:08:29 [main] - totalSoFar=8, emitted=-2\n17:08:29 [main] - totalSoFar=6, emitted=9\n17:08:29 [main] - Subscriber received: 15\n17:08:29 [main] - Subscriber got Completed event\n```\n\n### collect\ncollect operator acts similar to the _reduce_ operator, but while the _reduce_ operator uses a reduce function\nwhich returns a value, the _collect_ operator takes a container supplier and a function which doesn't return\nanything(a consumer). The mutable container is passed for every event and thus you get a chance to modify it\nin this collect consumer function.\n\n```java\nFlowable\u003cList\u003cInteger\u003e\u003e numbers = Flowable.just(3, 5, -2, 9)\n                                        .collect(ArrayList::new, (container, value) -\u003e {\n                                            log.info(\"Adding {} to container\", value);\n                                            container.add(value);\n                                            //notice we don't need to return anything\n                                        });\n=========\n17:40:18 [main] - Adding 3 to container\n17:40:18 [main] - Adding 5 to container\n17:40:18 [main] - Adding -2 to container\n17:40:18 [main] - Adding 9 to container\n17:40:18 [main] - Subscriber received: [3, 5, -2, 9]\n17:40:18 [main] - Subscriber got Completed event\n```\n\nbecause the usecase to store to a List container is so common, there is a **.toList()** operator that is just a collector adding to a List. \n\n### defer\nAn easy way to switch from a blocking method to a reactive Single/Flowable is to use **.defer(() -\u003e blockingOp())**.\n\nSimply using **Flowable.just(blockingOp())** would still block, as Java needs to resolve the parameter when invoking\n**Flux.just(param)** method, so _blockingOp()_ method would still be invoked(and block).\n\n```java\n//NOT OK\nFlowable\u003cString\u003e flowableBlocked = Flowable.just((blockingOp())); //blocks on this line\n```\n    \nIn order to get around this problem, we can use **Flowable.defer(() -\u003e blockingOp())** and wrap the _blockingOp()_ call inside a lambda which \nwill be invoked lazy **at subscribe time**.\n\n```java\nFlowable\u003cString\u003e stream = Flowable.defer(() -\u003e Flowable.just(blockingOperation())); \nstream.subscribe(val -\u003e log.info(\"Val \" + val)); //only now the code inside defer() is executed\n```\n\n\n## Merging Streams\nOperators for working with multiple streams\nCode at [Part03MergingStreams.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part03MergingStreams.java)\n\n### zip\nZip operator operates sort of like a zipper in the sense that it takes an event from one stream and waits\nfor an event from another other stream. Once an event for the other stream arrives, it uses the zip function\nto merge the two events.\n\nThis is an useful scenario when for example you want to make requests to remote services in parallel and\nwait for both responses before continuing. It also takes a function which will produce the combined result\nof the zipped streams once each has emitted a value.\n\n![Zip](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/zip.png)\n\nZip operator besides the streams to zip, also takes as parameter a function which will produce the \ncombined result of the zipped streams once each stream emitted its value\n\n```java\nSingle\u003cBoolean\u003e isUserBlockedStream = \n                    Single.fromFuture(CompletableFuture.supplyAsync(() -\u003e {\n                            Helpers.sleepMillis(200);\n                            return Boolean.FALSE;\n                    }));\n\nSingle\u003cInteger\u003e userCreditScoreStream = \n                    Single.fromFuture(CompletableFuture.supplyAsync(() -\u003e {\n                            Helpers.sleepMillis(2300);\n                            return 5;\n                    }));\n\nSingle\u003cPair\u003cBoolean, Integer\u003e\u003e userCheckStream = Single.zip(isUserBlockedStream, userCreditScoreStream, \n                      (blocked, creditScore) -\u003e new Pair\u003cBoolean, Integer\u003e(blocked, creditScore));\n\nuserCheckStream.subscribe(pair -\u003e log.info(\"Received \" + pair));\n```\n\nEven if the 'isUserBlockedStream' finishes after 200ms, 'userCreditScoreStream' is slow at 2.3secs, \nthe 'zip' method applies the combining function(new Pair(x,y)) after it received both values and passes it \nto the subscriber.\n\n\nAnother good example of 'zip' is to slow down a stream by another basically **implementing a periodic emitter of events**:\n\n```java  \nFlowable\u003cString\u003e colors = Flowable.just(\"red\", \"green\", \"blue\");\nFlowable\u003cLong\u003e timer = Flowable.interval(2, TimeUnit.SECONDS);\n\nFlowable\u003cString\u003e periodicEmitter = Flowable.zip(colors, timer, (key, val) -\u003e key);\n```\n\nSince the zip operator needs a pair of events, the slow stream will work like a timer by periodically emitting \nwith zip setting the pace of emissions downstream every 2 seconds.\n\n**Zip is not limited to just two streams**, it can merge 2,3,4,.. streams and wait for groups of 2,3,4 'pairs' of \nevents which it combines with the zip function and sends downstream.\n\n### merge\nMerge operator combines one or more stream and passes events downstream as soon as they appear.\n\n![merge](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/merge.png)\n\n```\nFlowable\u003cString\u003e colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\nFlowable\u003cLong\u003e numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(5);\n                \n//notice we can't say Flowable\u003cString\u003e or Flowable\u003cLong\u003e as the return stream o the merge operator since \n//it can emit either a color or number.                  \nFlowable flowable = Flowable.merge(colors, numbers);                \n\n============\n21:32:15 - Subscriber received: 0\n21:32:16 - Subscriber received: red\n21:32:16 - Subscriber received: 1\n21:32:17 - Subscriber received: 2\n21:32:18 - Subscriber received: green\n21:32:18 - Subscriber received: 3\n21:32:19 - Subscriber received: 4\n21:32:20 - Subscriber received: blue\n```\n\n### concat\nConcat operator appends another streams at the end of another\n![concat](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/concat.png)\n\n```java\nFlowable\u003cString\u003e colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\nFlowable\u003cLong\u003e numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(4);\n\nFlowable events = Flowable.concat(colors, numbers);\n\n==========\n22:48:23 - Subscriber received: red\n22:48:25 - Subscriber received: green\n22:48:27 - Subscriber received: blue\n22:48:28 - Subscriber received: 0\n22:48:29 - Subscriber received: 1\n22:48:30 - Subscriber received: 2\n22:48:31 - Subscriber received: 3\n```\n\nEven if the 'numbers' streams should start early, the 'colors' stream emits fully its events\nbefore we see any 'numbers'.\nThis is because 'numbers' stream is actually subscribed only after the 'colors' complete.\nShould the second stream be a 'hot' emitter, its events would be lost until the first one finishes\nand the seconds stream is subscribed.\n\n## Hot Publishers\nWe've seen that with 'cold publishers', whenever a subscriber subscribes, each subscriber will get\nit's version of emitted values independently, the exact set of data indifferently when they subscribe.\nBut cold publishers only produce data when the subscribers subscribes, however there are cases where \nthe events happen independently from the consumers regardless if someone is \nlistening or not and we don't have control to request more. So you could say we have 'cold publishers' for pull\nscenarios and 'hot publishers' which push.\n\n### Subjects\nSubjects are one way to handle hot observables. Subjects keep reference to their subscribers and allow 'multicasting' \nan event to them.\n\n```java\nfor (Disposable\u003cT\u003e s : subscribers.get()) {\n    s.onNext(t);\n}\n```\n\nSubjects besides being traditional Observables you can use the same operators and subscribe to them,\nare also an **Observer**(interface like **Subscriber** from [reactive-streams](#reactive-streams), implementing the 3 methods **onNext, onError, onComplete**), \nmeaning you can invoke subject.onNext(value) from different parts in the code,\nwhich means that you publish events which the Subject will pass on to their subscribers.\n\n```java\nSubject\u003cInteger\u003e subject = ReplaySubject.create()\n                     .map(...);\n                     .subscribe(); //\n\n...\nsubject.onNext(val);\n...\nsubject.onNext(val2);\n```\nremember for \n```java\nObservable.create(subscriber -\u003e {\n      subscriber.onNext(val);\n})\n```\n\n### ReplaySubject\nReplaySubject keeps a buffer of events that it 'replays' to each new subscriber, first he receives a batch of missed \nand only later events in real-time.\n\n```java\nSubject\u003cInteger\u003e subject = ReplaySubject.createWithSize(50);\n\nlog.info(\"Pushing 0\");\nsubject.onNext(0);\nlog.info(\"Pushing 1\");\nsubject.onNext(1);\n\nlog.info(\"Subscribing 1st\");\nsubject.subscribe(val -\u003e log.info(\"Subscriber1 received {}\", val), \n                            logError(), logComplete());\n\nlog.info(\"Pushing 2\");\nsubject.onNext(2);\n\nlog.info(\"Subscribing 2nd\");\nsubject.subscribe(val -\u003e log.info(\"Subscriber2 received {}\", val), \n                            logError(), logComplete());\n\nlog.info(\"Pushing 3\");\nsubject.onNext(3);\n\nsubject.onComplete();\n\n==================\n[main] - Pushing 0\n[main] - Pushing 1\n[main] - Subscribing 1st\n[main] - Subscriber1 received 0\n[main] - Subscriber1 received 1\n[main] - Pushing 2\n[main] - Subscriber1 received 2\n[main] - Subscribing 2nd\n[main] - Subscriber2 received 0\n[main] - Subscriber2 received 1\n[main] - Subscriber2 received 2\n[main] - Pushing 3\n[main] - Subscriber1 received 3\n[main] - Subscriber2 received 3\n[main] - Subscriber got Completed event\n[main] - Subscriber got Completed event\n```\n\n### ConnectableObservable / ConnectableFlowable and resource sharing\nThere are cases when we want to share a single subscription between subscribers, meaning while the code that executes\non subscribing should be executed once, the events should be published to all subscribers.     \n\nFor ex. when we want to share a connection between multiple Observables / Flowables. \nUsing a plain Observable would just reexecute the code inside _.create()_ and opening / closing a new connection for each \nnew subscriber when it subscribes / cancels its subscription.\n\n**ConnectableObservable** are a special kind of **Observable**. No matter how many Subscribers subscribe to ConnectableObservable, \nit opens just one subscription to the Observable from which it was created.\n\nAnyone who subscribes to **ConnectableObservable** is placed in a set of Subscribers(it doesn't trigger\nthe _.create()_ code a normal Observable would when .subscribe() is called). A **.connect()** method is available for ConnectableObservable.\n**As long as connect() is not called, these Subscribers are put on hold, they never directly subscribe to upstream Observable**\n\n```java\nConnectableObservable\u003cInteger\u003e connectableObservable = \n                                  Observable.\u003cInteger\u003ecreate(subscriber -\u003e {\n        log.info(\"Inside create()\");\n\n     /* A JMS connection listener example\n         Just an example of a costly operation that is better to be shared **/\n\n     /* Connection connection = connectionFactory.createConnection();\n        Session session = connection.createSession(true, AUTO_ACKNOWLEDGE);\n        MessageConsumer consumer = session.createConsumer(orders);\n        consumer.setMessageListener(subscriber::onNext); */\n\n        subscriber.setCancellable(() -\u003e log.info(\"Subscription cancelled\"));\n\n        log.info(\"Emitting 1\");\n        subscriber.onNext(1);\n\n        log.info(\"Emitting 2\");\n        subscriber.onNext(2);\n\n        subscriber.onComplete();\n}).publish();\n\nconnectableObservable\n       .take(1)\n       .subscribe((val) -\u003e log.info(\"Subscriber1 received: {}\", val), \n                    logError(), logComplete());\n\nconnectableObservable\n       .subscribe((val) -\u003e log.info(\"Subscriber2 received: {}\", val), \n                    logError(), logComplete());\n\nlog.info(\"Now connecting to the ConnectableObservable\");\nconnectableObservable.connect();\n\n===================\n\n```\n\n### share() operator \nAnother operator of the ConnectableObservable **.refCount()** allows to do away with having to manually call **.connect()**,\ninstead it invokes the .create() code when the first Subscriber subscribes while sharing this single subscription with subsequent Subscribers.\nThis means that **.refCount()** basically keeps a count of references of it's subscribers and subscribes to upstream Observable\n(executes the code inside .create() just for the first subscriber), but multicasts the same event to each active subscriber. \nWhen the last subscriber unsubscribes, the ref counter goes from 1 to 0 and triggers any unsubscribe callback associated.   \nIf another Subscriber subscribes after that, counter goes from 0 to 1 and the process starts over again. \n\n```java\nConnectableObservable\u003cInteger\u003e connectableStream = Observable.\u003cInteger\u003ecreate(subscriber -\u003e {\n   log.info(\"Inside create()\");\n   \n   //Simulated MessageListener emits periodically every 500 milliseconds\n   ResourceConnectionHandler resourceConnectionHandler = new ResourceConnectionHandler() {\n        @Override\n        public void onMessage(Integer message) {\n             log.info(\"Emitting {}\", message);\n             subscriber.onNext(message);\n        }\n   };\n   resourceConnectionHandler.openConnection();\n\n   //when the last subscriber unsubscribes it will invoke disconnect on the resourceConnectionHandler\n   subscriber.setCancellable(resourceConnectionHandler::disconnect);\n}).publish(); \n\n//publish().refCount() have been joined together in the .share() operator\nObservable\u003cInteger\u003e observable = connectableObservable.refCount();\n\nCountDownLatch latch = new CountDownLatch(2);\nconnectableStream\n      .take(5)\n      .subscribe((val) -\u003e log.info(\"Subscriber1 received: {}\", val), \n                    logError(), logComplete(latch));\n\nHelpers.sleepMillis(1000);\n\nlog.info(\"Subscribing 2nd\");\n//we're not seing the code inside .create() reexecuted\nconnectableStream\n      .take(2)\n      .subscribe((val) -\u003e log.info(\"Subscriber2 received: {}\", val), \n                    logError(), logComplete(latch));\n\n//waiting for the streams to complete\nHelpers.wait(latch);\n\n//subscribing another after previous Subscribers unsubscribed\nlatch = new CountDownLatch(1);\nlog.info(\"Subscribing 3rd\");\nobservable\n     .take(1)\n     .subscribe((val) -\u003e log.info(\"Subscriber3 received: {}\", val), logError(), logComplete(latch));\n\n\nprivate abstract class ResourceConnectionHandler {\n\n   ScheduledExecutorService scheduledExecutorService;\n\n   private int counter;\n\n   public void openConnection() {\n      log.info(\"**Opening connection\");\n\n      scheduledExecutorService = periodicEventEmitter(() -\u003e {\n            counter ++;\n            onMessage(counter);\n      }, 500, TimeUnit.MILLISECONDS);\n   }\n\n   public abstract void onMessage(Integer message);\n\n   public void disconnect() {\n      log.info(\"**Shutting down connection\");\n      scheduledExecutorService.shutdown();\n   }\n}\n\n===============\n14:55:23 [main] INFO BaseTestObservables - Inside create()\n14:55:23 [main] INFO BaseTestObservables - **Opening connection\n14:55:23 [pool-1-thread-1] INFO BaseTestObservables - Emitting 1\n14:55:23 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 1\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Emitting 2\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 2\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Emitting 3\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 3\n14:55:24 [main] INFO BaseTestObservables - Subscribing 2nd\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Emitting 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber2 received: 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Emitting 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber2 received: 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - **Shutting down connection\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n14:55:25 [main] INFO BaseTestObservables - Subscribing 3rd\n14:55:25 [main] INFO BaseTestObservables - Inside create()\n14:55:25 [main] INFO BaseTestObservables - **Opening connection\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Emitting 1\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Subscriber3 received: 1\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - **Shutting down connection\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n```\nThe **share()** operator of Observable / Flowable is an operator which basically does **publish().refCount()**. \n\n## Schedulers\nRxJava provides some high level concepts for concurrent execution, like ExecutorService we're not dealing\nwith the low level constructs like creating the Threads ourselves. Instead we're using a **Scheduler** which create\nWorkers who are responsible for scheduling and running code. By default RxJava will not introduce concurrency \nand will run the operations on the subscription thread.\n\nThere are two methods through which we can introduce Schedulers into our chain of operations:\n\n   - **subscribeOn** allows to specify which Scheduler invokes the code contained in the lambda code for Observable.create()\n   - **observeOn** allows control to which Scheduler executes the code in the downstream operators\n\nRxJava provides some general use Schedulers:\n \n  - **Schedulers.computation()** - to be used for CPU intensive tasks. A threadpool. Should not be used for tasks involving blocking IO.\n  - **Schedulers.io()** - to be used for IO bound tasks  \n  - **Schedulers.from(Executor)** - custom ExecutorService\n  - **Schedulers.newThread()** - always creates a new thread when a worker is needed. Since it's not thread pooled and \n  always creates a new thread instead of reusing one, this scheduler is not very useful \n \nAlthough we said by default RxJava doesn't introduce concurrency. Notice how we are not doing anything on another thread\nthan the subscribing thread 'main' and the Test doesn't end until the complete event is processed:\n```java\n@Test\npublic void byDefaultRxJavaDoesntIntroduceConcurrency() {\n   log.info(\"Starting\");\n\n   Observable.\u003cInteger\u003ecreate(subscriber -\u003e {\n        log.info(\"Someone subscribed\");\n        subscriber.onNext(1);\n        subscriber.onNext(2);\n\n        subscriber.onComplete();\n   })\n   .map(val -\u003e {\n         log.info(\"Mapping {}\", val);\n         //what if we do some Thread.sleep here \n         //Thread.sleep(2000);\n         return val * 10;\n   })\n   .subscribe(logNext());\n}\n===============\n11:23:49 [main] INFO BaseTestObservables - Starting\n11:23:50 [main] INFO BaseTestObservables - Someone subscribed\n11:23:50 [main] INFO BaseTestObservables - Mapping 1\n11:23:50 [main] INFO BaseTestObservables - Subscriber received: 10\n11:23:50 [main] INFO BaseTestObservables - Mapping 2\n11:23:50 [main] INFO BaseTestObservables - Subscriber received: 20\n```\nnow let's enable that _Thread.sleep(2000)_ above.\n```\n11:42:12 [main] INFO BaseTestObservables - Starting\n11:42:12 [main] INFO BaseTestObservables - Someone subscribed\n11:42:12 [main] INFO BaseTestObservables - Mapping 1\n11:42:14 [main] INFO BaseTestObservables - Subscriber received: 10\n11:42:14 [main] INFO BaseTestObservables - Mapping 2\n11:42:16 [main] INFO BaseTestObservables - Subscriber received: 20\n``` \nas expected nothing changes, just that we receive the events in the Subscriber delayed by 2 secs.\nTo prevent this, lots of RxJava operators that involve waiting as **delay**,**interval**, **zip** run on a Scheduler, otherwise they would just block the subscribing thread. \nBy default **Schedulers.computation()** is used, but the Scheduler can be passed as a parameter to those methods.\n\nOk so how can we provide different threads to run the different parts of the code.\n\n### subscribeOn\nAs stated above **subscribeOn** allows to specify on which Scheduler thread the subscribtion is made - which thread invokes the code contained in the lambda for Observable.create() -\n(it's **not** abouth the thread for where the code in **.subscribe((val) -\u003e {...})** gets executed). \nSince the operators are lazy and nothing happens until subscription, where the **.subscribeOn()** is called doesn't make any difference.\nAlso calling **.subscribeOn()** multiple times at different positions doesn't have any effect, only the first **.subscribeOn()** Scheduler is considered.   \n\n\n```java\n@Test\npublic void testSubscribeOn() {\n   log.info(\"Starting\");\n\n   Observable\u003cInteger\u003e observable = Observable.create(subscriber -\u003e { \n       //code that will execute inside the IO ThreadPool\n       log.info(\"Starting slow network op\");\n       Helpers.sleepMillis(2000);\n\n       log.info(\"Emitting 1st\");\n       subscriber.onNext(1);\n\n       subscriber.onComplete();\n   });\n\n   observable = observable\n                .subscribeOn(Schedulers.io()) //Specify execution on the IO Scheduler\n                .map(val -\u003e {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n                    return newValue;\n                });\n\n   /** Since we are switching the subscription thread we now need to wait \n   * for the Thread to complete so again we are using the CountDownLatch \"trick\" to do it.\n   **/    \n   CountDownLatch latch = new CountDownLatch(1);\n   \n   observable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n   );\n   \n   Helpers.wait(latch);\n}\n\n===============\n13:16:31 [main] INFO BaseTestObservables - Starting\n13:16:31 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Starting slow network op\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 1st\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Mapping 1 to 10\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 10\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Subscriber got Completed event\n```\nNotice how the code and also the flow down the operators like **.map()** is switched to this new Scheduler that was specified. \n\n\n### observeOn\n**observeOn** allows control to which Scheduler executes the code in the downstream operators.\nSo by using **observeOn()** we changed the Scheduler for the **map** operator, but notice how the last **.observeOn(Schedulers.newThread())** \nwe also influence the code received by the subscriber, while **.subscribeOn()** just had a part on the code executed before we changed with **.observeOn()**  \n\n```java\nlog.info(\"Starting\");\n\nObservable\u003cInteger\u003e observable = \n        Observable.create(subscriber -\u003e { \n                    //code that will execute inside the IO Scheduler\n             log.info(\"Emitting 1st\");\n             subscriber.onNext(1);\n \n             log.info(\"Emitting 2nd\");\n             subscriber.onNext(2);\n \n             subscriber.onComplete();\n        })\n        .subscribeOn(Schedulers.io())\n        .observeOn(Schedulers.computation())\n        .map(val -\u003e {\n              int newValue = val * 10;\n              log.info(\"Mapping {} to {}\", val, newValue);\n              return newValue;\n        })\n        .observeOn(Schedulers.newThread());\n\n   CountDownLatch latch = new CountDownLatch(1);\n   \n   observable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n   );\n   \n   Helpers.wait(latch);\n\n===============\n19:35:01 [main] INFO BaseTestObservables - Starting\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Started emitting\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 1st\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 2nd\n19:35:01 [RxComputationThreadPool-1] INFO BaseTestObservables - Mapping 1 to 10\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 10\n19:35:01 [RxComputationThreadPool-1] INFO BaseTestObservables - Mapping 2 to 20\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 20\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber got Completed event\n```\n\n### back to blocking world \nHow about when we want to switch back to a blocking flow. We saw above how we need to explicitly use latching\nto keep the [main] thread. Say we're incrementally switching from legacy code and we have a Service method\n**Collection\\\u003cString\\\u003e findUsers()** inside this method we can still be reactive but to the caller of the method we\nstill need to block until we get all the elements of the Collection.\nUsing **blockingIterable** will block our Test thread till the Flow completes, waiting\nfor the events to be emitted(we're sleeping just to show it's not completing by chance).\n\n```java\nlog.info(\"Starting\");\n\nFlowable\u003cString\u003e flowable = simpleFlowable()\n                .subscribeOn(Schedulers.io())\n                .subscribeOn(Schedulers.computation())\n                .map(val -\u003e {\n                    String newValue = \"^^\" + val + \"^^\";\n                    log.info(\"Mapping new val {}\", newValue);\n                    Helpers.sleepMillis(500);\n                    return newValue;\n                });\n\nIterable\u003cString\u003e iterable = flowable.blockingIterable(); //this call will block until\n//the stream completes\niterable.forEach(val -\u003e log.info(\"Received {}\", val));\n\n==========================\n17:48:13 [RxCachedThreadScheduler-1] - Started emitting\n17:48:13 [RxCachedThreadScheduler-1] - Emitting 1st\n17:48:13 [RxCachedThreadScheduler-1] - Mapping new val ^^1^^\n17:48:14 [RxCachedThreadScheduler-1] - Emitting 2nd\n17:48:14 [main] - Received ^^1^^\n17:48:14 [RxCachedThreadScheduler-1] - Mapping new val ^^2^^\n17:48:14 [main] - Received ^^2^^\n17:48:14 [main] - Finished blockingIterable\n```\nwe can see the events being received back on the **\\[main\\]** thread.\n\n```java\n    //block until the stream completes or throws an error.\n    flowable.blockingSubscribe(val -\u003e log.info(\"Subscriber received {}\", val));\n```\n\n\n## Flatmap operator\nThe flatMap operator is so important and has so many different uses it deserves it's own category to explain it.\nCode at [Part06FlatMapOperator.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part06FlatMapOperator.java)\n\nI like to think of it as a sort of **fork-join** operation because what flatMap does is it takes individual stream items\nand maps each of them to an Observable(so it creates new Streams from each object) and then 'flattens' the events from \nthese Streams back as coming from a single stream.\n\nWhy this looks like fork-join because for each element you can fork some jobs that keeps emitting results,\nand these results are emitted back as elements to the subscribers downstream\n\n**Rules of thumb** to consider before getting comfortable with flatMap: \n   \n   - When you have an 'item' **T** and a method **T -\u0026lt; Flowable\u0026lt;X\u0026gt;**, you need flatMap. Most common example is when you want \n   to make a remote call that returns an Observable / Flowable . For ex if you have a stream of customerIds, and downstream you\n    want to work with actual Customer objects:    \n   \n   - When you have Observable\u0026lt;Observable\u0026lt;T\u0026gt;\u0026gt;(aka stream of streams) you probably need flatMap. Because flatMap means you are subscribing\n   to each substream.\n\nWe use a simulated remote call that returns asynchronous events. This is a most common scenario to make a remote call for each stream element, \n(although in non reactive world we're more likely familiar with remote operations returning Lists **T -\u0026gt; List\u0026lt;X\u0026gt;**).\nOur simulated remote operation produces as many events as the length of the color string received as parameter every 200ms, \nso for example **red : red0, red1, red2** \n\n```java\nprivate Flowable\u003cString\u003e simulateRemoteOperation(String color) {\n  return Flowable.intervalRange(1, color.length(), 0, 200, TimeUnit.MILLISECONDS)\n             .map(iteration -\u003e color + iteration);\n}\n```\n\nIf we have a stream of color names:\n\n```java\nFlowable\u003cString\u003e colors = Flowable.just(\"orange\", \"red\", \"green\")\n```\n\nto invoke the remote operation: \n\n```java\nFlowable\u003cString\u003e colors = Flowable.just(\"orange\", \"red\", \"green\")\n         .flatMap(colorName -\u003e simulatedRemoteOperation(colorName));\n\ncolors.subscribe(val -\u003e log.info(\"Subscriber received: {}\", val));         \n\n====\n16:44:15 [Thread-0]- Subscriber received: orange0\n16:44:15 [Thread-2]- Subscriber received: green0\n16:44:15 [Thread-1]- Subscriber received: red0\n16:44:15 [Thread-0]- Subscriber received: orange1\n16:44:15 [Thread-2]- Subscriber received: green1\n16:44:15 [Thread-1]- Subscriber received: red1\n16:44:15 [Thread-0]- Subscriber received: orange2\n16:44:15 [Thread-2]- Subscriber received: green2\n16:44:15 [Thread-1]- Subscriber received: red2\n16:44:15 [Thread-0]- Subscriber received: orange3\n16:44:15 [Thread-2]- Subscriber received: green3\n16:44:16 [Thread-0]- Subscriber received: orange4\n16:44:16 [Thread-2]- Subscriber received: green4\n16:44:16 [Thread-0]- Subscriber received: orange5\n```\n\nNotice how the results are coming intertwined(mixed) and it might not be as you expected it.This is because flatMap actually subscribes to it's inner Observables \nreturned from 'simulateRemoteOperation'. You can specify the **concurrency level of flatMap** as a parameter. Meaning \nyou can say how many of the substreams should be subscribed \"concurrently\" - after **onComplete** is triggered on the substreams,\na new substream is subscribed-.\n\nBy setting the concurrency to **1** we don't subscribe to other substreams until the current one finishes:\n\n```\nFlowable\u003cString\u003e colors = Flowable.just(\"orange\", \"red\", \"green\")\n                     .flatMap(val -\u003e simulateRemoteOperation(val), 1); //\n\n```\n\nNotice now there is a sequence from each color before the next one appears\n\n```\n17:15:24 [Thread-0]- Subscriber received: orange0\n17:15:24 [Thread-0]- Subscriber received: orange1\n17:15:25 [Thread-0]- Subscriber received: orange2\n17:15:25 [Thread-0]- Subscriber received: orange3\n17:15:25 [Thread-0]- Subscriber received: orange4\n17:15:25 [Thread-0]- Subscriber received: orange5\n17:15:25 [Thread-1]- Subscriber received: red0\n17:15:26 [Thread-1]- Subscriber received: red1\n17:15:26 [Thread-1]- Subscriber received: red2\n17:15:26 [Thread-2]- Subscriber received: green0\n17:15:26 [Thread-2]- Subscriber received: green1\n17:15:26 [Thread-2]- Subscriber received: green2\n17:15:27 [Thread-2]- Subscriber received: green3\n17:15:27 [Thread-2]- Subscriber received: green4\n```\n\nThere is actually an operator which is basically this **flatMap with 1 concurrency called concatMap**.\n\n\nInside the flatMap we can operate on the substream with the same stream operators\n\n```java\nObservable\u003cPair\u003cString, Integer\u003e\u003e colorsCounted = colors\n    .flatMap(colorName -\u003e {\n               Observable\u003cLong\u003e timer = Observable.interval(2, TimeUnit.SECONDS);\n\n               return simulateRemoteOperation(colorName) // \u003c- Still a stream\n                              .zipWith(timer, (val, timerVal) -\u003e val)\n                              .count()\n                              .map(counter -\u003e new Pair\u003c\u003e(colorName, counter));\n               }\n    );\n```\n\nWe can also use **switchIfEmpty** to provide some values when the original Publisher doesn't return anything, just completes.\n```java\nFlowable\u003cString\u003e colors = Flowable.just(\"red\", \"\", \"blue\")\n                            .flatMap(colorName -\u003e simulateRemoteOperation(colorName)\n                                                    .switchIfEmpty(Flowable.just(\"NONE\")));\n\n13:11:02  Subscriber received: red0\n13:11:02  Subscriber received: red1\n13:11:02  Subscriber received: red2\n13:11:03  Subscriber received: NONE\n13:11:03  Subscriber received: blue0\n13:11:03  Subscriber received: blue1\n13:11:03  Subscriber received: blue2\n13:11:03  Subscriber received: blue3\n13:11:03  Subscriber got Completed event\n```\n\n**flatMapIterable** is just an easy way to pass each of the elements of a collection\nas a stream\n```\nFlowable\u003cString\u003e colors = Flowable.just(1)\n                .flatMapIterable(it -\u003e generateColors());\n\n\nprivate List\u003cString\u003e generateColors() {\n   return Arrays.asList(\"red\", \"green\", \"blue\");\n}\n\n```\n\n**switchMap** operator also prevents inter-leavings as only one of stream is subscribed at a time, \nbut this is controlled from upstream. If a new value comes from upstream, the current subscribed inner-stream \n gets canceled and a new subscription is made for the new value.\nThe current stream will remain subscribed as long as there are no new values from upstream. \n```java   \nFlowable\u003cString\u003e colors = Flowable.interval(0,400, TimeUnit.MILLISECONDS)\n         .zipWith(Arrays.asList(\"EUR\", \"USD\", \"GBP\"), (it, currency) -\u003e currency)\n         .doOnNext(ev -\u003e log.info(\"Emitting {}\", ev))\n         .switchMap(currency -\u003e simulateRemoteOperation(currency)\n                      .doOnSubscribe((subscription) -\u003e log.info(\"Subscribed new\"))\n                      .doOnCancel(() -\u003e log.info(\"Unsubscribed {}\", currency))\n         );\n```\n\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting EUR\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:16 [RxComputationThreadPool-2] INFO BaseTestObservables - Subscriber received: EUR1\n17:45:16 [RxComputationThreadPool-2] INFO BaseTestObservables - Subscriber received: EUR2\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting USD\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Unsubscribed EUR\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:16 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD1\n17:45:16 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD2\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting GBP\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Unsubscribed USD\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:17 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD3\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP1\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP2\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP3\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber got Completed event\n\n## Error handling\nCode at [Part08ErrorHandling.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part08ErrorHandling.java)\n\nExceptions are for exceptional situations.\nThe Reactive Streams specification says that **exceptions are terminal operations**. \nThat means in case an error occurs, it triggers an unsubscription upstream and the error travels downstream to the Subscriber, invoking the 'onError' handler:\n\n```java\nObservable\u003cString\u003e colors = Observable.just(\"green\", \"blue\", \"red\", \"yellow\")\n       .map(color -\u003e {\n              if (\"red\".equals(color)) {\n                        throw new RuntimeException(\"Encountered red\");\n              }\n              return color + \"*\";\n       })\n       .map(val -\u003e val + \"XXX\");\n\ncolors.subscribe(\n         val -\u003e log.info(\"Subscriber received: {}\", val),\n         exception -\u003e log.error(\"Subscriber received error '{}'\", exception.getMessage()),\n         () -\u003e log.info(\"Subscriber completed\")\n);\n```\n\nreturns:\n```\n23:30:17 [main] INFO - Subscriber received: green*XXX\n23:30:17 [main] INFO - Subscriber received: blue*XXX\n23:30:17 [main] ERROR - Subscriber received error 'Encountered red'\n```\nAfter the map() operator encounters an error it unsubscribes(cancels the subscription) from upstream\n(therefore 'yellow' is not even emitted). The error travels downstream and triggers the error handler in the Subscriber.\n\n\nThere are operators to deal with error flow control:\n \n### onErrorReturn\n\nThe 'onErrorReturn' operator replaces an exception with a value:\n\n```java\nFlowable\u003cInteger\u003e numbers = Flowable.just(\"1\", \"3\", \"a\", \"4\", \"5\", \"c\")\n                            .doOnCancel(() -\u003e log.info(\"Subscription canceled\"))\n                            .map(Integer::parseInt) \n                            .onErrorReturn(0);      \nsubscribeWithLog(numbers);\n\n======================\nSubscriber received: 1\nSubscriber received: 3\nSubscription canceled\nSubscriber received: 0\nSubscriber got Completed event\n```\n\nNotice though how **it didn't prevent map() operator from unsubscribing from the Flowable**, but it did \ntrigger the normal **onNext** callback instead of **onError** in the subscriber.\n\n\nLet's introduce a more realcase scenario of a simulated remote request that fails whenever it's invoked\nwith \"red\" and \"black\" color parameters otherwise just add some \\*s.\n\n\n```java\nprivate Observable\u003cString\u003e simulateRemoteOperation(String color) {\n    return Observable.\u003cString\u003ecreate(subscriber -\u003e {\n         if (\"red\".equals(color)) {\n              log.info(\"Emitting RuntimeException for {}\", color);\n              throw new RuntimeException(\"Color red raises exception\");\n         }\n         if (\"black\".equals(color)) {\n              log.info(\"Emitting IllegalArgumentException for {}\", color);\n              throw new IllegalArgumentException(\"Black is not a color\");\n         }\n\n         String value = \"**\" + color + \"**\";\n\n         log.info(\"Emitting {}\", value);\n         subscriber.onNext(value);\n         subscriber.onCompleted();\n    });\n}\n\nFlowable\u003cString\u003e colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -\u003e simulateRemoteOperation(color))\n                .onErrorReturn(throwable -\u003e \"-blank-\");\n                \nsubscribeWithLog(colors);\n\n============\n\n22:15:51 [main] INFO - Emitting **green**\n22:15:51 [main] INFO - Subscriber received: **green**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Emitting RuntimeException for red\n22:15:51 [main] INFO - Subscriber received: -blank-\n22:15:51 [main] INFO - Subscriber got Completed event\n```\nflatMap encounters an error when it subscribes to 'red' substreams and thus still unsubscribe from 'colors' \nstream and the remaining colors are not longer emitted\n\n\n```java\nFlowable\u003cString\u003e colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -\u003e simulateRemoteOperation(color)\n                                    .onErrorReturn(throwable -\u003e \"-blank-\")\n                );\n```\nonErrorReturn() is applied to the flatMap substream and thus translates the exception to a value and so flatMap \ncontinues on with the other colors after red\n\nreturns:\n```\n22:15:51 [main] INFO - Emitting **green**\n22:15:51 [main] INFO - Subscriber received: **green**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Emitting RuntimeException for red\n22:15:51 [main] INFO - Subscriber received: -blank-\n22:15:51 [main] INFO - Emitting **white**\n22:15:51 [main] INFO - Subscriber received: **white**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Subscriber got Completed event\n```\n\n### onErrorResumeNext\nonErrorResumeNext() returns a stream instead of an exception, useful for example to invoke a fallback \nmethod that returns an alternate Stream\n\n```java\nObservable\u003cString\u003e colors = Observable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n     .flatMap(color -\u003e simulateRemoteOperation(color)\n                        .onErrorResumeNext(th -\u003e {\n                            if (th instanceof IllegalArgumentException) {\n                                return Observable.error(new RuntimeException(\"Fatal, wrong arguments\"));\n                            }\n                            return fallbackRemoteOperation();\n                        })\n     );\n\nprivate Observable\u003cString\u003e fallbackRemoteOperation() {\n        return Observable.just(\"blank\");\n}\n```\n\n\n\n## Retrying\n\n### timeout()\nTimeout operator raises exception when there are no events incoming before it's predecessor in the specified time limit.\n\n### retry()\n**retry()** - resubscribes in case of exception to the Observable\n\n```java\nFlowable\u003cString\u003e colors = Flowable.just(\"red\", \"blue\", \"green\", \"yellow\")\n       .concatMap(color -\u003e delayedByLengthEmitter(TimeUnit.SECONDS, color) \n                             //if there are no events flowing in the timeframe   \n                             .timeout(6, TimeUnit.SECONDS)  \n                             .retry(2)\n                             .onErrorResumeNext(Observable.just(\"blank\"))\n       );\n\nsubscribeWithLog(colors.toBlocking());\n```\n\nreturns\n```\n12:40:16 [main] INFO - Received red delaying for 3 \n12:40:19 [main] INFO - Subscriber received: red\n12:40:19 [RxComputationScheduler-2] INFO - Received blue delaying for 4 \n12:40:23 [main] INFO - Subscriber received: blue\n12:40:23 [RxComputationScheduler-4] INFO - Received green delaying for 5 \n12:40:28 [main] INFO - Subscriber received: green\n12:40:28 [RxComputationScheduler-6] INFO - Received yellow delaying for 6 \n12:40:34 [RxComputationScheduler-7] INFO - Received yellow delaying for 6 \n12:40:40 [RxComputationScheduler-1] INFO - Received yellow delaying for 6 \n12:40:46 [main] INFO - Subscriber received: blank\n12:40:46 [main] INFO - Subscriber got Completed event\n```\n\nWhen you want to retry considering the thrown exception type:\n\n```java\nObservable\u003cString\u003e colors = Observable.just(\"blue\", \"red\", \"black\", \"yellow\")\n         .flatMap(colorName -\u003e simulateRemoteOperation(colorName)\n                .retry((retryAttempt, exception) -\u003e {\n                           if (exception instanceof IllegalArgumentException) {\n                               log.error(\"{} encountered non retry exception \", colorName);\n                               return false;\n                           }\n                           log.info(\"Retry attempt {} for {}\", retryAttempt, colorName);\n                           return retryAttempt \u003c= 2;\n                })\n                .onErrorResumeNext(Observable.just(\"generic color\"))\n         );\n```\n\n```\n13:21:37 [main] INFO - Emitting **blue**\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 1 for red\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 2 for red\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 3 for red\n13:21:37 [main] INFO - Emitting IllegalArgumentException for black\n13:21:37 [main] ERROR - black encountered non retry exception \n13:21:37 [main] INFO - Emitting **yellow**\n13:21:37 [main] INFO - Subscriber received: **blue**\n13:21:37 [main] INFO - Subscriber received: generic color\n13:21:37 [main] INFO - Subscriber received: generic color\n13:21:37 [main] INFO - Subscriber received: **yellow**\n13:21:37 [main] INFO - Subscriber got Completed event\n```\n\n### retryWhen\nA more complex retry logic like implementing a backoff strategy in case of exception\nThis can be obtained with **retryWhen**(exceptionObservable -\u003e Observable)\n\nretryWhen resubscribes when an event from an Observable is emitted. It receives as parameter an exception stream\n     \nwe zip the exceptionsStream with a .range() stream to obtain the number of retries,\nhowever we want to wait a little before retrying so in the zip function we return a delayed event - .timer()\n\nThe delay also needs to be subscribed to be effected so we also flatMap\n\n```java\nObservable\u003cString\u003e colors = Observable.just(\"blue\", \"green\", \"red\", \"black\", \"yellow\");\n\ncolors.flatMap(colorName -\u003e \n                   simulateRemoteOperation(colorName)\n                      .retryWhen(exceptionStream -\u003e exceptionStream\n                                    .zipWith(Observable.range(1, 3), (exc, attempts) -\u003e {\n                                        //don't retry for IllegalArgumentException\n                                        if(exc instanceof IllegalArgumentException) {\n                                             return Observable.error(exc);\n                                        }\n\n                                        if(attempts \u003c 3) {\n                                             return Observable.timer(2 * attempts, TimeUnit.SECONDS);\n                                        }\n                                        return Observable.error(exc);\n                                    })\n                                    .flatMap(val -\u003e val)\n                      )\n                      .onErrorResumeNext(Observable.just(\"generic color\")\n                   )\n            );\n```\n\n```\n15:20:23 [main] INFO - Emitting **blue**\n15:20:23 [main] INFO - Emitting **green**\n15:20:23 [main] INFO - Emitting RuntimeException for red\n15:20:23 [main] INFO - Emitting IllegalArgumentException for black\n15:20:23 [main] INFO - Emitting **yellow**\n15:20:23 [main] INFO - Subscriber received: **blue**\n15:20:23 [main] INFO - Subscriber received: **green**\n15:20:23 [main] INFO - Subscriber received: generic color\n15:20:23 [main] INFO - Subscriber received: **yellow**\n15:20:25 [RxComputationScheduler-1] INFO - Emitting RuntimeException for red\n15:20:29 [RxComputationScheduler-2] INFO - Emitting RuntimeException for red\n15:20:29 [main] INFO - Subscriber received: generic color\n15:20:29 [main] INFO - Subscriber got Completed event\n```\n\n**retryWhen vs repeatWhen** \nWith similar names it worth noting the difference.\n \n   - repeat() resubscribes when it receives onCompleted().\n   - retry() resubscribes when it receives onError().\n   \nExample using repeatWhen() to implement periodic polling\n```java\nremoteOperation.repeatWhen(completed -\u003e completed\n                                     .delay(2, TimeUnit.SECONDS))                                                       \n```\n   \n## Backpressure\n\nIt can be the case of a slow consumer that cannot keep up with the producer that is producing too many events\nthat the subscriber cannot process. \n\nBackpressure relates to a feedback mechanism through which the subscriber can signal to the producer how much data \nit can consume and so to produce only that amount.\n\nThe [reactive-streams](https://github.com/reactive-streams/reactive-streams-jvm) section above we saw that besides the \n**onNext, onError** and **onComplete** handlers, the Subscriber\nhas an **onSubscribe(Subscription)**, Subscription through which it can signal upstream it's ready to receive a number \nof items and after it processes the items request another batch.\n\n\n```java\npublic interface Subscriber\u003cT\u003e {\n    //signals to the Publisher to start sending events\n    public void onSubscribe(Subscription s);     \n    \n    public void onNext(T t);\n    public void onError(Throwable t);\n    public void onComplete();\n}\n```\n\nThe methods exposed by **Subscription** through which the subscriber comunicates with the upstream:\n\n```java\npublic interface Subscription {\n    public void request(long n); //request n items\n    public void cancel();\n}\n```\n\nSo in theory the Subscriber can prevent being overloaded by requesting an initial number of items. The Publisher would\nsend those items downstream and not produce any more, until the Subscriber would request more. We say in theory because\nuntil now we did not see a custom **onSubscribe(Subscription)** request being implemented. This is because if not specified explicitly,\nthere is a default implementation which requests of **Long.MAX_VALUE** which basically means \"send all you have\".\n\nNeither did we see the code in the producer that takes consideration of the number of items requested by the subscriber. \n\n```java\nFlowable.create(subscriber -\u003e {\n      log.info(\"Started emitting\");\n\n      for(int i=0; i \u003c 300; i++) {\n           if(subscriber.isCanceled()) {\n              return;\n           }\n           log.info(\"Emitting {}\", i);\n           subscriber.next(i);\n      }\n\n      subscriber.complete();\n}, BackpressureStrategy.BUFFER); //BackpressureStrategy will be explained further bellow\n```\nLooks like it's not possible to slow down production based on request(as there is no reference to the requested items),\nwe can at most stop production if the subscriber canceled subscription. \n\nThis can be done if we extend Flowable so we can pass our custom Subscription type to the downstream subscriber:\n\n```java\nprivate class CustomRangeFlowable extends Flowable\u003cInteger\u003e {\n\n        private int startFrom;\n        private int count;\n\n        CustomRangeFlowable(int startFrom, int count) {\n            this.startFrom = startFrom;\n            this.count = count;\n        }\n\n        @Override\n        public void subscribeActual(Subscriber\u003c? super Integer\u003e subscriber) {\n            subscriber.onSubscribe(new CustomRangeSubscription(startFrom, count, subscriber));\n        }\n\n        class CustomRangeSubscription implements Subscription {\n\n            volatile boolean cancelled;\n            boolean completed = false;\n            \n            private int count;\n            private int currentCount;\n            private int startFrom;\n\n            private Subscriber\u003c? super Integer\u003e actualSubscriber;\n\n            CustomRangeSubscription(int startFrom, int count, Subscriber\u003c? super Integer\u003e actualSubscriber) {\n                this.count = count;\n                this.startFrom = startFrom;\n                this.actualSubscriber = actualSubscriber;\n            }\n\n            @Override\n            public void request(long items) {\n                log.info(\"Downstream requests {} items\", items);\n                for(int i=0; i \u003c items; i++) {\n                    if(cancelled || completed) {\n                        return;\n                    }\n\n                    if(currentCount == count) {\n                        completed = true;\n                        if(cancelled) {\n                            return;\n                        }\n\n                        actualSubscriber.onComplete();\n                        return;\n                    }\n\n                    int emitVal = startFrom + currentCount;\n                    currentCount++;\n                    actualSubscriber.onNext(emitVal);\n                }\n            }\n\n            @Override\n            public void cancel() {\n                cancelled = true;\n            }\n        }\n    }\n```   \nNow lets see how we can custom control how many items we request from upstream, to simulate an initial big request, \nand then a request for other smaller batches of items as soon as the subscriber finishes and is ready for another batch.\n  \n```java\nFlowable\u003cInteger\u003e flowable = new CustomRangeFlowable(5, 10);\n\nflowable.subscribe(new Subscriber\u003cInteger\u003e() {\n\n       private Subscription subscription;\n       private int backlogItems;\n\n       private final int BATCH = 2;\n       private final int INITIAL_REQ = 5;\n\n       @Override\n       public void onSubscribe(Subscription subscription) {\n                this.subscription = subscription;\n                backlogItems = INITIAL_REQ;\n\n                log.info(\"Initial request {}\", backlogItems);\n                subscription.request(backlogItems);\n            }\n\n            @Override\n            public void onNext(Integer val) {\n                log.info(\"Subscriber received {}\", val);\n                backlogItems --;\n\n                if(backlogItems == 0) {\n                    backlogItems = BATCH;\n                    subscription.request(BATCH);\n                }\n            }\n\n            @Override\n            public void onError(Throwable throwable) {\n                log.info(\"Subscriber encountered error\");\n            }\n\n            @Override\n            public void onComplete() {\n                log.info(\"Subscriber completed\");\n            }\n        });\n=====================\nInitial request 5\nDownstream requests 5 items\nSubscriber received 5\nSubscriber received 6\nSubscriber received 7\nSubscriber received 8\nSubscriber received 9\nDownstream requests 2 items\nSubscriber received 10\nSubscriber received 11\nDownstream requests 2 items\nSubscriber received 12\nSubscriber received 13\nDownstream requests 2 items\nSubscriber received 14\nSubscriber completed        \n```  \n\nReturning to the _Flowable.create()_ example since it's not taking any account of the requested \nitems by the subscriber, does it mean it might overwhelm a slow Subscriber? \n\n```java\nprivate Flowable\u003cInteger\u003e createFlowable(int items,\n                     BackpressureStrategy backpressureStrategy) {\n\nreturn Flowable.create(subscriber -\u003e {\n        log.info(\"Started emitting\");\n\n        for (int i = 0; i \u003c items; i++) {\n            if(subscriber.isCancelled()) {\n                 return;\n            }\n                \n            log.info(\"Emitting {}\", i);\n            subscriber.onNext(i);\n        }\n\n        subscriber.onComplete();\n}, backpressureStrategy); //can be BackpressureStrategy.DROP, BUFFER, LATEST,..\n```\nThis is where the 2nd parameter _BackpressureStrategy_ comes in that allows you to specify what to do \nin the case.\n \n   - BackpressureStrategy.BUFFER buffer in memory the events that overflow. Of course is we don't drop over some threshold, it might lead to OufOfMemory. \n   - BackpressureStrategy.DROP just drop the overflowing events\n   - BackpressureStrategy.LATEST keep only recent event and discards previous unconsumed events.\n   - BackpressureStrategy.ERROR we get an error in the subscriber immediately  \n   - BackpressureStrategy.MISSING means we don't care about backpressure(we let one of the downstream operators\n   onBackpressureXXX handle it -explained further down-)\n\n  \nStill what does it mean to 'overwhelm' the subscriber? \nIt means to emit more items than requested by downstream subscriber.\nBut we said that by default the subscriber requests Long.MAX_VALUE since the code \n**flowable.subscribe(onNext(), onError, onComplete)** uses a default **onSubscribe**:\n```\n(subscription) -\u003e subscription.request(Long.MAX_VALUE);\n```\n\nso unless we override it like in our custom Subscriber above, it means it would never overflow. But between the Publisher and the Subscriber you'd have a series of operators. \nWhen we subscribe, a Subscriber travels up through all operators to the original Publisher and some operators override \nthe requested items upstream. One such operator is **observeOn**() which makes it's own request to the upstream Publisher(256 by default),\nbut can take a parameter to specify the request size.\n\n```\nFlowable\u003cInteger\u003e flowable = createFlowable(5, BackpressureStrategy.DROP)\n                .observeOn(Schedulers.io(), false, 3);\nflowable.subscribe((val) -\u003e {\n                               log.info(\"Subscriber received: {}\", val);\n                               Helpers.sleepMillis(millis);\n                           }, logError(), logComplete());\n======\n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[RxCachedThreadScheduler-1] - Subscriber received: 1\n[RxCachedThreadScheduler-1] - Subscriber received: 2\n[RxCachedThreadScheduler-1] - Subscriber got Completed event  \n```\nThis is expected, as the subscription travels upstream through the operators to the source Flowable, while initially\nthe Subscriber requesting Long.MAX_VALUE from the upstream operator **observeOn**, which in turn subscribes to the source and it requests just 3 items from the source instead.\nSince we used **BackpressureStrategy.DROP** all the items emitted outside the expected 3, get discarded and thus never reach our subscriber.\n\nYou may wonder what would have happened if we didn't use **observeOn**. We had to use it if we wanted to be able\nto produce faster than the subscriber(it wasn't just to show a limited request operator), because we'd need a \nseparate thread to produce events faster than the subscriber processes them.   \n\nAlso you can transform an Observable to Flowable by specifying a BackpressureStrategy, otherwise Observables \njust throw exception on overflowing(same as using BackpressureStrategy.DROP in Flowable.create()).\n```\nFlowable flowable = observable.toFlowable(BackpressureStrategy.DROP)\n```\nso can a hot Publisher be converted to a Flowable:\n```\nPublishSubject\u003cInteger\u003e subject = PublishSubject.create();\n\nFlowable\u003cInteger\u003e flowable = subject\n                .toFlowable(BackpressureStrategy.DROP)\n```\n\nThere are also specialized operators to handle backpressure the onBackpressureXXX operators: **onBackpressureBuffer**,\n**onBackpressureDrop**, **onBackpressureLatest**\n\nThese operators request Long.MAX_VALUE(unbounded amount) from upstream and then take it upon themselves to manage the \nrequests from downstream. \nIn the case of _onBackpressureBuffer_ it adds in an internal queue and send downstream the events as requested,\n_onBackpressureDrop_ just discards events that are received from upstream more than requested from downstream, \n_onBackpressureLatest_ also drops emitted events excluding the last emitted event(most recent).  \n\n```java\nFlowable\u003cInteger\u003e flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -\u003e log.info(\"Buffer has overflown\"));\n\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\nsubscribeWithSlowSubscriber(flowable);                \n\n=====                \n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[main] - Emitting 5\n[main] - Emitting 6\n[main] - Emitting 7\n[main] - Emitting 8\n[main] - Emitting 9\n[main] - Buffer has overflown\n[RxCachedThreadScheduler-1] ERROR - Subscriber received error 'Buffer is full'                \n```\n\nWe create the Flowable with _BackpressureStrategy.MISSING_ saying we don't care about backpressure\nbut let one of the onBackpressureXXX operators handle it.\nNotice however \n\n\n\nChaining together multiple onBackpressureXXX operators doesn't actually make sense\nUsing something like\n\n```java\nFlowable\u003cInteger\u003e flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                 .onBackpressureBuffer(5)\n                 .onBackpressureDrop((val) -\u003e log.info(\"Dropping {}\", val))\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n                 \nsubscribeWithSlowSubscriber(flowable);\n```\n\nis not behaving as probably you'd expected - buffer 5 values, and then dropping overflowing events-.\nBecause _onBackpressureDrop_ subscribes to the previous _onBackpressureBuffer_ operator\nsignaling it's requesting **Long.MAX_VALUE**(unbounded amount) from it. \nThus **onBackpressureBuffer** will never feel its subscriber is overwhelmed and never \"trigger\", meaning that the last \nonBackpressureXXX operator overrides the previous one if they are chained.\n\nOf course for implementing an event dropping strategy after a full buffer, there is the special overrided\nversion of **onBackpressureBuffer** that takes a **BackpressureOverflowStrategy**.\n\n```java\nFlowable\u003cInteger\u003e flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -\u003e log.info(\"Buffer has overflown\"),\n                                            BackpressureOverflowStrategy.DROP_OLDEST);\n\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\nsubscribeWithSlowSubscriber(flowable);\n\n===============\n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[main] - Emitting 5\n[main] - Emitting 6\n[main] - Emitting 7\n[main] - Emitting 8\n[main] - Buffer has overflown\n[main] - Emitting 9\n[main] - Buffer has overflown\n[RxCachedThreadScheduler-1] - Subscriber received: 1\n[RxCachedThreadScheduler-1] - Subscriber received: 2\n[RxCachedThreadScheduler-1] - Subscriber received: 5\n[RxCachedThreadScheduler-1] - Subscriber received: 6\n[RxCachedThreadScheduler-1] - Subscriber received: 7\n[RxCachedThreadScheduler-1] - Subscriber received: 8\n[RxCachedThreadScheduler-1] - Subscriber received: 9\n[RxCachedThreadScheduler-1] - Subscriber got Completed event\n```\n\nonBackpressureXXX operators can be added whenever necessary and it's not limited to cold publishers and we can use them \non hot publishers also.\n\n## Articles and books for further reading\n[Reactive Programming with RxJava](http://shop.oreilly.com/product/0636920042228.do)\n\n  \n","funding_links":[],"categories":["\u003ca name=\"Java\"\u003e\u003c/a\u003eJava"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalamaci%2Frxjava-walkthrough","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbalamaci%2Frxjava-walkthrough","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalamaci%2Frxjava-walkthrough/lists"}