30
Going Reactive with Java 8 Ryan Knight & Björn Antonsson

Typesafe Webinar: Going Reactive with Java 8

Embed Size (px)

DESCRIPTION

Java 8's lambdas make building Reactive applications a whole lot easier and cleaner. Through copious code examples this session will show you how to build event-driven, scalable, resilient, and responsive applications with Java 8, Play Framework and Akka. On the web side you will learn about using lambdas for async & non-blocking requests & WebSockets. You will also learn how the actor model in Akka pairs well with lambdas to create an event-driven foundation that provides concurrency, clustering and fault-tolerance.

Citation preview

Page 1: Typesafe Webinar: Going Reactive with Java 8

Going Reactive with Java 8

Ryan Knight & Björn Antonsson

Page 2: Typesafe Webinar: Going Reactive with Java 8

Users Want

In-Sync DataReal-time CollaborationInstant FeedbackTo Not Wait

Page 3: Typesafe Webinar: Going Reactive with Java 8

Users Want Reactive Apps

www.ReactiveManifesto.org

Page 4: Typesafe Webinar: Going Reactive with Java 8

Reactive Web Apps with

Play Framework

http://www.playframework.com

Page 5: Typesafe Webinar: Going Reactive with Java 8

Reactive Web Apps withPlay Framework

Reactive RequestsReactive CompositionReactive Push2-Way Reactive

Page 6: Typesafe Webinar: Going Reactive with Java 8

RoutesDeclarative, Type-safe URL Mapping

VERB PATH CONTROLLER_METHOD

GET / controllers.Application.index()GET /foo controllers.Application.foo()

Page 7: Typesafe Webinar: Going Reactive with Java 8

ControllersSynchronous Request

Useful for requests that don`t have anything to not block on

public static Result syncFoo() { return ok("sync foo"); }

Page 8: Typesafe Webinar: Going Reactive with Java 8

Reactive Requests

Page 9: Typesafe Webinar: Going Reactive with Java 8

Asynchronous RequestUnder the covers Play implements all requests in this way

public static F.Promise<Result> asyncFoo() { return F.Promise.promise(() -> ok("async foo")); }

Page 10: Typesafe Webinar: Going Reactive with Java 8

Reactive Request (Async + Non-Blocking)

Needs to have something to not block on

public static Integer longRunningCalculation() { return (5134 * 5789) / 349; }

public static F.Promise<Result> basicPromise() { F.Promise<Integer> promise = F.Promise.promise(() -> longRunningCalculation()); return promise.map((Integer i) -> ok("The calculation result is: " + i)); }

Page 11: Typesafe Webinar: Going Reactive with Java 8

Reactive RequestsTwo chained requests (client to server & server to typesafe.com)

both async & non-blocking

public static F.Promise<Result> reactiveRequest() { F.Promise<WS.Response> typesafePromise = WS.url("http://www.typesafe.com").get(); return typesafePromise.map(response -> ok(response.getBody())); }

Page 12: Typesafe Webinar: Going Reactive with Java 8

Reactive CompositionThree requests, two in parrallel (depending on thread availability)

all async & non-blocking

public static F.Promise<Result> reactiveComposition() { final F.Promise<WS.Response> twitterPromise = WS.url("http://www.twitter.com").get(); final F.Promise<WS.Response> typesafePromise = WS.url("http://www.typesafe.com").get();

return twitterPromise.flatMap((twitter) -> typesafePromise.map((typesafe) -> ok(twitter.getBody() + typesafe.getBody()))); }

Page 13: Typesafe Webinar: Going Reactive with Java 8

Reactive Push with SSEAsync & Non-Blocking Server to Client Push

Java Controller

public static Result events() { EventSource eventSource = new EventSource() { public void onConnected() { sendData("hello"); } }; return ok(eventSource); }

CoffeeScript Client

events = new EventSource("/events") events.onmessage = (e) -> alert(e.data)

Page 14: Typesafe Webinar: Going Reactive with Java 8

2-Way Reactive with WebSocketsBi-directional reactive pushJava Controller with Java 8 Method Reference

public static WebSocket<String> echo() { return new WebSocket<String>() { public void onReady(final In<String> in, final Out<String> out) { in.onMessage(out::write); } }; }

CoffeeScript Client

ws = new WebSocket("ws://localhost:9000/echo") ws.onmessage = (message) -> console.log(message.data) ws.onopen = () -> ws.send("foo")

Page 15: Typesafe Webinar: Going Reactive with Java 8

Reactive Apps with Akka

http://akka.io

Page 16: Typesafe Webinar: Going Reactive with Java 8

Reactive Apps with AkkaActor BasedHighly ConcurrentAsynchronousDistributableScales Up & Out

Page 17: Typesafe Webinar: Going Reactive with Java 8

Akka Actor PropertiesMessage BasedEvent DrivenSane Concurrency ModelNon-Request Based LifecycleIsolated Failure Handling(Supervision)

Page 18: Typesafe Webinar: Going Reactive with Java 8

Actors with LambdasEasily define the behavior of your actor

public static class Greeter extends AbstractActor { String greeting = "";

public Greeter() { receive(ReceiveBuilder. match(WhoToGreet.class, message -> greeting = "hello, " + message.who). match(Greet.class, message -> sender().tell(new Greeting(greeting), self())). build()); } }

Page 19: Typesafe Webinar: Going Reactive with Java 8

Handing off WorkFor responsiveness and/or fault tolerance

public class HandoffActor extends AbstractActor {{ receive(ReceiveBuilder.matchEquals("hello", s -> { ActorRef worker = context().actorOf(Props.create(AbstractActor.class, () -> new AbstractActor() {{ receive(ReceiveBuilder. match(String.class, s -> { // long running and/or dangerous computation sender().tell(s.toUpperCase(), self()); self().tell(PoisonPill.getInstance(), self()); }).build()); }})); worker.forward(s, context()); }).build()); }}

Page 20: Typesafe Webinar: Going Reactive with Java 8

Supervision with LambdasTake different actions depending on the failure

private static SupervisorStrategy strategy = new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder. match(ArithmeticException.class, e -> resume()). match(NullPointerException.class, e -> restart()). match(IllegalArgumentException.class, e -> stop()). matchAny(o -> escalate()).build());

@Override public SupervisorStrategy supervisorStrategy() { return strategy; }

Page 21: Typesafe Webinar: Going Reactive with Java 8

Changing Behavior with LambdasQuickly implement changes in behavior

public class Swapper extends AbstractLoggingActor { public Swapper() { receive(ReceiveBuilder. matchEquals(Swap, s -> { log().info("Hi"); context().become(ReceiveBuilder. matchEquals(Swap, x -> { log().info("Ho"); context().unbecome(); // go back to previous behavior }).build(), false); // push on top and keep old behavior }).build()); } }

Page 22: Typesafe Webinar: Going Reactive with Java 8

Actors as Finite StateMachines

A Fixed Number of StatesDefined Transitions Between StatesUsed to Model for Example

ProtocolsProcesses

Page 23: Typesafe Webinar: Going Reactive with Java 8

Finite State MachinesDefining Behavior in States

public class Buncher extends AbstractFSM<State, Data> {{ startWith(Idle, Uninitialized);

when(Idle, matchEvent(SetTarget.class, Uninitialized.class, (setTarget, uninitialized) -> stay().using(new Todo(setTarget.getRef(), new LinkedList<>()))));

when(Active, Duration.create(1, "second"), matchEvent(Arrays.asList(Flush.class, StateTimeout()), Todo.class, (event, todo) -> goTo(Idle).using(todo.copy(new LinkedList<>()))));

// ... transitions left out

initialize(); }}

Page 24: Typesafe Webinar: Going Reactive with Java 8

Finite State MachinesDefining Transition Behavior

public class Buncher extends AbstractFSM<State, Data> {{ startWith(Idle, Uninitialized);

// ... state behavior left out

onTransition( matchState(Active, Idle, () -> { // reuse this matcher final UnitMatch<Data> m = UnitMatch.create( matchData(Todo.class, todo -> todo.getTarget().tell(new Batch(todo.getQueue()), self()))); m.match(stateData()); }). state(Idle, Active, () -> {/* Do something here */}));

initialize(); }}

Page 25: Typesafe Webinar: Going Reactive with Java 8

Interoperability

https://github.com/scala/scala-java8-compat

Page 26: Typesafe Webinar: Going Reactive with Java 8

Java Scala InteroperabilitySeamlessly Work with Scala Futures

import scala.concurrent.*; import static scala.compat.java8.JFunction.*;

class Test { private static Future<Integer> futureExample(Future<String> future, ExecutionContext ec) { return future.map(func(s -> s.toUpperCase()), ec).map(func(s -> s.length()), ec); } }

Page 27: Typesafe Webinar: Going Reactive with Java 8

Java Scala InteroperabilitySeamlessly Convert Between Java CompletionStage and Scala

Future

import java.util.concurrent.CompletionStage; import scala.concurrent.Future; import static scala.compat.java8.FutureConverters.*;

final CompletionStage<String> cs = ... // from an async Java API final Future<String> f = toScala(cs); ... final Future<Integer> f2 = ... // from an async Scala API final CompletionStage<Integer> cs2 = toJava(f2);

Page 28: Typesafe Webinar: Going Reactive with Java 8

Demo: Reactive Stocks (Java 8)

Get the Activator Template: http://typesafe.com/activator/template/reactive-stocks-java8

Akka Actors for thread-safe state and non-request based eventsPlay Framework for Reactive Composition, Reactive Push, and aJavaScript UI

Reactive Stocks (Java 8)

Page 29: Typesafe Webinar: Going Reactive with Java 8

Get Started with Activator

http://typesafe.com/activator/template/hello-akka-java8

http://typesafe.com/activator/template/reactive-java8-play

http://typesafe.com/activator/template/akka-supervision-java-lambda

http://typesafe.com/activator/template/akka-sample-fsm-java-lambda

http://typesafe.com/activator/template/akka-sample-persistence-java-lambda

http://typesafe.com/activator/template/reactive-stocks-java8

Hello Akka! (Java 8)

Go Reactive with Java 8 & Play Framework

Akka Supervision in Java with Lambdas

Akka FSM in Java with Lambdas

Akka Persistence Samples in Java with Lambdas

Reactive Stocks (Java 8)