0
votes

I have an issue with Slick configuration in my Play application (Play 2.4.3). I read documentation article but want to move dbConfig from controller to specified trait and mixin this trait to repository class.

There are several files in project: ClientRepository (class), BaseClientRepository (trait) and BaseDbRepository (trait).

trait BaseDbRepository {
  val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
  import dbConfig.driver.api._

  def withConnection[T](f: => DBIOAction[T, NoStream, Nothing]) = {
    dbConfig.db.run(f)
  }
}

trait BaseClientRepository {
  def getById(id: Int): Future[Client]
  def getByLocation(location: String): Future[Seq[Client]]
}

class ClientRepository extends BaseDbRepository with BaseClientRepository {

  def getById: Future[Client] = withConnection {
    ...
  }

  def getByLocation: Future[Seq[Client]] = withConnection {
    ...
  }
}

This works great with my Client controller:

class Client extends Controller {
  def getById(id: Int) = ???
}

But when I try to use DI with Guice:

class Client @Inject()(clientRepository: BaseClientRepository) extends Controller {
  def getById(id: Int) = Action.async {
    // I try to use client repository here
  }
}

It failes with the following exception CreationException: Unable to create injector, see the following errors:

1) An exception was caught and reported. Message: There is no started application at com.google.inject.util.Modules$OverrideModule.configure(Modules.java:177)

I tried to move this definition val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current) into Global.scala and it just works, but as I now Global.scala is deprecated now.

So, where is the best place for it?

Update: I use injection module for DI configuration:

class InjectionModule extends AbstractModule {
  def configure() {
    bind(classOf[BaseClientRepository]).toInstance(new ClientRepository)
  }
}
2

2 Answers

1
votes

dbConfig should be a lazy val or a function in this case. That works for me:

private lazy val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
0
votes

Guice failed to inject an implementation of BaseClientRepository, the annotation @ImplementedBy can help.

@ImplementedBy(classOf[ClientRepository])
trait BaseClientRepository {
   def getById(id: Int): Future[Client]
   def getByLocation(location: String): Future[Seq[Client]]
}