In Part 1 we covered routes, controllers and client side scripting. In the time since that post, the Play framework released version 2.4 (Damiya) on May 27, 2015. With a major point release there are usually enough changes to warrant taking some time to rebuild a few things. Since the ticket-overlords project is still fairly small, the effort will be minimal. This gives us a good opportunity to take a look at what is entailed in performing a framework upgrade.

As before, the source code for this tutorial series is available on github with the code specifically for this post here. Since the code builds on the previous post, you can grab the current state of the project (where part one finished) here.

Updating the reference to Play

In project\plugins.sbt change the installed sbt-plugin for Play to reflect the new version of the framework. As well, sbt-mocha got a version bump.

// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.0")

// ... <snip> ...

// The sbt Mocha Plugin
addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0")

In addition, the latest version of play requires sbt version 0.13.8. Open up project/build.properties and update that reference as well.

sbt.version=0.13.8

Changes in dependencies

When you reload activator, it will download all the new dependencies and then fail in an error.

[info] Done updating.
Anorm has been moved to an external module.
See https://playframework.com/documentation/2.4.x/Migration24 for details.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?

Every major release of Play comes with a well documented migration guide. This document outlines how features have changed from the previous version and suggestions on how to bring your code up to speed.

The first change we will need to make is explicitly including the eclipse sbt plugin. As the migration guide mentions, the eclipse plugin is no longer included by default. Open up project/plugins.sbt and add the following line:

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

Note: at the time of this posting, 4.0.0 was still in Release candidate status, so if this does not work for you, try version “4.0.0-RC2”

Next in the 2.4 migration guide, there is a section explaining how Anorm (the database access library) has been moved from the core framework into a new separate library.

Since we do not currently use Anorm, we can remove that from our build.sbt file. The modified libraryDependencies should now look like this:

libraryDependencies ++= Seq(
  jdbc,
  cache,
  ws,
  "org.webjars" % "jquery" % "2.1.3"
)

In the activator terminal, press r to retry loading. Activator will successfully load the application. At this point you will want to regenerate the eclipse settings for the project.

[ticket-overlords] $ eclipse with-source=true

You will notice it download even more dependencies downloaded. At this point refresh the project in eclipse. You will notice a large number of errors print out in the IDE. This is because specs2 which was used for tests in the initial template has also been pulled out of the core Play distribution.

Specs2 Dependency Missing

We can easily add this back by modifying our libraryDependencies again. We will also need to add a resolver for the scalaz-stream dependency as mentioned in the migration guide.

libraryDependencies ++= Seq(
  specs2 % Test,
  jdbc,
  cache,
  ws,
  "org.webjars" % "jquery" % "2.1.3"
)

resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"

Deprecated methods

We need to restart activator and regenerate our eclipse settings again. Once that is complete, refresh the project in eclipse. Now that it compiles successfully, the errors disappear, but new warnings about javascriptRouter appear instead.

If you do get errors in eclipse, delete the contents of your target folder, it will be recreated next compile).

javascriptRouter is deprecated

We do not have to change this now, but we might as well fix any deprecated calls when we find them as opposed to getting stuck at a later point. This can easily be fixed by adding an import statement and changing one line in the Application.scala controller.

package controllers

import play.api._
import play.api.mvc._
import play.api.routing.JavaScriptReverseRouter

object Application extends Controller {

  def index = Action {
    Ok(views.html.index())
  }

  def jsRoutes = Action { implicit request =>
    Ok(
        JavaScriptReverseRouter("jsRoutes")(
        routes.javascript.Tickets.ticketsAvailable
      )
    )
  }

}

Configuration changes

At this point we can ~ run the application and manually verify it has the same behavior as before. Looking through the rest of the Migration Guide there are some interesting things we have not yet had a chance to play with, like the Dependency Injection changes. (We will get to that eventually, just not today).

One portion that stands out is the Configuration Changes section. Our project contains a file named conf\application.conf that we have not modified before, but is already out of date!

Open application.conf and change the following:


play.crypto.secret

Note, your value for application.secret will be different if you created the template on your own. No need to worry about the value yet, just change the configuration parameter name.

Old:

application.secret="VRZV/ppo<t?;NKZN?=PE<N;Yie_G^:sxQrL544YEl[fRsrE<:hMbT;Yj<WhG`bS@"

New:

play.crypto.secret="VRZV/ppo<t?;NKZN?=PE<N;Yie_G^:sxQrL544YEl[fRsrE<:hMbT;Yj<WhG`bS@"

play.i18n.langs

Old:

application.langs="en"

New:

play.i18n.langs="en"

Updates to logging

You will also have noticed that while loading the application, there was a warning about logging features no longer being loaded from the application.conf. Create a file named conf/application-logger.xml and add the following contents.

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>logs/ticket-overlords.log</file>
    <encoder>
      <pattern>
%date %level [%thread] %logger{10} [%file:%line] %msg %n
      </pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <encoder>
      <pattern>
%gray([%-20file:%-3line]) %highlight(%-5level) %boldBlue(%logger{15}) :: %msg %n
      </pattern>
    </encoder>

  </appender>

  <logger name="play" level="INFO" />
  <logger name="application" level="DEBUG" />

  <root level="WARN">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

This gives us application logging at the DEBUG level, but INFO for the rest of play and WARN for everything else. We also get some colors in our logs that are displayed to the activator console.

Remove the old logging parameters from the configuration file as well, since they now serve no purpose.

We now have an up to date version of the application, ready for development with the latest version of the Play framework.

Until next time…

We stepped through the changes required for 2.4 coming from a 2.3 application. Even a tiny application like ours requires some love and attention when a new version of the framework is released. Once you get the hang of it, you can get through the upgrades fairly quickly.

I would strongly recommend reading the Play framework mailing list to get an idea when the milestone and release candidates are available and also to get a handle on how impactful the changes will be to projects you maintain. In addition, the migration guides are helpful to learn about features you may not have even realized existed.

In part 3, we will cover database access, schema creation and migration and build out more of the REST API.