Migrating to Play 2.1

Play 2.1 Migration

I have just finished migrating one of my apps from Play 2.0.4 to 2.1 and while doing that I compiled a list of all the big & little things that I had to adapt. My app uses many parts of Play (except Anorm) so hopefully it will cover a lot of problems you will encounter. My app is written entirely in Scala, so changes in the Java API will (mostly) not be covered. First of all you should read the official migration guide.

Compilation

Compilation times seem to have become even slower than before. Even on simple project with only a few files you can wait a good amount of time after changing a single file. I could actually trace this back to the fact that even when running play ~run (automatic compilation on file change, only useful when you’re not using an IDE) doesn’t prevent a re-compile when refreshing the browser.

What’s gone

Mixing Scala and Java API and using templates doesn’t seem to be possible anymore. As soon as you add javaCore to your dependencies, your templates will expect their types from either the Scala or Java API, whereas before it would choose the correct one for you.

Using Option in path parameters (they removed the PathBindable). You can implement your own PathBindable for this (as shown here), however they are right in that it doesn’t make much sense to have an optional value in your path.

What’s changed

Scala Futures

Play 2.0’s Promise has been replaced by Scala 2.10’s Future. This also means that instead of Akka.future {} you now wrap code that should be computed asynchronously with scala.concurrent.Future {}. And don’t forget to bring the right execution context in scope. The default execution context in Scala is scala.concurrent.ExecutionContext.Implicits.global, Play offers another one with play.api.libs.concurrent.Execution.Implicits._). If you have some blocking code, make sure to use a different context so the server thread won’t block.

More infos in the official documentation and in this excellent introduction.

JSON

The JSON parser has been rewritten. For one, the reads method no longer returns the value directly, but is wrapped in a JsResult. JsResult is a monadic structure which can be constructed using validate and allows for our well-known for comprehension:

implicit object UserReads extends Reads[User] {
  def reads(json: JsValue): JsResult[User] = for {
    name < - (json  "name").validate[String]
    email <- (json  "email").validate[String]
    password <- (json  "password").validate[String]
  } yield User(name, email, password)
}

This yields either a JsSuccess(user, _) or a JsError(_, Seq[ValidationError]).

While this work perfectly fine, it only catches the first error found. If you want to aggregate all errors, you have to use the functional builder pattern:

import play.api.libs.functional.syntax._
implicit val UserReads: Reads[User] = (
  (__  "name").read[String] ~
  (__  "email").read[String] ~
  (__  "password").read[String]
)(User)

You could then parse a String into a JsValue, and turn that value into a JsResult[User]:

val json = Json.parse("""{ "name" : "John Smith", "email" : "mail@company.com", "password" : "asd-h-33-hasdh" }""")
val userResult = Json.fromJson[User](json)
userResult foreach ( user => println(user.name) )

Generating JSON is a bit simpler now, you no longer have to mix JSON types with Scala types, e.g.: Seq[JsObject] = toJson(Map("name" -> name, "email", )) can now be expressed as Json.obj("name" -> name, "email") and Js.array("foo", "bar", "baz").

For more info check out the official blog post.

PushEnumerator is deprecated

If you’re using PushEnumerator, you’ll see this compiler error: class PushEnumerator in package iteratee is deprecated: use Concurrent.broadcast instead. Concurrent.broadcast() is a method that creates a tuple of an Enumerator and a Channel. A Channel is a means of pushing data imperatively into one or more iteratees. You use the enumerator to produce data and pass that data to the iteratee(s) via the channel. val enumerator = Enumerator.imperative[String]() now becomes val (enumerator, channel) = Concurrent.broadcast[String] When calling Ok.stream(), the enumerator is sufficient, just as before. Use the channel where the data is produced, for example inside an actor, and call the push method as you would have done on the PushEnumerator. This separates the imperative code from the Enumerator, which seems to be a sensible choice. What’s a bit annoying is that this introduces yet another import with play.api.libs.iteratee.Concurrent._, since the Channel trait is hidden inside the Concurrent object. The number of imports seems to grow with every release. Concurrent also contains a lot more utility methods for creating Enumerators, Enumeratees, and so on.

EssentialAction

EssentialAction is the new superclass (well, trait) of Action and is defined as (RequestHeader => Iteratee[Array[Byte], Result]), i.e. a function that maps a request to an Iteratee which in turn takes a byte stream and outputs a Result. Actions are still used in that they are a simplification of EssentialAction when you don’t care how the body is parsed and you are just interested in the request, the body as parsed to the correct type (instead of a raw byte stream), and the result. If you write a body parser, it still has to deal with the byte array.

You will stumble upon EssentialAction if you are using the built-in Security.Authenticated helper. You can easily migrate by changing the return type to EssentialAction, like this:

def Authenticated[A](p: BodyParser[A])(f: => String => Request[A] => Result): EssentialAction =
  Security.Authenticated(userFromCookie, onUnauthorized) { user =>
    Action(p) { request =>
      f(user)(request)
    }
  }

// Convenience for when you don't need a BP and simply use AnyContent
def Authenticated(f: => String => Request[AnyContent] => Result): EssentialAction =
  Authenticated(BodyParsers.parse.anyContent)(f)

EssentialFilter

A Filter is a light-weight action you can use when you don’t even care about the request body. Mix-in WithFilters in your Global object as explained in this post.

Routes

The routes compiler now catches unreachable code (i.e. two routes which map to the same action). I used this when a POST /login failed and the user would accidentally navigate to GET /login. In that case I would serve him the index page. In 2.1, this has to be implemented with a redirect.

Also, you can use routes from submodules as explained in the migration guide.

Minor API changes

Formatters apparently now have to be implicit objects, my implicit defs were no longer recognized (but this is a best practice anyway).

PathBindable and QueryStringBindable both have a new helper class Parsing with makes defining new bindables trivial, and they also have a new transform method to create a bindable B from a bindable A.

play.api.http.MimeTypes, a new object in the http package (StandardValues.scala) which defines constants for HTTP mime types, so instead of saying as("text/html") you can now say as(HTML). Accompanied by MediaRange, which basically allows setting multiple MIME types (for example in an Accept header) so if the preferred type is not available, other types can be accepted.

Scala 2.10 compiler

The compiler seems to become smarter and smarter (I wonder when it will become self-aware). This not related to Play but to Scala 2.10, but seeing error like this at compile time impressed me: comparing values of types play.api.i18n.Lang and String using '==' will always yield false.

Posted in Scala & Playframwork
2 comments on “Migrating to Play 2.1
  1. Bruno Unna says:

    The routes compiler now catches unreachable code (i.e. two routes which map to the same action). I used this when a POST /login failed and the user would accidentally navigate to GET /login. In that case I would serve him the index page. In 2.1, this has to be implemented with a redirect.

    A brief disclaimer: I’m relatively new to the Scala ecosystem, so please be patient with me. 🙂

    How come several, distinct routes can render some “unreachable code”? I understand the reverse-resolution mechanism should be given a clear set of rules in order to operate without ambiguities, but the direct mechanism, which is what I’m interested in right now, should be working out-of-the-box. Or else…?

    My code:


    # Item-related actions
    POST /item controllers.ItemController.newItem
    PUT /item controllers.ApplicationController.methodNotAllowed
    GET /item controllers.ApplicationController.methodNotAllowed

    Yields this message:


    [warn] /home/bruno/Entwicklung/pServer/conf/routes:8: unreachable code
    [warn] GET /item controllers.ApplicationController.methodNotAllowed
    [warn] one warning found

    Since this case, from my point of view, should be rather common when programming REST services, I’m sure I’m missing something important here.

    Should you have any suggestion as to the best way to approach this problem, I’ll appreciate it. 🙂

    • marius says:

      It’s all about the reverse-routing in your case. For example in your Scala template, when you write `@controllers.ApplicationController.methodNotAllowed`, Play will pick the first item that matches this method, so you will always get PUT. Calling `/item` in your browser will be resolved correctly (hence only a warning, not an error).

Leave a Reply

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

*

Time limit is exhausted. Please reload CAPTCHA.