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
  }
  ...
}

Mark Siebert

Author Bio

Mark is a full-stack engineer who cut his teeth on professional software development at Lucid Software where he specialized in building scalable backend systems. He's a huge fan of open source software and is one of the primary authors of Relate (database access library) and Cumulus (AWS infrastructure management). Mark loves watching shows with his wife, studying Chinese, and hunting Minecraft chickens.