Как правильно привязать черту к ее значению, если у последней есть неявные параметры
[Пожалуйста, прости меня за длинный вопрос, я все еще учусь Скале.]
Я пытаюсь связать универсальный признак с его обобщенным impl, который имеет неявные параметры. Вот код очистки:
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)
}
}
}
Я использую Play, ReactiveMongo и ScalaGuice (все последние версии). Итак, вот мой основной класс 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
}
}
И скажем, у меня есть один из моих контроллеров с зависимостью от PersistenceService, например:
class PersistenceServiceController @Inject()(val PersistenceService: PersistenceService[Bar], cc ControllerComponents) extends AbstractController(cc) { ... }
И модель (как вы, вероятно, можете догадаться) с ее последствиями Reader/Writer:
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 = { ... }
}
}
Со всеми этими вещами я получаю следующее исключение во время выполнения:
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)
Ясно, что вещи, которые мой класс MongoPersistenceService должен получить в контексте выполнения, кое-как упускают. Я понимаю, что Play как бы волшебным образом обеспечивает контекст выполнения, когда вы правильно настраиваете свои вещи с помощью guice. Но в этом случае, похоже, это не работает.
Как я могу это исправить?
1 ответ
Ну, я чувствую себя плохо об этом, но сообщение об ошибке было довольно очевидно, чтобы найти проблему. Чтобы это исправить, мне пришлось вручную связать импл для BSONDocumentReader[Bar]
, BSONDocumentWriter[Bar]
а также ClassTag[Bar]
,
С тех пор я реорганизовал свой код в нечто гораздо более простое. Но хотел сообщить другим людям, в чем была проблема.