2017-07-16 3 views
0

[S'il vous plaît pardonnez-moi pour la longue question, je suis encore à apprendre à Scala.]Comment lier correctement un trait à son impl lorsque l'on a plus tard paramètres implicites

J'essaie de lier un trait générique à son impl générique qui a des paramètres implicites. Voici le code de nettoyage:

trait PersistenceService[T <: SomeOtherClass] { 
    def persist(record: T): Future[Unit] 
} 

class MongoPersistenceService[T <: SomeOtherClass] @Inject()(implicit ec: ExecutionContext, tag: ClassTag[T]) extends PersistenceService[T] { 
    val collectionName: String = tag.runtimeClass.getSimpleName 
    val databaseName = "someDatabase" 

    def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017") 
           .flatMap(_.database(databaseName)) 

    def collection: Future[BSONCollection] = db.map(_.collection(collectionName)) 

    def persist(record: T): Future[Unit] = { 
    val result = for { 
     col <- collection 
     writeResult <- col.insert(record) 
    } yield writeResult 
    result.recoverWith { 
         case WriteResult.Code(11000) => throw RecordAlreadyExistsException(record, 
                          "") 
         }.map(_ =>()) 
    } 

    def read(id: BSONObjectID): Future[T] = { 
    val query = BSONDocument("_id" -> id) 
    val readResult: Future[T] = for { 
     coll <- collection 
     record <- coll.find(query).requireOne[T] 
    } yield record 

    readResult.recoverWith { 
          case NoSuchResultException => throw RecordNotFoundException(id) 
          } 
    } 
} 

J'utilise Play, ReactiveMongo et ScalaGuice (toutes les dernières versions). Alors, voici ma principale tout de liaison de classe Module:

class Module(env: Environment, config: Configuration) extends AbstractModule with ScalaModule { 
    def configure(): Unit = { 
    bind[PersistenceService[_]].to[MongoPersistenceService[_]] // Also tried with specific class instead of _ but not working either 
    } 
} 

Et disons que j'ai un de mon contrôleur avec dépendance PersistenceService comme ceci:

class PersistenceServiceController @Inject()(val PersistenceService: PersistenceService[Bar], cc ControllerComponents) extends AbstractController(cc) { ... } 

Et le modèle (comme vous pouvez probablement le deviner) avec son implicits lecteur/enregistreur:

case class Bar() extends SomeOtherClass() {} 
object Bar { 
    implicit object BarReader extends BSONDocumentReader[Bar] { 
    def read(doc: BSONDocument): Bar = { ... } 
    } 
    implicit object BarWriter extends BSONDocumentWriter[Bar] { 
    def write(bar: Bar): BSONDocument = { ... } 
    } 
} 

Avec toutes ces étoffes, je commence à l'exception d'exécution suivantes:

com.google.inject.CreationException: Unable to create injector, see the following errors: 
1) No implementation for reactivemongo.bson.BSONDocumentReader<Bar> was bound. 
    while locating reactivemongo.bson.BSONDocumentReader<Bar> 
    for the 2nd parameter of MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 
2) No implementation for reactivemongo.bson.BSONDocumentWriter<Bar> was bound. 
    while locating reactivemongo.bson.BSONDocumentWriter<Bar> 
    for the 3rd parameter of persistence.MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 
3) No implementation for scala.reflect.ClassTag<Bar> was bound. 
    while locating scala.reflect.ClassTag<Bar> 
    for the 5th parameter of MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 

Donc, clairement, les choses que ma classe MongoPersistenceService devrait obtenir dans le contexte d'exécution manquent comment. Je comprends que Play est un peu magique fournissant le contexte d'exécution lorsque vous configurez vos affaires correctement avec guice. Mais dans ce cas, on dirait que ça ne marche pas.

Comment puis-je résoudre ce problème?

Répondre

0

Eh bien, je me sens mal à propos de celui-ci, mais le message d'erreur était assez évident pour trouver le problème. Pour le réparer, j'ai dû lier manuellement un impl pour BSONDocumentReader[Bar], BSONDocumentWriter[Bar] et ClassTag[Bar].

J'ai depuis refactorisé mon code à quelque chose de beaucoup plus simple. Mais voulait faire savoir aux autres quel était le problème.