Reputation: 95
Any idea why the code below can handle the Success
without any issues, but when trying to return a Failure
ends up throwing an Exception
?
Exception in thread "main" au.com.ingdirect.splunk.Implicits.package$LameExcuse: hello at au.com.ingdirect.splunk.Implicits.package$RichJob$$anonfun$asFuture$1.apply(package.scala:42) at au.com.ingdirect.splunk.Implicits.package$RichJob$$anonfun$asFuture$1.apply(package.scala:36) at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
This is my code:
/* --- Main.scala --- */
import test.Implicits._
val job = service.createJob("search immediatePayment", queryArgs)
Await.result(job, 10 seconds)
job.onComplete{
case Success(j) => println("Success!!")
case Failure(l: LameExcuse) => println("Why I never fall here?")
}
/* --- package.scala ---*/
package object Implicits {
implicit val executorService = Executors.newFixedThreadPool(4)
implicit val executionContext = ExecutionContext.fromExecutorService(executorService)
case class LameExcuse(msg: String) extends Exception(msg)
implicit class RichJob(val job: Job) {
def asFuture(): Future[Job] = {
// I promise i will return a completed Job
val p = Promise[Job]()
val fail = false
// ... and here i am
future {
while (!job.isDone()) {
Thread.sleep(1000)
}
if (fail)
p failure (new LameExcuse("Service unavailable")) //<-- This will print the stacktrace on the console, but it will not send a Failure
else
p success job //<-- This works fine
}
p.future
}
}
Thanks
Upvotes: 0
Views: 193
Reputation: 35463
I think part of your issue is that in Main.scala, you are first performing a blocking Await.result
before you register your non-blocking onComplete
callback. With Await.result
, if the Future
is failed, whatever exception the Failure
is wrapping will be thrown all the way out. So, in your case, if the Future
is failed, you will never get to the code where you register the onComplete
callback. If you remove the Await.result
, things should work as expected for you, more gracefully failing and hitting your Failure
case in the onComplete
callback.
In addition, in asFuture
, I'm not sure why you need that Promise
. You already created a Future
and can just return that as opposed to using a Promise
. Your code could be simplified to:
def asFuture(): Future[Job] = {
val fail = false
future {
while (!job.isDone()) {
Thread.sleep(1000)
}
if (fail)
throw new LameExcuse("Service unavailable")
job
}
}
Upvotes: 2