Tuesday, August 30, 2016

Dependancy Injection and Anorm

Moving from Play Framework 2.4.x to 2.5.x requires to drop global variables. Specifically in this case play.api.Play.current and play.api.db.DB.

Most of my models using Anorm have a simple form:
case class Model(id:Long, name:String, …)

case object Model {
  val model=get[Long]("id")~get[String]("name")~ … map {
    case id~name~ … => Model(id, name, …)
  }
  def findById(id:Long):Option[Model]=DB.withConnection { implicit c=>
    SQL"SELECT * FROM models WHERE modelId=$id".as(model*).headOption
  }
}

In 2.5.x, DB is now deprecated. It is recommended to use dependancy injection.
Here's a minimum to support 2.5.x:
1. Instead of changing much (such as not using a case object), change DB to implicit.
    def findById(id:Long)(implicit db:Database):Option[Model]=db.withConnection { implicit c=>
       SQL"SELECT * FROM models WHERE modelId=$id".as(model*).headOption
    }  

2. For every controller using models, add @Inject()(db: Database), e.g., 
       class Application @Inject()(db: Database) extends Controller {
          implicit val dbImplicitVal=db

3. For every AKKA actor using models, add (db:Database), e.g., 
      class Logger(db:Database) extends Actor {
     and by calling props with a valid database when requesting an actor, e.g., 
       val logger=actorSystem.actorOf(Props(new Logger(db)))

Simple and minimal.





No comments:

Post a Comment