Question

Just trying to get my first futures use up and running and doing a test similar to an example outlined in the Akka in Action MEAP book. I want to call a web service and return the result in a future. I am using scalaxb to access the web service. I have outlined the code below but when I run it the app terminates without waiting for the response from the service. Maybe someone can tell me what I am missing?

import scala.util._
import control.NonFatal
import scala.concurrent._
import ExecutionContext.Implicits.global

object Test {


    val service = (new MyServiceBindings with scalaxb.Soap11Clients with scalaxb.DispatchHttpClients {}).service

    def test = {

        val f = future {

            service.someCall() match {
                case Right(resp) => resp
                case Left(fault) => throw new Exception("Fault: " + fault)}
            }
        }

        f.onComplete {
            case Success(resp) => println("Resp: " + resp)
            case Failure(NonFatal(e)) => println("Fail: " + e)
        }
    }

    def main(args: Array[String]): Unit = {
        test
    }
}
Was it helpful?

Solution

It terminates because the main thread that is executed inside your Test has completed. The threads that are used internally by the Dispatch library don't keep the program from exiting.

You would need to wait on the future since this is the only thing your test app is doing. Put this after the onComplete statement.

import scala.concurrent.duration._ Await.ready(f, 10.seconds)

Now bear in mind that this is bad practice usually. You need it here because your test app is doing nothing else, but in a real app, you wouldn't want to block after each futures call, as that would negate the point of using futures.

OTHER TIPS

You can patch this in the main funtion by adding the following logic to your test application:

def main(args: Array[String]) :  Unit = {

  // Assuming test is a future that did not complete yet.
  while(!test.isCompleted) { 
       Thread.sleep(100) 
  }
  // Software exits here only after future is completed.  
}

Or Better if you have many futures you can implement it this way:

// Assuming you have --> listOfFutures = ArrayBuffer[Future]

def main(args: Array[String]) : Unit = {
   while(!listOfFutures.isEmpty) {
      listOfFutures.foreach {
         future =>
          if(future.isCompleted) {
             listOfFutures -= future
          }
      }
      //checks which futures are completed every half-a-second
      Thread.sleep(500) 
   }
   // Program exits after all futures have been completed.
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top