Arnold Overwater
Arnold Overwater

Reputation: 43

Scala Play Framework Slick session doesn't work

I'm trying a simple test application with Slick and the Play2 Framework, but the compiler keeps complaining the implicit session cannot be inferred.

Here is my Build.scala:

import sbt._
import Keys._
import play.Project._

object ApplicationBuild extends Build {

  val appName         = "dummy"
  val appVersion      = "1.0"

  val appDependencies = Seq(
    jdbc,
    "mysql" % "mysql-connector-java" % "5.1.26",
    "com.typesafe.slick" %% "slick" % "1.0.1"
  )


  val main = play.Project(appName, appVersion, appDependencies).settings(
    // Add your own project settings here      
  )

}

And this is my Global singleton that holds my database connections:

package models

import play.api.Play.current
import play.api.db.DB
import slick.session.Session
import slick.driver.MySQLDriver.simple._
import scala.slick.session.Database.threadLocalSession


object Global {

  lazy val database = Database.forDataSource(DB.getDataSource())

  lazy val session = database.createSession()

}

And my controller:

package controllers

import scala.language.implicitConversions
import play.api._
import play.api.mvc._
import models.Global.session

import slick.driver.MySQLDriver.simple._

object Application extends Controller {

  def index = Action {
    /*slick.driver.MySQLDriver.simple.*/Query(Foo).foreach( _ => () ) // Do nothing for now
    Ok(views.html.index("hola"))
  }

  object Foo extends Table[(Long, String, String)]("Foo") {
    def * = column[Long]("id") ~ column[String]("bar1") ~ column[String]("bar2")
  }

}

As you can see my Global.session val is imported, but it keeps saying no implicit session was found.

Upvotes: 4

Views: 1787

Answers (1)

arussinov
arussinov

Reputation: 1237

To make queries you need two things: connection to the database and a session, so your problem is how you define and use them. With Database.threadLocalSession in scope, you can make your queries like this :

Database.forURL("jdbc:h2:mem:play", driver = "org.h2.Driver") withSession {
          //create table
          Foo.ddl.create
          //insert data
          Foo.insert((1.toLong,"foo","bar"))
          //get data
          val data : (Long,String,String) = (for{f<-Foo}yield(f)).first
}

or you can do it like this:

val database  = Database.forDataSource(DB.getDataSource())
 database.withSession{ implicit session : Session =>
          Foo.ddl.create
          Foo.insert((1.toLong,"foo","bar"))
          val data : (Long,String,String) = (for{f<-Foo}yield(f)).first
}

I have create a test and it works fine, you can play with it:

"Foo should be creatable " in {
  running(FakeApplication(additionalConfiguration = inMemoryDatabase())) {
    val database  = Database.forDataSource(DB.getDataSource())
    database.withSession{ implicit session : Session =>
      Foo.ddl.create
      Foo.insert((1.toLong,"foo","bar"))
      val data : (Long,String,String) = (for{f<-Foo}yield(f)).first

      data._1 must equalTo(1)
    }
  }
}

Also you may look at here

Upvotes: 4

Related Questions