Play 2.0, Scala and the new way of doing things

Recently there’s been a (heated) discussion on the Play framework mailing list about Play 1.x vs Play 2.0, Scala, and the added level of complexity.

First off, some of these points are completely valid. For many Java hackers, Play 1.x was an enlightenment. While it’s true that it was a copy of Ruby on Rails in Java, it was the first framework which allowed agile web development on the JVM (i.e. hot-reloading, compile errors are shown in the browser, no XML configuration, and so on). With 1.1 and 1.2 it added most of the needed features while keeping a light style of development. Many people feel that with Play 2.0, this lightness has gone.

Why is that? Let me show you some examples.

Claim 1: You have to learn a new language

Play 2.0 is written in Scala, and even though it has a Java API, as a non-Scala developer you quickly encounter code you don’t understand. First and foremost, it’s the templating engine, which is based on Scala. The framework authors’ response is that you can switch out the templating engine. But why use a web framework if you have to switch out every component? And it’s obviously not the first thing you want to do when trying out something for the first time. I still don’t understand why they didn’t bundle the Groovy engine.

The build file is not only written in Scala, but even a Scala DSL. I initially found this to be an advantage since I already knew SBT. Well, at least I thought so. SBT 0.7 was a joy to use, but apparently it’s a fun exercise to completely change the DSL with every point-release. They should also have changed the name because this tool is anything but simple.

And for the record, the route files are written in Scala-style, too. However, this shouldn’t be a big a deal, as the route syntax is pretty limited.

Whether or not you like Scala itself is a very personal choice; you should at least give it a try. Yes it’s a complex beast, but it also allows you to write beautiful code, especially if you embrace the functional paradigm (see the examples below).

Claim 2: Compilation times are slower

This is what I found to be the biggest problem with Play 2.0. Agile development with fast tournaround times makes only half as much sense when one small change in a templates results in the recompilation of 60 classes and takes 10 seconds. Fortunately, the authors of Play and of SBT (the compiler being the main culprit here) are aware of that. So hopefully, compile times will improve in the near future.

Another annoyance was unexpected runtime errors (e.g. VerifyError) every now and then. This should vanish as the framework matures.

Conclusion?

So, is Play 2.0 a step in the wrong direction? Absolutely not. I used Play 2.0 with Scala for about three months (even before it reached RC status), and found it an an absolute joy to use. In short, this is because it supports a style of development I’d call Functional Web Programming. Let me show you what I mean by that.

Action Composition

Actions (i.e. the methods that are invoked by clicking a link or pushing a button) are composable, which means you can take one, and wrap it around another, and end up with a new action that is a combination of the two. This allows for powerful and scaling abstractions.

The basic action is called Action (no surprise here) and is essentially a function which maps a request to a result. For example, in our application we have pages that can only be accessed by an administrator. So the easiest way to protect those pages was to define an action called AuthenticatedAdmin which in turns calls Authenticated (whose only job is it to verify if the user is logged in), which in turn calls the actual action.

In terms of code it looks like this:

def Authenticated[A](p: BodyParser[A])(f: AuthenticatedRequest[A] => Result) = {
  Action(p) { implicit request =>
    request.session.get("email").flatMap(email => UserDAO.findByEmail(email)).map { user =>
      f(AuthenticatedRequest(user, request))
    }.getOrElse(Results.Ok(views.html.error("Not Authorized", "You have to log in to view the requested page")))
  }
}

def AuthenticatedAdmin[A](f: AuthenticatedRequest[AnyContent] => Result) = Authenticated { implicit request =>
  request.user.adminProfile match {
    case Some(profile: AdminProfile) => f(AuthenticatedRequest(request.user, request))
    case _ => Results.Ok(views.html.error("Not Authorized", "You need administrator privileges to access the requested page"))
  }
}

The Authenticated action reads the email from the session cookie. If the email is not there, the user has to log-in (which is an overlay in our app, otherwise you’d redirect to the log-in page). If the email is found it is used to find the actual user object (from the database or the cache) and put it in the request (a custom request called AuthenticatedRequest, essentially a case class containing the real request and the user). Now the AuthenticatedAdmin action can reuse these mechanics and add another layer around it. It only checks if the user has an admin profile (which is a simple role system of course) and only then execute the action function (called f) itself.

Finally we can use it in the controller like this:

def index = AuthenticatedAdmin { implicit request =>
  Ok(views.html.admin.index())
}

Take a look at the official documentation for more examples. In a future blog post I will show what kung fu you can do with them.

Templates are functions, too

The templating engine uses Scala code and mixes code and markup based on ASP.NET Razor. While I’d like to see a templating engine that completely separates code and markup (as in Lift or Enlive), this engine is also a pleasure to work with.

A template is a function. The first line of the template defines its input parameters, and the content is the return value. And as in a typical function, you can call other functions (or templates) from within. You can find some cool examples in the wiki.

Composable Framework

The framework itself is composable. You can use a different templating engine (e.g. the aforementioned Groovy engine), you are free to use whatever datastore you want, you can use Akka, or any other JVM library or SBT plug-in. Heck you can even dismiss the core framework and use only the templating engine and Anorm with Akka, BlueEyes or Spray.

Conclusion (now for reals!)

So far Play 2.0 was an enjoyable experience and I’m looking forward to seeing it mature and using it in future projects. I hope you’ll enjoy it, too.

Posted in Scala & Playframwork Tagged with: , ,
One comment on “Play 2.0, Scala and the new way of doing things
  1. Paul says:

    Hey, great post! I used it when trying to evaluate upgrading to 2.0 from 1.2.4. You can see our take on the subject over at the Awfbeat.com blog… http://blog.awfbeat.com/post/22314115684/impressions-of-play-framework-1-2-4-vs-2-0.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.