When an exception
is thrown from within a Future
, you can (should) use recover
to handle it.
For instance,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
...will throw an Exception
from within the Future
. But seeing as we can predict that an Exception
of type FairlyStupidException
with a high probability, we can specifically handle this case in an elegant way:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
As you can see the method given to recover
is a PartialFunction
over the domain of all Throwable
, so you can handle just a certain few types and then let the rest go into the ether of exception handling at higher levels in the Future
stack.
Note that this is similar to running the following code in a non-Future
context:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
It is really important to handle exceptions generated within Future
s because much of the time they are more insidious. They don't get all in your face usually, because they run in a different execution context and thread, and thus do not prompt you to fix them when they happen, especially if you don't notice anything in logs or the behavior of the application.