After explaining what problem Reactive Programming solves I will give an introduction to one implementation: RxJava. I show how to compose Observable without concurrency first and then with Scheduler. I finish the talk by showing examples of flow control and draw backs.
Inspired from https://www.infoq.com/presentations/rxjava-reactor and https://www.infoq.com/presentations/rx-service-architecture
Code: https://github.com/toff63/Sandbox/tree/master/java/rsjug-rx/rsjug-rx/src/main/java/rs/jug/rx
44. Cold Stream vs Hot Stream
Hot Stream Cold Stream
no control on emission rate emits when requested
UI events, Metric events,
System events
DB query, Service request,
Downloading file
45. Cold Stream vs Hot Stream
Hot Stream Cold Stream
no control on emission rate emits when requested
UI events, Metric events,
System events
DB query, Service request,
Downloading file
Flow control Flow control & Back pressure
72. ● Observable API is complex
● Takes time to become fluent with Observable
● Hard to test !
● Debugging is harder as everything is asynchronous
● Stacktraces can be truncated due to scheduler
Drawbacks
73. Stacktrace example
18:42:59.487 [rx-request-processor-5-67] ERROR
n.k.t.util.HttpContentInputStream - Error on server
io.netty.util.IllegalReferenceCountException: refCnt: 0
at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1178) ~[netty-buffer-4.0.27.Final.jar:4.0.27.Final]
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:848) ~[netty-buffer-4.0.27.Final.jar:4.0.27.Final]
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:841) ~[netty-buffer-4.0.27.Final.jar:4.0.27.Final]
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:831) ~[netty-buffer-4.0.27.Final.jar:4.0.27.Final]
at netflix.karyon.transport.util.HttpContentInputStream$1.onNext(HttpContentInputStream.java:67) [karyon2-governator-2.3.0.jar:2.3.0]
at netflix.karyon.transport.util.HttpContentInputStream$1.onNext(HttpContentInputStream.java:33) [karyon2-governator-2.3.0.jar:2.3.0]
at rx.Observable$33.onNext(Observable.java:7480) [rxjava-1.0.10.jar:1.0.10]
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:130) [rxjava-1.0.10.jar:1.0.10]
at io.reactivex.netty.protocol.http.UnicastContentSubject$AutoReleaseByteBufOperator$1.onNext(UnicastContentSubject.java:262) [rxnetty-0.4.9.jar:0.4.9]
at rx.internal.operators.NotificationLite.accept(NotificationLite.java:150) [rxjava-1.0.10.jar:1.0.10]
at rx.internal.operators.BufferUntilSubscriber.emit(BufferUntilSubscriber.java:151) [rxjava-1.0.10.jar:1.0.10]
at rx.internal.operators.BufferUntilSubscriber.onNext(BufferUntilSubscriber.java:184) [rxjava-1.0.10.jar:1.0.10]
at io.reactivex.netty.protocol.http.UnicastContentSubject.onNext(UnicastContentSubject.java:286) [rxnetty-0.4.9.jar:0.4.9]
at io.reactivex.netty.protocol.http.server.ServerRequestResponseConverter.invokeContentOnNext(ServerRequestResponseConverter.java:193)
[rxnetty-0.4.9.jar:0.4.9]
at io.reactivex.netty.protocol.http.server.ServerRequestResponseConverter.channelRead(ServerRequestResponseConverter.java:129) [rxnetty-0.4.9.jar:0.4.9]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:339) [netty-transport-4.0.27.Final.jar:4.0.27.Final]
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:32) [netty-transport-4.0.27.Final.jar:4.0.27.Final]
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:329) [netty-transport-4.0.27.Final.jar:4.0.27.Final]
at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:36) [netty-common-4.0.27.Final.jar:4.0.27.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111) [netty-common-4.0.27.Final.jar:4.0.27.Final]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-common-4.0.27.Final.jar:4.0.27.Final]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73]