1
votes

Consider the below code:

class TestActor extends Actor {
  def receive = {

    case "hello" => 
      sender ! Future {
        "Sample future result"
      }
  }
}

I have the below route defined:

def r5: Route = {
    pathPrefix("check") {
      onSuccess(system.actorOf(Props[TestActor]).ask("hello")) {
        successResult =>
          complete {
            "The result is " + successResult
          }
      }
    }
  }

When I access the route, I get the output as The result is Success(Sample future result) while I expected it to be The result is Sample future result. From the docs here about onSuccess:

Evaluates its parameter of type Future[T], and once the Future has been completed successfully, extracts its result as a value of type T and passes it to the inner route.

and the example given is:

val route =
  path("success") {
    onSuccess(Future { "Ok" }) { extraction =>
      complete(extraction)
    }
  }

So where am I going wrong?

2

2 Answers

2
votes

ask returns a Future[T]. Your pattern match handler inside receive wraps it in an additional Future[T], so you're getting a Future[Future[String]].

If you want to only retrieve T, remove the Future from your TestActor:

case class TestResult(s: String)
case "hello" => 
  sender ! TestResult("Sample future result")
0
votes

If the use of ask is inevitable then in the onComplete in r5 route you need to open the future twice as you are receiving a Future[Future[String]].

The on Complete will unwrap one and you can have

  def r5: Route = {
    pathPrefix("check") {
      onSuccess(system.actorOf(Props[TestActor]).ask("hello")) {
        successResult => { 
                 successResult.Oncomplete {
                      case Success(res) => {
                                complete {
                                      "The result is " + res //res will have Sample Future Result }
                      case Failure(ex) => complete("Some Error Occured")
        
      }
    }
  }