Typesafe Webinar: Going Reactive with Java 8
Post on 06-May-2015
3014 Views
Preview:
DESCRIPTION
Transcript
Users Want
In-Sync DataReal-time CollaborationInstant FeedbackTo Not Wait
Users Want Reactive Apps
www.ReactiveManifesto.org
Reactive Web Apps withPlay Framework
Reactive RequestsReactive CompositionReactive Push2-Way Reactive
RoutesDeclarative, Type-safe URL Mapping
VERB PATH CONTROLLER_METHOD
GET / controllers.Application.index()GET /foo controllers.Application.foo()
ControllersSynchronous Request
Useful for requests that don`t have anything to not block on
public static Result syncFoo() { return ok("sync foo"); }
Reactive Requests
Asynchronous RequestUnder the covers Play implements all requests in this way
public static F.Promise<Result> asyncFoo() { return F.Promise.promise(() -> ok("async foo")); }
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)); }
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())); }
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()))); }
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)
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")
Reactive Apps with AkkaActor BasedHighly ConcurrentAsynchronousDistributableScales Up & Out
Akka Actor PropertiesMessage BasedEvent DrivenSane Concurrency ModelNon-Request Based LifecycleIsolated Failure Handling(Supervision)
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()); } }
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()); }}
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; }
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()); } }
Actors as Finite StateMachines
A Fixed Number of StatesDefined Transitions Between StatesUsed to Model for Example
ProtocolsProcesses
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(); }}
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(); }}
Interoperability
https://github.com/scala/scala-java8-compat
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); } }
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);
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)
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)
top related