Introducing Akka Cloud to Edge Continuum. Build once for the Cloud. Seamlessly deploy to the Edge - Read Blog
Support
play-framework java8

Play Framework with Java 8

In case you missed our recent post Go Reactive with Java 8 or the follow-up webinar, a stable release of Java 8 is now available and is supported by the Play Framework. Some of the new Java features lend themselves well to developing Reactive applications with Play, and I’ll show you how to use them.

If you’re new to Play, it’s a modern web application framework that is designed to meet the tenets of Reactive Systems. Play gives you the foundation to make scalable and responsive applications based on Functional Programming patterns. This is natural to do in Play and using Java 8 makes these patterns clearer and more concise. I’m going to demonstrate how to do this using sample code taken from the Typesafe Activator template “Go Reactive with Java 8 & Play.”

I’ll start by showing a synchronous (blocking) controller action:

public static Integer longRunningCalculation() {

    return (5134 * 5789) / 349;

}

public static Result syncFoo() {

    Integer i = longRunningCalculation();

    return ok("The calculation result is: " + i);

}

This action uses the same thread to handle a request, execute longRunningCalculation(), construct a Result, and serve a response. In other words, the thread is blocked for the duration of the request lifecycle. This is how traditional Java Servlet containers work and for fast returning actions a synchronous flow is acceptable, but in general this is a Reactive anti-pattern and should be avoided. Play was designed to remedy this problem and it provides a programming model that allows you to decouple request/response execution from action logic execution.

Here's how the action can be rewritten to take advantage of Play’s Reactive model:

public static F.Promise<Result> asyncFoo() {

    F.Promise<Integer> promise = F.Promise.promise(() -> longRunningCalculation());

    return promise.map((Integer i) -> ok("The calculation result is: " + i));

}

Now the controller action is non-blocking. The request thread delegates the action logic to F.Promise.promise() which will run its function argument on a separate background thread but returns a Promise<Integer> without waiting for this execution. A Promise is a wrapper for a value that will become available sometime in the future. When this Promise<Integer> is fulfilled with the calculation result, the Integer value will be mapped to a Result using the function argument of promise.map(...). The request thread doesn’t need to wait for the calculation or subsequent mapping and can immediately return a Promise<Result>, which frees itself for re-use by the server. Play's event-driven model will listen for the eventual completion of the Promise<Result> which will trigger allocation of another thread to serve the response. This is just one example of how Play provides abstractions that reduce code requirements. And what's really cool here is that we're able to use Java 8 Lambda Expressions for the F.Promise.promise() and promise.map() methods. In previous Java versions the same action functionality would have required anonymous inner classes and might have spanned 14 lines.

This pattern of abstracting asynchronous executions using Promise wrappers is used extensively in Play to prevent blocking throughout the entire request chain. For example, here’s a controller action that depends on an external service call using Play’s Web Service library:

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()));

}

The Play WS.url().get() call is asynchronous and returns a Promise<WS.Response>. After the WS call completes the WS.Response is transformed to a Result using another Java 8 Lambda Expression.

For more complex controller actions we can do “Reactive Composition” which is a pattern for combining multiple Promises into a single Promise<Result>:

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())));

}

 

In this example both WS.url().get() calls run in independent threads and each returns a Promise<WS.Response>. When these Promises are completed the results are composed or combined into a single Result. The request and response threads are never blocked!

You can also create controller actions to Reactively push events to a client:

// Java controller

public static Result events() {

    EventSource eventSource = new EventSource() {

        public void onConnected() {

            sendData("Vaya con dios brah!");

        }

    };

    return ok(eventSource);

}
# Coffeescript

events = new EventSource("/events")

events.onmessage = (e) ->

    alert(e.data)

Or you can do a "2-Way Reactive" push action with WebSockets:

// Java controller

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

ws = new WebSocket("ws://localhost:9000/echo")

ws.onmessage = (message) ->

  alert(message.data)

$("#websocket-demo").click () ->

  ws.send("foo")

Note that the argument for in.onMessage() uses another cool Java 8 feature, a Method Reference.

That covers the core Reactive patterns for the Play Framework using Java 8. To learn more, install Java 8, download Typesafe Activator, and start playing with the Java 8 templates. Have fun!

The Total Economic Impact™
Of Lightbend Akka

  • 139% ROI
  • 50% to 75% faster time-to-market
  • 20x increase in developer throughput
  • <6 months Akka pays for itself