SlideShare a Scribd company logo
1 of 35
Download to read offline
mindloops
RXJAVA: FROM THE TRENCHES
PETER HENDRIKS
@PETERHENDRIKS80
PETER@MINDLOOPS.NL
Agenda
• Intro
• Why we want RxJava
• RxJava in Practice
• Future / conclusion
What is ReactiveX?
“A library for composing asynchronous
and event-based programs by using observable
sequences” - Erik Meijer
What is RxJava?
• Port of ReactiveX C# framework to Java
• Open source, lead by Netflix
• 1.0.0 release november 2014, 2.0.0 last week :)
• ReactiveX is currently available in 14 programming languages
RxJava Survival Guide
// In your own code, convert results in a fluent way...

Observable<String> descriptionObservable = eventObservable.map(event -> event.getDescription());
// e.g. Database, services, keyboard, messaging etc.

MyEventProducer eventProducer = new MyEventProducer();
// use some custom adapter code to adapt to an RxJava "Observable"

Observable<MyEvent> eventObservable = eventProducer.toObservable();
// ... And compose with other Observables

Observable<Success> storeObservable = eventObservable.flatMap(event -> storeEvent(event));



private Observable<Success> storeEvent(MyEvent event) {

// stores the event asynchronously...

}
// Start flowing by subscribing and do something with final results
storeObservable.subscribe(myEvent -> {/* do something */}, error -> LOG.error("Oops", error));
Case: Sanoma Learning
• Web e-learning platform
• Many users
• Co-development: multiple
agile product teams
Case: Sanoma Learning
• AngularJS, Java 8, Vert.x,
MongoDB, AWS S3, Redis
• Suite of micro-services







Microservices met Vert.x
- Tim van Eindhoven, Zaal 4, 11:30
Why RxJava
WHY RXJAVA
Why we want RxJava
• Avoid “callback hell”
• Out of the box support
• Streaming performance benefits
Simplicity of the POJAM
• A simple, blocking Plain Old JAva Method
• Predictable execution flow
• Fully built-in result and error handling
• Easy to compose
public List<QuestionView> listQuestions(String studentId, String segmentId) {

List<Question> questions = contentService.findBySegmentId(segmentId);



List<QuestionView> result = new ArrayList<>();

for(Question question : questions) {

Progress progress = progressService.findByQuestionId(studentId, question.getId());

result.add(new QuestionView(question, progress));

}

return result;

}
Vert.x callback example
MessageConsumer<String> consumer = eventBus.consumer("news.uk.sport");

consumer.handler(message -> {

try {

System.out.println("I have received a message: " + message.body());

message.reply("how interesting!");

} catch (Exception e) {

message.fail(500, e.getMessage());

}

});



sendNewsMessage("Yay! Someone kicked a ball across a patch of grass", ar -> {

if (ar.succeeded()) {

System.out.println("Received reply: " + ar.result().body());

} else {

ar.cause().printStackTrace();

}

});
private void sendNewsMessage(String message, Handler<AsyncResult<Message<Object>>> replyHandler) {

eventBus.send("news.uk.sport", message, replyHandler);

}
Callback hell
void listQuestions(String studentId, String segmentId, Handler<AsyncResult<List<QuestionView>>> resultHandler) {

findBySegmentId(segmentId, ar -> {

if (ar.succeeded()) {

List<QuestionView> result = new ArrayList<>();

List<Question> questions = ar.result().body();

for(Question question : questions) {

findByQuestionId(studentId, question.getId(), progressAr -> {

if (ar.succeeded()) {

Progress progress = progressAr.result().body();

result.add(new QuestionView(question, progress));

questions.remove(question);

if (questions.isEmpty()) {

resultHandler.handle(Future.<List<QuestionView>>succeededFuture(result));

}

} else {

resultHandler.handle(Future.<List<QuestionView>>failedFuture(ar.cause()));

}

});

}

} else {

resultHandler.handle(Future.<List<QuestionView>>failedFuture(progressAr.cause()));

}

} );

}



private void findBySegmentId(String segmentId, Handler<AsyncResult<Message<List<Question>>>> handler) {}



private void findByQuestionId(String studentId, String questionId, Handler<AsyncResult<Message<Progress>>> handler) {}
Solution: RxJava as “Promise API”
public Observable<QuestionView> listQuestions(String studentId, String segmentId) {

return contentService.findBySegmentId(segmentId)

.concatMap(question -> progressService.findByQuestionId(studentId, question.getId())

.map(progress -> new QuestionView(question, progress)));

}
RxJava: one Promise API to rule them all
• We want to use one promise API
everywhere to fix callback hell
• RxJava is directly supported in Vert.x and
the MongoDB Java driver
Typical request processing overhead
Thread
Request
Response (List)
Domain data
(List)
public List<QuestionView> listQuestions(String studentId, String segmentId) {

List<Question> questions = contentService.findBySegmentId(segmentId);



List<Question> result = new ArrayList<>();

for(Question question : questions) {

Progress progress =
progressService.findByQuestionId(studentId, question.getId());

result.add(new QuestionView(question, progress));

}

return result;

}
Streaming == less intermediate data needed
public Observable<QuestionView> listQuestions(String studentId, String
segmentId) {

return contentService.findBySegmentId(segmentId)

.flatMap(question ->
progressService.findByQuestionId(studentId, question.getId())

.map(progress -> new QuestionView(question, progress)));

}
Thread
Request
Response (List)
Domain data
(element)
RXJAVA IN PRACTICE
Expect a learning curve
“Simple” promises vs RxJava
CompletableFuture Observable
What emits 1 event or 1 error emit 0 or more events and/or 1 error
When
Immediately scheduled for
execution
already executing, or only after
subscription
Where
Event can be read at any time
after completion
Event is available once
Learn to stream first!
• RxJava will force you to do it
• It helps to be comfortable with Java 8 Stream API first
• Java 8 Stream API still very useful for POJAM code
public Observable<QuestionView> listQuestions(String studentId, String segmentId) {

return contentService.findBySegmentId(segmentId)

.flatMap(question -> progressService.findByQuestionId(studentId, question.getId())

.map(progress -> new QuestionView(question, progress)));

}
Hot vs Cold Observables
// HOT

MyEventProducer eventProducer = new MyEventProducer();

// some other code...

Observable<MyEvent> hotObservable = Observable.create(subscriber -> {

// Listen to producer here.

});

hotObservable.subscribe(myEvent -> {/* do something with event */});
// COLD

Observable<MyEvent> coldObservable = Observable.create(subscriber -> {

MyEventProducer eventProducer = new MyEventProducer();

// Listen to producer here.

});

// some other code...

coldObservable.subscribe(myEvent -> {/* do something with event */});
Examples of hot and cold
// HOT example

HttpServer server = vertx.createHttpServer();

Observable<HttpServerRequest> requests = server.requestStream().toObservable();

// some other code

requests.subscribe(request -> System.out.println(request.absoluteURI()));
//COLD example

MongoClient mongoClient = MongoClients.create();

MongoCollection<Document> questionCollection =
mongoClient.getDatabase("contents").getCollection("questions");

Observable<Document> allQuestions = questionCollection.find().toObservable();

// some other code

allQuestions.subscribe(question -> System.out.println(question));
Always end with subscribe somewhere
// wrong way to check value
@Test

public void storeAnswerStoresAnswer() {

Observable<QuestionView> questionView = answerController.storeAnswer("1", "test");



questionView.map(view -> assertThat(view, is(testView)));

}
// use test subscriber to test observables in isolation
@Test

public void storeAnswerStoresAnswer() {

Observable<QuestionView> questionView = answerController.storeAnswer("1", "test");



TestSubscriber<QuestionView> ts = new TestSubscriber<>();

questionView.subscribe(ts);

ts.awaitTerminalEvent();

ts.assertNoErrors();

ts.assertValue(testValue);

}
0 or more events dilemma
// POJAM

public QuestionView storeAnswer(String questionId, String textValue) {

Question question = contentService.findByQuestionId(questionId);

if (question == null) {

throw new IllegalStateException("question not found");

}

Answer answer = validateAnswer(question, textValue);

progressService.store(questionId, answer);

return new QuestionView(question, answer);

}
// RxJava wrong

public Observable<QuestionView> storeAnswer(String questionId, String textValue) {

return contentService.findByQuestionId(questionId)

.flatMap(question -> {

Answer answer = validateAnswer(question, textValue);

return progressService.store(questionId, answer)

.map(x -> new QuestionView(question, answer));

});

}
// RxJava with switch

public Observable<QuestionView> storeAnswer(String questionId, String textValue) {

return contentService.findByQuestionId(questionId)

.switchIfEmpty(Observable.defer(() ->

Observable.error(new IllegalStateException("question not found"))))

.flatMap(question -> {

Answer answer = validateAnswer(question, textValue);

return progressService.store(questionId, answer)

.map(x -> new QuestionView(question, answer));

});

}
Mapping “always empty” results
public Observable<Void> storeResult(String answer) {

System.out.println("Do some async operation without result.");

return Observable.empty();

}



public Observable<String> processRequest(String answer) {

// This does not work right

return storeResult(answer)

.map(x -> "success!");

}
public interface MongoCollection<TDocument> {

/**

* @return an Observable with a single element indicating when the operation has completed
or with either a com.mongodb.DuplicateKeyException or com.mongodb.MongoException

*/

Observable<Success> insertOne(TDocument document);

}

// Return non-null event to be compatible with RxJava 2.x

public enum Success {

SUCCESS

}
Will change in RxJava 2.x
Better distinction between 0, 1,
optional and multiple results
Make it easy to do the right thing
Only use RxJava when needed
• POJAM code still the best for a lot of your code
• Use RxJava only for async composition/streaming
public boolean isAnswerCorrect(Question question, String answer) {

// some complicated synchronised checking logic here

return true;

}



public Observable<String> processRequest(String questionId, String answer) {

return contentService.findByQuestionId(questionId)

.map(question -> isAnswerCorrect(question, answer))

.map(result -> result ? "Good job!" : "Better luck next time!");

}
Separate subscribe code
• Separate and reuse subscribe code from observable chains
// BAD: subscription mixed with observable code

public void processRequest(HttpServerRequest request, String questionId, String answer) {

contentService.findByQuestionId(questionId)

.map(question -> isAnswerCorrect(question, answer))

.map(result -> result ? "Good job!" : "Better luck next time!")

.subscribe(result -> request.response().end(result));

}
// GOOD: simple observable code, easy to test and cannot forget to subscribe

public Observable<String> processRequest(String questionId, String answer) {

return contentService.findByQuestionId(questionId)

.map(question -> isAnswerCorrect(question, answer))

.map(result -> result ? "Good job!" : "Better luck next time!");

}
Async code and crappy stack traces
public static void main(String[] args) {

Observable.empty()

.observeOn(Schedulers.io())

.toBlocking()

.first();

}
Exception in thread "main" java.util.NoSuchElementException: Sequence contains no elements

at rx.internal.operators.OperatorSingle$ParentSubscriber.onCompleted(OperatorSingle.java:131)

at rx.internal.operators.OperatorTake$1.onCompleted(OperatorTake.java:53)

at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:195)

at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$1.call(OperatorObserveOn.java:162)

at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(<…>.java:180)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(<…>.java:293)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)
Band-aid: add context to logging/exceptions
// generic wrapping code

public void processRequest(HttpServerRequest request,

Function<HttpServerRequest, Observable<String>> processor) {

Observable<String> observable = processor.apply(request);

observable.subscribe(

result -> processResult(request, result),

error -> processError(request, error));

}



private void processError(HttpServerRequest request, Throwable error) {

LOG.error("An error occurred processing: " + request.uri(), error);

request.response().setStatusCode(500).setStatusMessage(error.getMessage()).end();

}
FUTURE OF RXJAVA
The Future of RxJava looks promising
• Increased adoption for “Reactive Streams”
• RxJava 2 solves some API weirdness and simplifies simple event handling
• Strong adoption in Android and JavaScript
• Spring 5 goes big on reactive, including RxJava support
Spring example
@RestController

public class RxJavaController {

private final RxJavaService aService;

@Autowired

public RxJavaController(RxJavaService aService) {

this.aService = aService;

}

@RequestMapping(path = "/handleMessageRxJava", method = RequestMethod.POST)

public Observable<MessageAcknowledgement> handleMessage(@RequestBody Message message) {

System.out.println("Got Message..");

return this.aService.handleMessage(message);

}

}
RxJava 2.x
Reactive Streams
(Backpressure)
No Backpressure
0..n items,
complete, error
Flowable Observable
0..1 item, complete,
error
Maybe
1 item, error Single
complete, error Completable
CONCLUSION
RxJava in practice
- Learning to stream
- Hot vs Cold observables
- Always subscribe
- 0 or more events dilemma
- Dealing with always empty results Make it easy
- Still use POJAM code
- Separate subscribe code
- Make up for stack trace
Why we want RxJava
- Avoid Callback Hell
- Streaming helps performance
- Out of the box support
PETER HENDRIKS
@PETERHENDRIKS80
PETER@MINDLOOPS.NL

More Related Content

What's hot

Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for AndroidTomáš Kypta
 
Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaFabio Collini
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaRick Warren
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxAndrzej Sitek
 
Intro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich AndroidIntro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich AndroidEgor Andreevich
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentationGene Chang
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015Constantine Mars
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kros Huang
 
Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaPratama Nur Wijaya
 
How to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingHow to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingIndicThreads
 
Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroidSavvycom Savvycom
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaKasun Indrasiri
 
Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in JavaYakov Fain
 

What's hot (20)

Practical RxJava for Android
Practical RxJava for AndroidPractical RxJava for Android
Practical RxJava for Android
 
Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJava
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 
Rx java in action
Rx java in actionRx java in action
Rx java in action
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to Rx
 
AWS Java SDK @ scale
AWS Java SDK @ scaleAWS Java SDK @ scale
AWS Java SDK @ scale
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
Forgive me for i have allocated
Forgive me for i have allocatedForgive me for i have allocated
Forgive me for i have allocated
 
Intro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich AndroidIntro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich Android
 
RxJava Applied
RxJava AppliedRxJava Applied
RxJava Applied
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
 
RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015RxJava for Android - GDG DevFest Ukraine 2015
RxJava for Android - GDG DevFest Ukraine 2015
 
Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
 
Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta Indonesia
 
How to Think in RxJava Before Reacting
How to Think in RxJava Before ReactingHow to Think in RxJava Before Reacting
How to Think in RxJava Before Reacting
 
Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroid
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
Reactive Thinking in Java
Reactive Thinking in JavaReactive Thinking in Java
Reactive Thinking in Java
 

Similar to RxJava from the trenches

Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekPaco van Beckhoven
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
 
Ajax Under The Hood
Ajax Under The HoodAjax Under The Hood
Ajax Under The HoodWO Community
 
Improve unit tests with Mutants!
Improve unit tests with Mutants!Improve unit tests with Mutants!
Improve unit tests with Mutants!Paco van Beckhoven
 
Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTruls Jørgensen
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB
 
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMEREVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMERAndrey Karpov
 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09Daniel Bryant
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterKaty Slemon
 
Introduction to Software Testing
Introduction to Software TestingIntroduction to Software Testing
Introduction to Software TestingSergio Arroyo
 
Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4jeresig
 

Similar to RxJava from the trenches (20)

Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech Week
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Ajax Under The Hood
Ajax Under The HoodAjax Under The Hood
Ajax Under The Hood
 
Improve unit tests with Mutants!
Improve unit tests with Mutants!Improve unit tests with Mutants!
Improve unit tests with Mutants!
 
Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinner
 
Javascript quiz
Javascript quizJavascript quiz
Javascript quiz
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Design for Testability
Design for TestabilityDesign for Testability
Design for Testability
 
Jason parsing
Jason parsingJason parsing
Jason parsing
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
 
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMEREVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
EVERYTHING ABOUT STATIC CODE ANALYSIS FOR A JAVA PROGRAMMER
 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
 
Struts2 - 101
Struts2 - 101Struts2 - 101
Struts2 - 101
 
Introduction to Software Testing
Introduction to Software TestingIntroduction to Software Testing
Introduction to Software Testing
 
Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4
 
D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 
D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 

Recently uploaded

WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...masabamasaba
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 

Recently uploaded (20)

WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 

RxJava from the trenches

  • 1. mindloops RXJAVA: FROM THE TRENCHES PETER HENDRIKS @PETERHENDRIKS80 PETER@MINDLOOPS.NL
  • 2. Agenda • Intro • Why we want RxJava • RxJava in Practice • Future / conclusion
  • 3. What is ReactiveX? “A library for composing asynchronous and event-based programs by using observable sequences” - Erik Meijer
  • 4. What is RxJava? • Port of ReactiveX C# framework to Java • Open source, lead by Netflix • 1.0.0 release november 2014, 2.0.0 last week :) • ReactiveX is currently available in 14 programming languages
  • 5. RxJava Survival Guide // In your own code, convert results in a fluent way...
 Observable<String> descriptionObservable = eventObservable.map(event -> event.getDescription()); // e.g. Database, services, keyboard, messaging etc.
 MyEventProducer eventProducer = new MyEventProducer(); // use some custom adapter code to adapt to an RxJava "Observable"
 Observable<MyEvent> eventObservable = eventProducer.toObservable(); // ... And compose with other Observables
 Observable<Success> storeObservable = eventObservable.flatMap(event -> storeEvent(event));
 
 private Observable<Success> storeEvent(MyEvent event) {
 // stores the event asynchronously...
 } // Start flowing by subscribing and do something with final results storeObservable.subscribe(myEvent -> {/* do something */}, error -> LOG.error("Oops", error));
  • 6. Case: Sanoma Learning • Web e-learning platform • Many users • Co-development: multiple agile product teams
  • 7. Case: Sanoma Learning • AngularJS, Java 8, Vert.x, MongoDB, AWS S3, Redis • Suite of micro-services
 
 
 
 Microservices met Vert.x - Tim van Eindhoven, Zaal 4, 11:30
  • 9. Why we want RxJava • Avoid “callback hell” • Out of the box support • Streaming performance benefits
  • 10. Simplicity of the POJAM • A simple, blocking Plain Old JAva Method • Predictable execution flow • Fully built-in result and error handling • Easy to compose public List<QuestionView> listQuestions(String studentId, String segmentId) {
 List<Question> questions = contentService.findBySegmentId(segmentId);
 
 List<QuestionView> result = new ArrayList<>();
 for(Question question : questions) {
 Progress progress = progressService.findByQuestionId(studentId, question.getId());
 result.add(new QuestionView(question, progress));
 }
 return result;
 }
  • 11. Vert.x callback example MessageConsumer<String> consumer = eventBus.consumer("news.uk.sport");
 consumer.handler(message -> {
 try {
 System.out.println("I have received a message: " + message.body());
 message.reply("how interesting!");
 } catch (Exception e) {
 message.fail(500, e.getMessage());
 }
 });
 
 sendNewsMessage("Yay! Someone kicked a ball across a patch of grass", ar -> {
 if (ar.succeeded()) {
 System.out.println("Received reply: " + ar.result().body());
 } else {
 ar.cause().printStackTrace();
 }
 }); private void sendNewsMessage(String message, Handler<AsyncResult<Message<Object>>> replyHandler) {
 eventBus.send("news.uk.sport", message, replyHandler);
 }
  • 12. Callback hell void listQuestions(String studentId, String segmentId, Handler<AsyncResult<List<QuestionView>>> resultHandler) {
 findBySegmentId(segmentId, ar -> {
 if (ar.succeeded()) {
 List<QuestionView> result = new ArrayList<>();
 List<Question> questions = ar.result().body();
 for(Question question : questions) {
 findByQuestionId(studentId, question.getId(), progressAr -> {
 if (ar.succeeded()) {
 Progress progress = progressAr.result().body();
 result.add(new QuestionView(question, progress));
 questions.remove(question);
 if (questions.isEmpty()) {
 resultHandler.handle(Future.<List<QuestionView>>succeededFuture(result));
 }
 } else {
 resultHandler.handle(Future.<List<QuestionView>>failedFuture(ar.cause()));
 }
 });
 }
 } else {
 resultHandler.handle(Future.<List<QuestionView>>failedFuture(progressAr.cause()));
 }
 } );
 }
 
 private void findBySegmentId(String segmentId, Handler<AsyncResult<Message<List<Question>>>> handler) {}
 
 private void findByQuestionId(String studentId, String questionId, Handler<AsyncResult<Message<Progress>>> handler) {}
  • 13. Solution: RxJava as “Promise API” public Observable<QuestionView> listQuestions(String studentId, String segmentId) {
 return contentService.findBySegmentId(segmentId)
 .concatMap(question -> progressService.findByQuestionId(studentId, question.getId())
 .map(progress -> new QuestionView(question, progress)));
 }
  • 14. RxJava: one Promise API to rule them all • We want to use one promise API everywhere to fix callback hell • RxJava is directly supported in Vert.x and the MongoDB Java driver
  • 15. Typical request processing overhead Thread Request Response (List) Domain data (List) public List<QuestionView> listQuestions(String studentId, String segmentId) {
 List<Question> questions = contentService.findBySegmentId(segmentId);
 
 List<Question> result = new ArrayList<>();
 for(Question question : questions) {
 Progress progress = progressService.findByQuestionId(studentId, question.getId());
 result.add(new QuestionView(question, progress));
 }
 return result;
 }
  • 16. Streaming == less intermediate data needed public Observable<QuestionView> listQuestions(String studentId, String segmentId) {
 return contentService.findBySegmentId(segmentId)
 .flatMap(question -> progressService.findByQuestionId(studentId, question.getId())
 .map(progress -> new QuestionView(question, progress)));
 } Thread Request Response (List) Domain data (element)
  • 19. “Simple” promises vs RxJava CompletableFuture Observable What emits 1 event or 1 error emit 0 or more events and/or 1 error When Immediately scheduled for execution already executing, or only after subscription Where Event can be read at any time after completion Event is available once
  • 20. Learn to stream first! • RxJava will force you to do it • It helps to be comfortable with Java 8 Stream API first • Java 8 Stream API still very useful for POJAM code public Observable<QuestionView> listQuestions(String studentId, String segmentId) {
 return contentService.findBySegmentId(segmentId)
 .flatMap(question -> progressService.findByQuestionId(studentId, question.getId())
 .map(progress -> new QuestionView(question, progress)));
 }
  • 21. Hot vs Cold Observables // HOT
 MyEventProducer eventProducer = new MyEventProducer();
 // some other code...
 Observable<MyEvent> hotObservable = Observable.create(subscriber -> {
 // Listen to producer here.
 });
 hotObservable.subscribe(myEvent -> {/* do something with event */}); // COLD
 Observable<MyEvent> coldObservable = Observable.create(subscriber -> {
 MyEventProducer eventProducer = new MyEventProducer();
 // Listen to producer here.
 });
 // some other code...
 coldObservable.subscribe(myEvent -> {/* do something with event */});
  • 22. Examples of hot and cold // HOT example
 HttpServer server = vertx.createHttpServer();
 Observable<HttpServerRequest> requests = server.requestStream().toObservable();
 // some other code
 requests.subscribe(request -> System.out.println(request.absoluteURI())); //COLD example
 MongoClient mongoClient = MongoClients.create();
 MongoCollection<Document> questionCollection = mongoClient.getDatabase("contents").getCollection("questions");
 Observable<Document> allQuestions = questionCollection.find().toObservable();
 // some other code
 allQuestions.subscribe(question -> System.out.println(question));
  • 23. Always end with subscribe somewhere // wrong way to check value @Test
 public void storeAnswerStoresAnswer() {
 Observable<QuestionView> questionView = answerController.storeAnswer("1", "test");
 
 questionView.map(view -> assertThat(view, is(testView)));
 } // use test subscriber to test observables in isolation @Test
 public void storeAnswerStoresAnswer() {
 Observable<QuestionView> questionView = answerController.storeAnswer("1", "test");
 
 TestSubscriber<QuestionView> ts = new TestSubscriber<>();
 questionView.subscribe(ts);
 ts.awaitTerminalEvent();
 ts.assertNoErrors();
 ts.assertValue(testValue);
 }
  • 24. 0 or more events dilemma // POJAM
 public QuestionView storeAnswer(String questionId, String textValue) {
 Question question = contentService.findByQuestionId(questionId);
 if (question == null) {
 throw new IllegalStateException("question not found");
 }
 Answer answer = validateAnswer(question, textValue);
 progressService.store(questionId, answer);
 return new QuestionView(question, answer);
 } // RxJava wrong
 public Observable<QuestionView> storeAnswer(String questionId, String textValue) {
 return contentService.findByQuestionId(questionId)
 .flatMap(question -> {
 Answer answer = validateAnswer(question, textValue);
 return progressService.store(questionId, answer)
 .map(x -> new QuestionView(question, answer));
 });
 } // RxJava with switch
 public Observable<QuestionView> storeAnswer(String questionId, String textValue) {
 return contentService.findByQuestionId(questionId)
 .switchIfEmpty(Observable.defer(() ->
 Observable.error(new IllegalStateException("question not found"))))
 .flatMap(question -> {
 Answer answer = validateAnswer(question, textValue);
 return progressService.store(questionId, answer)
 .map(x -> new QuestionView(question, answer));
 });
 }
  • 25. Mapping “always empty” results public Observable<Void> storeResult(String answer) {
 System.out.println("Do some async operation without result.");
 return Observable.empty();
 }
 
 public Observable<String> processRequest(String answer) {
 // This does not work right
 return storeResult(answer)
 .map(x -> "success!");
 } public interface MongoCollection<TDocument> {
 /**
 * @return an Observable with a single element indicating when the operation has completed or with either a com.mongodb.DuplicateKeyException or com.mongodb.MongoException
 */
 Observable<Success> insertOne(TDocument document);
 }
 // Return non-null event to be compatible with RxJava 2.x
 public enum Success {
 SUCCESS
 } Will change in RxJava 2.x Better distinction between 0, 1, optional and multiple results
  • 26. Make it easy to do the right thing
  • 27. Only use RxJava when needed • POJAM code still the best for a lot of your code • Use RxJava only for async composition/streaming public boolean isAnswerCorrect(Question question, String answer) {
 // some complicated synchronised checking logic here
 return true;
 }
 
 public Observable<String> processRequest(String questionId, String answer) {
 return contentService.findByQuestionId(questionId)
 .map(question -> isAnswerCorrect(question, answer))
 .map(result -> result ? "Good job!" : "Better luck next time!");
 }
  • 28. Separate subscribe code • Separate and reuse subscribe code from observable chains // BAD: subscription mixed with observable code
 public void processRequest(HttpServerRequest request, String questionId, String answer) {
 contentService.findByQuestionId(questionId)
 .map(question -> isAnswerCorrect(question, answer))
 .map(result -> result ? "Good job!" : "Better luck next time!")
 .subscribe(result -> request.response().end(result));
 } // GOOD: simple observable code, easy to test and cannot forget to subscribe
 public Observable<String> processRequest(String questionId, String answer) {
 return contentService.findByQuestionId(questionId)
 .map(question -> isAnswerCorrect(question, answer))
 .map(result -> result ? "Good job!" : "Better luck next time!");
 }
  • 29. Async code and crappy stack traces public static void main(String[] args) {
 Observable.empty()
 .observeOn(Schedulers.io())
 .toBlocking()
 .first();
 } Exception in thread "main" java.util.NoSuchElementException: Sequence contains no elements
 at rx.internal.operators.OperatorSingle$ParentSubscriber.onCompleted(OperatorSingle.java:131)
 at rx.internal.operators.OperatorTake$1.onCompleted(OperatorTake.java:53)
 at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:195)
 at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$1.call(OperatorObserveOn.java:162)
 at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
 at java.util.concurrent.FutureTask.run(FutureTask.java:266)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(<…>.java:180)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(<…>.java:293)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 at java.lang.Thread.run(Thread.java:745)
  • 30. Band-aid: add context to logging/exceptions // generic wrapping code
 public void processRequest(HttpServerRequest request,
 Function<HttpServerRequest, Observable<String>> processor) {
 Observable<String> observable = processor.apply(request);
 observable.subscribe(
 result -> processResult(request, result),
 error -> processError(request, error));
 }
 
 private void processError(HttpServerRequest request, Throwable error) {
 LOG.error("An error occurred processing: " + request.uri(), error);
 request.response().setStatusCode(500).setStatusMessage(error.getMessage()).end();
 }
  • 32. The Future of RxJava looks promising • Increased adoption for “Reactive Streams” • RxJava 2 solves some API weirdness and simplifies simple event handling • Strong adoption in Android and JavaScript • Spring 5 goes big on reactive, including RxJava support
  • 33. Spring example @RestController
 public class RxJavaController {
 private final RxJavaService aService;
 @Autowired
 public RxJavaController(RxJavaService aService) {
 this.aService = aService;
 }
 @RequestMapping(path = "/handleMessageRxJava", method = RequestMethod.POST)
 public Observable<MessageAcknowledgement> handleMessage(@RequestBody Message message) {
 System.out.println("Got Message..");
 return this.aService.handleMessage(message);
 }
 }
  • 34. RxJava 2.x Reactive Streams (Backpressure) No Backpressure 0..n items, complete, error Flowable Observable 0..1 item, complete, error Maybe 1 item, error Single complete, error Completable
  • 35. CONCLUSION RxJava in practice - Learning to stream - Hot vs Cold observables - Always subscribe - 0 or more events dilemma - Dealing with always empty results Make it easy - Still use POJAM code - Separate subscribe code - Make up for stack trace Why we want RxJava - Avoid Callback Hell - Streaming helps performance - Out of the box support PETER HENDRIKS @PETERHENDRIKS80 PETER@MINDLOOPS.NL