Using play-slick and slick-codegen

slick

(Julian Wilson) #1

Hi,

Not sure if this is the right place for this or slick, but essentially I’m trying to leverage slick-codegen to produce some models for my schema and also use play-slick to provide my service/DAO classes with the correct database. The issue I’m having is that mixing in both HasDatabaseConfigProvider and the Tables has some access privileges problems. It seems like HasDatabaseConfig creates a protected final lazy profile:

  protected final lazy val profile: P = dbConfig.profile // field is lazy to avoid early initializer problems.

but the Tables trait from slick-codegen has a public profile:

trait Tables {
  val profile: utils.MyPostgresProfile
...

How can I get play-slick and slick-codgen to play nicely together? Essentially I am wondering if this example


can be modified to work with play-slick.

Thanks


(Will Sargent) #2

The evil but fun way to do it would be to monkeypatch the field using setAccessible https://tersesystems.com/blog/2014/03/02/monkeypatching-java-classes/ – but I understand why you wouldn’t want to do that.

The Play way to do it would be to inject the profile or the dbConfig as a provider into a singleton component that instantiated a slick-codegen class and executed on it. You would bind in the Module class using asEagerSingleton().

https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection#Singletons


(Julian Wilson) #3

Thanks for the pointers. I ended up doing simply the following. Seems to work pretty well

class Service @Inject()(
    @NamedDatabase("db") protected val dbConfigProvider: DatabaseConfigProvider,
    implicit val ec: ExecutionContext)
    extends HasDatabaseConfigProvider[PostgresProfile]{

  import profile.api._

    def getUser(userId: Int): Future[List[String]] = {
    db.run(Tables.User.filter(_.userId === userId).result map {
      resultOption =>
        resultOption.map(toModel).map(_.id)
    })
  }