My application uses Play 2.4 with Scala 2.11 .I started transforming my existing code to make use of Google Guice that comes with Play 2.4 .
When I run my code after making the first set of changes , I found Some DAOs in my code are failing with circular dependency error.
For example I have two DAOs
class BookDAO @Inject()
(protected val personDAO : PersonDAO,
@NamedDatabase("mysql")protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
...
...
val personId = //some id
personDAO.get(personId)
}
class PersonDAO @Inject()
(protected val bookDAO : BookDAO,
@NamedDatabase("mysql")protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
...
...
val bookName= //some id
personDAO.getByName(bookName)
}
I got the below error while trying to access either BookDAO or PersonDAO
Tried proxying schema.BookDAO to support a circular dependency, but it is not an interface.
at schema.BookDAO.class(Books.scala:52)
while locating schema.BookDAO
Can someone help me resolving this error .
Thanks in advance
答案 0 :(得分:4)
Inject a Provider
instead:
class BookDAO @Inject()(personDaoProvider: Provider[PersonDAO], ...)
extends HasDatabaseConfigProvider[JdbcProfile] {
val personDAO = personDaoProvider.get
def person = personDAO.get(personId)
}
And the same for BookDAO
. This will work out of the box. Guice already "knows" how to inject Providers.
Decouple the class definition from the implementation. See Mon Calamari's answer.
答案 1 :(得分:2)
Define your dependencies as follows and pull up all needed methods from class to trait:
@ImplementedBy(classOf[BookDao])
trait IBookDao {
// abstract defs
}
class BookDao @Inject()(protected val personDAO: IPersonDao, protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] with IBookDao {
}
@ImplementedBy(classOf[PersonDao])
trait IPersonDao {
// abstract defs
}
class PersonDao @Inject()(protected val bookDAO: IBookDao, protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] with IPersonDao {
}
As you can see, each dao
implements a trait and all dao
dependencies are injected by trait
. This gives Guice
possibility to inject a proxy class and resolve a circular dependency issue.
More details on playframework scala
dependency injection here.