We recently decided to port code over from a Play Framework app written in Java over to Scala for many reasons like Scala’s expressiveness and asynchronous capabilities. Our code was messy, excessively verbose and highly blocking so the plan was to introduce Scala, clean up as much as possible and to write non-blocking code for new pages.

We started with the Corporate site pages like the homepage, about us, contact, etc. These pages were backed by controller actions that looked like:

This was not incredibly bad, but it was not as fluid as we wanted. The code was also making blocking service calls, which was hurting performance so we decided to first make the action declaration read better. This is when we started looking into Play’s Action Composition. We wanted to use verbs (since these were actions) for action function names. For example, we wanted an action that required authentication and notifications to look like:

Our first thought was to validate the request and inject data into it for use in the action. So, in pseudo code this read like:

We explored ActionBuilder[R], which extends from the ActionFunction[R] and is composable. The main functionality is placed in the invokeBlock[A] method. We easily ported the @Authenticated annotation logic here:

Note the use of a custom request case class AuthRequest , which wraps the original request, layering it with additional data. Basically, this builder accepts a request and a function (that accepts our custom AuthRequest and returns a Future[Result] ). Since invokeBlock returns a Future[Result] it was very easy to compose async builders like this. Using a case class for AuthRequest was not the only option. A trait would’ve worked too, but case classes offer pattern matching, which could be useful down the line.

Next, we had to create a similar ActionFunction to inject notifications. This time we played with ActionTransformer[R, P], which transforms a request from type R to type P . Here’s what we did:

Again, using the NotificationRequest case class we were able to layer an optional list of the users notifications to the request, except this time the request was an AuthRequest . Here we used an ActionTransformer that transforms the AuthRequest to a Future[NotificationRequest] .

So as you can see we can keep adding more ActionBuilder s, ActionTransformer s, ActionRefiners and ActionFunction s to layer more functionality onto a request before it reaches the core action code to keep it lean and focused on doing one thing: rendering a view, redirecting, etc. Here’s what our action looked like at the end of all this manipulation: