3
votes

I have a Future[Future[Set[String]]. I flatmap it to return a Future[Set[String]]. I wait for infinity (I know this is bad) and then check if the Future is complete. It returns true. However, when I get the value returned by Future and try to add it to a Set, it doesn't add it. Statements at the end of the callback get printed first. When I return the Set from the method, it is always empty though the Future does return values. I have added comments as to explain the sequence of events happening. Please point me if I am doing something wrong! Thanks!

val googleXfpSegments = Set[String]()
val customCriteriaFuture: Future[List[Long]] = getCustomCriteriaValueIds(lineItemPage.getResults())
// getCustomCriteriaValues returns a Future[Set[String]]
val criteriaValueList = customCriteriaFuture.flatMap(criteriaIdList => getCustomCriteriaValues(criteriaIdList.toSet))
// I wait for infinite time
Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf)
log.info("Future Completed = " + criteriaValueList.isCompleted) // This returns true
criteriaValueList onComplete {
    case Success(segmentNames) => {
        // This statement gets printed after the "TEST" value gets printed
        log.info("SegmentNameList = " + segmentNames.mkString(","))
        googleXfpSegments ++= segmentNames
        // This prints nothing which means the segmentNames is not getting added
        log.info("Google Segments = " + googleXfpSegments.mkString(",")) 
    }
    case Failure(error) => log.error("Error occurred ", error)
}
googleXfpSegments += "TEST"
// This prints TEST
log.info("Google Segments = " + googleXfpSegments.mkString(",")) 

Log output is shown below:

[info] [INFO] [2014-12-09 17:25:01,147] [service.GoogleXFPService] Future Completed = true 
[info] [INFO] [2014-12-09 17:25:01,148] [service.GoogleXFPService] Google Segments = TEST 
[info] [INFO] [2014-12-09 17:25:01,148] [service.GoogleXFPService] SegmentNameList = vt.cm,vt.cp,ex.qy,ex.ahe,cm.gannett_trav
1
Where is the onComplete callback mentioned in the title? - Michael Zajac
@m-z I edited the post. It doesn't matter if I use onComplete or foreach. It still doesn't execute the Success block first. - Anand
googleXfpSegments is this a mutable Set ? - Soumya Simanta
@SoumyaSimanta nope it is an immutable set. - Anand
@Anand - not clear to me how you can reassign to `val googleXfpSegments'? - Soumya Simanta

1 Answers

5
votes

You need to assign the output of Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf) to a value. Currently you are waiting for it to complete, doing nothing with the output, then attaching an onComplete callback to an already completed future, then your program terminates before the callback can run.

val segmentNames = Await.result(criteriaValueList, scala.concurrent.duration.Duration.Inf)
log.info("Google Segments = " + segmentNames.mkString(","))