11
votes

I have a Try that throws Exception. I want that Try to become a Future so I will be able to recoverWith.

How can I convert the Try into a Future without handling any exceptions in the Try (just in the Future with recover)?

note that Await is needed to test the result of your future

The code sample demonstrates what I had in mind but it also throws once reached (new RuntimeException("-------failed-------") is what I get)

val t = Try(throw new RuntimeException("my"))

val resF : Future[String] = if (t.isSuccess)
  Future.successful(t.get)
else
  Future.failed(new RuntimeException("-------failed-------"))

val resFWithRecover = resF.recoverWith{
  case NonFatal(e) =>
    Future.successful("recoveredWith")
}
Await.result(resFWithRecover, Duration("5s"))
4

4 Answers

24
votes

... how do convert Try to Future without handling any exception in the Try?

Use Future.fromTry.

scala> val t = Try(throw new RuntimeException("my"))
t: scala.util.Try[Nothing] = Failure(java.lang.RuntimeException: my)

scala> val resF = Future.fromTry(t)
resF: scala.concurrent.Future[Nothing] = scala.concurrent.impl.Promise$KeptPromise@57cf54e1

scala> resF.recoverWith{
     |   case NonFatal(e) =>
     |     Future.successful("recoveredWith")
     | }
res5: scala.concurrent.Future[String] = scala.concurrent.impl.Promise$DefaultPromise@1b75c2e3
1
votes

There's no need to introduce Future if all you want to do is to use recoverWith (kind of like flatMap) on your Try object.

You could so something like the following:

val t = Try[String](throw new RuntimeException("my"))
val u = t.recoverWith{
  case e => Success(s"ignoring exception ${e.getLocalizedMessage}")
}
u.foreach(println(_))

This results in the following output to the console:

ignoring exception my
1
votes
 // you need to provide your try with type information in lhs
 // as the rhs is not providing any type info
 val t: Try[String] = Try(throw new RuntimeException("my"))

 // Now you can easily get a Future[String] from this Try[String]
 val f = Future.fromTry(t)

 // or you can use pattern matching
 val f2 = t match {
   case Success(str) => Future.succesful(str)
   case Failure(ex) => Future.failed(ex)
 }
0
votes

You can recoverWith on Try also

Use map and recover methods on Try to produce Future.successful and Future.failed respectively and then get on Try

val future = 
 Try {
   throw new Exception("explosion")
 }.map { result =>
   Future.successful(result)
 }.recover { case th =>
   Future.failed(th)
 }.get

Using Pattern Matching

val future =  
 Try {
  throw new Exception("something")
 } match {
  case Success(value) => Future.successful(value)
  case Failure(th) => Future.failed(th)
 }