Play Framework – A simple cookbook

Play Framework is creating a lot of hype but it is still way behind that generated by Bitcoin. Just saying.

Anyways, let’s get to the point without beating around the bush.

The documentation of Play sucks big (no pun intended :-)). The differences between Play 1.x and 2.x are so profound that it requires a complete code change. This can be a huge thumbs-down in deciding to use Play in the first place. But, you know, LinkedIn is using it. So there must be something about Play. Innit?

Bearing this in mind, I decided to go ahead with Play come what may. There were lots of places where I got stuck for days with no help whatsoever except from yours truly :-). This (running) blog post aims to make the lives of some developers easy by giving detailed instructions on some of the issues I faced and how to overcome it.

Async Programming

Play is built on Akka which bills itself as “… toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on the JVM”. Hence, async must come natively. It does. But it isn’t very easy to understand how to implement it.

Any initial documentation search tells us to use –

F.Promise<WS.HttpResponse> remoteCall = WS.url("http://www.pristinecrap.com").getAsync();

This works perfectly as long as we use URLs directly. What if we use third party libraries? This is where the documentation tends to get murky.

Do not worry. The below code snippet worked for me –

import play.libs.F.Promise;
import play.libs.Akka;
import play.mvc.Result;
import play.mvc.Controller;

public class ApplicationController extends Controller {
     public static Result asyncProcess() {
          ...
          Promise<BusinessObject> businessObject = Akka.future(new Callable() {
               public BusinessObject call() {
                    return newBusinessObject(originRequestParameters);
               }
          });
          return async(
               businessObject.map(
                    new Function () {
                         public Result apply(BusinessObject businessObject) {
                              return (ok(page.render()));
                         }
                    }
               }
          );
     }
}

I am yet to figure out how to implement async operations outside of the Controller 😦

Jobs & Global Settings

Play 1.x has support for Jobs. It was very easy to understand the concepts with annotations such as @OnApplicationStart for running bootstrap jobs, @Every and @On for running scheduled and cron jobs.

Play 2.x completely removed this concept of Jobs. Why? Don’t ask me. Nevertheless, I spent a few hours to figure out how to simulate a job. The @OnApplicationStart functionality is obtained by extending GlobalSettings and writing your logic inside onStart(Application app) function.

import play.GlobalSettings;

public class ApplicationGlobal extends GlobalSettings {
     @Override
     public void onStart(Application app) {
          ...
     }
}

Scheduler

Ok you explained how to implement a bootstrap job in Play 2.x. Nice! But how do we implement a scheduled job? This question really frustated me as none of the available documentation worked.

The first implementation that you will come across is for Play 2.0 –

import play.libs.Akka;
import akka.util.Duration;

Akka.system().scheduler().schedule(
     Duration.create(0, TimeUnit.MILLISECONDS),
     Duration.create(30, TimeUnit.MINUTES)
     testActor, 
     "tick"
);

I am not sure if the above code snippet works in Play 2.0. But in Play 2.1, it doesn’t compile. The package akka.util.Duration doesn’t even exist and it is not a one-off case. Why have they made so many changes in minor version upgrades too? Blows my mind! I spent one day just to find out how to implement a scheduled job in Play 2.1. You don’t have to go through the same mental torture –

import play.libs.Akka;
import scala.concurrent.duration.FiniteDuration;
import java.util.concurrent.TimeUnit;

Akka.system().scheduler().schedule(new FiniteDuration(0, TimeUnit.SECONDS), new FiniteDuration(1, TimeUnit.MINUTES), new MyCustomJob(), Akka.system().dispatcher());

The above job runs every 1 minute and executes MyCustomJob() which is a class that implements Runnable.

To run a scheduled job just once at a pre-determined time, use the following –

import play.libs.Akka;
import scala.concurrent.duration.FiniteDuration;
import java.util.concurrent.TimeUnit;

Akka.system().scheduler().scheduleOnce(new FiniteDuration(1, TimeUnit.MINUTES), new MyCustomJob(), Akka.system().dispatcher());

As you can see, these are just some of the issues that I have faced and their solutions. Just pray that I run into more issues 🙂

Advertisement
This entry was posted in Technical and tagged , , , , , , , . Bookmark the permalink.

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 )

Facebook photo

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

Connecting to %s