Reputation: 15579
When using some code like the following:
scala> Future { null } onComplete { case Success(v) => v.toString }
Scala throws the following exception:
scala> java.lang.NullPointerException
at $line14.$read$$iw$$iw$$anonfun$2.apply(<console>:11)
at $line14.$read$$iw$$iw$$anonfun$2.apply(<console>:11)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
This would be OK, since I am not handling any exceptions. The problem is that my application hangs completely.
I am using concurrent.ExecutionContext.Implicits.global
and I think onComplete
is executed in this global execution context. The problem is that it seems like the execution context stops accepting any work and and the application just hangs.
Do I have to explicitly use try ... catch
so that I protect my app in case something unexpected happens in onComplete
?
Thank you
Upvotes: 1
Views: 1554
Reputation: 18746
First of all, the NullPointerException
you get has nothing to do with the future; it does not happen inside the Future
block.
What you can do, is wrapping code that might return null
in Option()
.
Your code would then look like this:
Future { Option(mightBeANull) } onComplete { case Success(v) => v.map(_.toString) }
Upvotes: 0
Reputation: 39587
IIRC, this was an issue only in the very earliest implementation.
You can supply a handler or "reporter":
scala> import util._
import util._
scala> import concurrent._
import concurrent._
scala> ExecutionContext.fromExecutor(null, (t: Throwable) => println(s"Hi, $t"))
res0: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@221a3fa4
scala> implicit val x = res0
x: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@221a3fa4
scala> Future { null } onComplete { case Success(v) => v.toString }
<console>:16: warning: match may not be exhaustive.
It would fail on the following input: Failure(_)
Future { null } onComplete { case Success(v) => v.toString }
^
Hi, java.lang.NullPointerException
scala>
Everything is handled.
Upvotes: 3