Как правильно привязать черту к ее значению, если у последней есть неявные параметры

[Пожалуйста, прости меня за длинный вопрос, я все еще учусь Скале.]

Я пытаюсь связать универсальный признак с его обобщенным 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],

С тех пор я реорганизовал свой код в нечто гораздо более простое. Но хотел сообщить другим людям, в чем была проблема.

Другие вопросы по тегам