Как получить элемент объектов в akka actor scala - PullRequest
0 голосов
/ 11 февраля 2020

Я новичок в Акке и scala. У меня есть API, который возвращает класс POJO. Примерно так

pathPrefix("dataprofile") {
          get {
            ctx =>
              (sActor ? GetDataAccessProfileByUserAndAccount(account, user)).mapTo[Either[Rejection, DataAccessProfile]] map {
                case Left(x) => ctx.reject(x)
                case Right(x) => ctx.complete(x)
              }

          }
        } ~

Теперь я хочу использовать этот sActor в каком-то другом API и использовать два элемента (List и String) из DataAccessProfile. И после получения этих двух элементов я хочу установить его в CompleteInput. Я написал что-то вроде

pathPrefix("complete") {
          post {
            entity(as[CompleteInput]) { completeInput =>
              complete {
                var session = user.username.get + "_" + account.id.get
                var uNameAccountId = user.username.get +"|" + account.id.get
                if(jwt_token == null || !validateJwt(jwt_token)){
                  jwt_token = encodeJwt(uNameAccountId)
                }
                val result =  (sActor ? GetDataAccessProfileByUserAndAccount(account, user)).mapTo[Either[Rejection, DataAccessProfile]]
                implicit val timeout = Timeout(2 seconds)
                DataAccessProfile future = (DataAccessProfile) Await.result(result, timeout.duration)
                println(future.studyIds)

                autoCompleteService(session,jwt_token,completeInput)
              }
            }
          }
        } ~

Я получаю сообщение об ошибке "; ' но нашел "." Мой вопрос заключается в том, как мы можем извлечь элемент (ы) из sActor или любого другого решения

Теперь я попробовал это:

val future2: Future[DataAccessProfile] = (sActor ? GetDataAccessProfileByUserAndAccount(account, user)).mapTo[DataAccessProfile]
implicit val timeout = Timeout(2 seconds)
val result = Await.result(future2, timeout.duration)
println("---------------------------" +result)

Это исключение времени выполнения, говорящее об исключении java .lang. ClassCastException: Невозможно привести scala .util.Right к com.comprehend.protobuf.rba c .DataAccessProfile

1 Ответ

0 голосов
/ 11 февраля 2020

Я думаю, вы получили ошибку компиляции по адресу:

DataAccessProfile future = (DataAccessProfile) Await.result(result, timeout.duration)

это выглядит как более Java объявление стиля, но поскольку вы пишете на Scala, оно должно выглядеть так:

val future: DataAccessProfile = Await.result(result, timeout.duration).get.asInstanceOf[DataAccessProfile]

Но у этого решения есть ряд проблем: оно блокирует, потому что использует await, и небезопасно, потому что Await.result и Either.get могут выдавать ошибки, поэтому их нужно правильно обрабатывать. Я предлагаю вам взглянуть поближе на эту страницу: https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onComplete.html

И, возможно, реализовать что-то вроде:

 onComplete(result) {
      case Success(Right(profile)) => autoCompleteService(session, jwt_token, completeInput)
      case Success(Left(rejection)) => complete((InternalServerError, "Message was rejected - specify error details here"))
      case Failure(ex)    => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
    }

ОБНОВЛЕНИЕ # 1 : итоговое решение будет выглядеть так:

pathPrefix("complete") {
  post {
    entity(as[CompleteInput]) { completeInput =>
        val session = user.username.get + "_" + account.id.get
        val uNameAccountId = user.username.get +"|" + account.id.get
        if(jwt_token == null || !validateJwt(jwt_token)){
          jwt_token = encodeJwt(uNameAccountId)
        }

        val result =  (sActor ? GetDataAccessProfileByUserAndAccount(account, user)).mapTo[Either[Rejection, DataAccessProfile]]

        onComplete(result) {
          case Success(Right(profile)) =>
            println(future.studyIds)
            autoCompleteService(session, jwt_token, completeInput)

          case Success(Left(rejection)) =>
            complete((InternalServerError, "Message was rejected - specify error details here"))

          case Failure(ex) =>
            complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
        }
    }
  }
} ~

ОБНОВЛЕНИЕ # 2 : Согласно вашему последнему обновлению я удалил Either использование:

pathPrefix("complete") {
  post {
    entity(as[CompleteInput]) { completeInput =>
        val session = user.username.get + "_" + account.id.get
        val uNameAccountId = user.username.get +"|" + account.id.get
        if(jwt_token == null || !validateJwt(jwt_token)){
          jwt_token = encodeJwt(uNameAccountId)
        }

        val result: Future[DataAccessProfile] = (sActor ? GetDataAccessProfileByUserAndAccount(account, user)).mapTo[DataAccessProfile]

        onComplete(result) {
          case Success(profile) =>
            println(future.studyIds)
            val updatedInput = completeInput.copy(dataAccessControl = JavaConversions.seqAsJavaList(list2))
            autoCompleteService(session, jwt_token, updatedInput)

          case Failure(ex) =>
            complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
        }
    }
  }
} ~

Надеюсь, это поможет!

...