Blog | Blue Matador

Setting Up Play Framework Evolutions with Dependency Injection and MySQL

Written by Mark Siebert | Mar 23, 2017 4:01:00 AM

If you wanted Play Framework, DB migrations, MySQL, and compile time dependency injection, you might have a tough time with Play's documentation. Even though we work on cloud performance monitoring software on the daily, we don't cut through documentation the way we can divine productions issues from raw data streams.

If you’re anything like us, you love Scala and Play Framework. You are probably a fierce advocate of compile time dependency injection (who wants to have to actually run their app to know if it’s correct?). You definitely have a database and want to use Play Framework’s evolutions for database migrations. However, if you read Play’s documentation, you’ll find that it’s a little incomplete and you need to do a little detective work through the Scaladocs to piece things together. We did that digging when we set up our MySQL databases with Play, and have compiled our findings here so you don’t have to waste time searching. This guide expects working knowledge of compile time DI in Play.

First, you’ll need to add the correct dependencies to your project definition’s settings in SBT.

import play.sbt.PlayImport._

...

.settings(
  libraryDependencies ++= Seq(
    // or whatever jdbc connector you use
    "mysql" % "mysql-connector-java" % "5.1.36",
    PlayImport.evolutions,
    PlayImport.jdbc,
    ...
  )
)

Next, you’ll want to set up the class that extends play.api.BuiltInComponentsFromContext. It will need to mix in some components that give you access to the database and the Evolutions system.

import play.api.BuiltInComponentsFromContext
import play.api.ApplicationLoader.Context
import play.api.db.{DBComponents, HikariCPComponents}
import play.api.db.evolutions.EvolutionsComponents

class AppComponents(cntx: Context)
  extends BuiltInComponentsFromContext(cntx)
  with DBComponents
  with EvolutionsComponents
  with HikariCPComponents
{
  // this will actually run the database migrations on startup
  applicationEvolutions

  // set up the model by passing in a play.api.db.Database object
  // for connections to the database
  private[this] val db = dbApi.database("default")
  private[this] val model = new AppModel(db)

  ...
}

By the way, we highly recommend using both Relate, a database query tool in Scala, and Macwire, which helps resolve dependencies in Scala.

Play’s documentation mentions EvolutionsComponents, but you’ll also need DBComponents to provide the dbApi that EvolutionsComponents needs, and mixing in HikariCPComponents will let you use Play’s default connection pooling. You’ll also have to get an instance of play.api.db.Database to pass to your models so you can get database connections.

That’s it! Now that you’ve provided a Database object to your model, you can query your databases just like the examples in Play’s documentation!

import play.api.db.Database

class AppModel(db: Database) {
  ...
  db.withConnection { connection =>
    // your query here
  }
  ...
}