Play 2.3, Java 8 and async results

For the Java developers, Play 2.3 greatest feature is the native support for Java 8 and all things that are possible with lamba support.  Almost all pieces of code that were built with anonymous classes now can be replaced with lambdas.

Let’s see the case when we want to return a async result. The older version is like this:

    Promise<List<Photo>> promise = Promise.promise(new Function0<List<Photo>>() {

    	@Override
    	public List<Photo> apply() throws Throwable {
  		  return JPA.em().createQuery("select p from Photo p",Photo.class)
  		  .getResultList();
    	}
    });

    return promise.map(new Function<List<Photo>, Result>() {

    	@Override
    	public Result apply(List<Photo> photos) throws Throwable {
    		Html render = views.html.photos.render(photos);
    		return ok(render);
    	}
    });

The new version with lambdas is way more cleaner.

    Promise<List<Photo>> listingPhotos = Promise.promise( () -> {
    	return JPA.em().createQuery("select p from Photo",Photo.class).getResultList();
    });

Remember, all methods that receive functional interfaces(interfaces with just one method) can be used passing lambda as arguments!

And here, we didn’t separate our code like we should. Database access is being done in our controller. If we put this code in a different class, we can improve the usage of promise.

  Promise<List<Photo>> listingPhotos = Promise.promise(Photos::all);

Method Reference is a great feature to use with lambdas, the code is much more cleaner. Now you have to use map method to transform the Promise<List<Photo>>  to Promise<Result>.  This will be a common situation around your application.

    return listingPhotos.map((photos) -> {
    	Html render = views.html.photos.render(photos);
    	return ok(render);
    });

Here we can try to be more creative. I would like to use Method Reference to create Promise<Result> rather than use the map method. It would be nice if we had used a pimped version of Promise class with statuses map method. Here a example:

    return new PimpedPromise<List<Photo>>(listingPhotos).
            map(Controller::ok,views.html.photos::render);

There is nothing out of the box in Play so, to accomplish this, we can create our pimped version! Take a look:

    public class PimpedPromise<T> {

    	private Promise<T> promise;

    	public PimpedPromise(Promise<T> promise) {
    		this.promise = promise;
    	}

    	public <B extends Content> Promise<Result> map(play.libs.F.Function<Content, play.mvc.Results.Status> statusFunction,Function<? super T, B> callback) {
    		Promise<B> contentPromise = promise.map(callback);
    		return contentPromise.map(content -> {
    			return statusFunction.apply(content);
    		});
    	}

    }

We just changed a little bit the signature of map method :). We forced the developer to pass a function(second argument) that returns a Content object. Then we get the result of promise.map and we have to map again using the status function(first argument). Maybe it is a little bit complicated inside our pimped promise but is, at least for me, better to be used in controllers.

What do you think? Have you tried to create something new with the lambda support?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s