kliew
kliew

Reputation: 3183

Scala Play Future[Response] always empty

The Future[Response].value: Option[Try[Response]] is always empty. Am I misunderstanding Futures? Do I need to wrap this in an onSuccess? But then it won't return a String, but a Unit?

@tailrec private def initConnection: String =
  {
    val response: Future[Response] = initHeaders(WS.url(url)).post(authBody)
    val retry: Boolean = {
      response.value.isEmpty || response.value.get.isFailure || response.value.get.get.header("ConnectionID").isEmpty
    }

    if (!retry) return response.value.get.get.header("ConnectionID").get
    else initConnection
  }

Upvotes: 0

Views: 494

Answers (1)

knutwalker
knutwalker

Reputation: 5974

Future#value does not block on the future. If the future is already completed at the time of calling value, you will get Some(_), otherwise it will be None. So you see only None since you check the value immediately after sending the request and it hasn't finished yet. You can use future combinators like collect and recoverWith to implement the retry functionality and return a Future[String] instead of a String. If you really need the value later, you will have to Await.result the future.

import scala.util.control.NonFatal
import scala.concurrent.Await

private def initConnectionFuture: Future[String] =
  initHeaders(WS.url(url)).post(authBody).collect {
    case response if response.header("ConnectionID").isDefined =>
      response.header("ConnectionID").get
  }.recoverWith {
    case NonFatal(_) => initConnectionFuture
  }

private def initConnection: String =
  Await.result(initConnectionFuture, 5 seconds) // or any other acceptable timeout

In addition to the timeout, you might also want to limit the number of retries, e.g.

private def initConnectionFuture(retries: Int = 5): Future[String] =
  initHeaders(WS.url(url)).post(authBody).collect {
    case response if response.header("ConnectionID").isDefined =>
      response.header("ConnectionID").get
  }.recoverWith {
    case NonFatal(_) if retries > 0 => initConnectionFuture(retries - 1)
  }

Upvotes: 2

Related Questions