ozma
ozma

Reputation: 1803

Convert Try to Future and recoverWith as Future

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"))

Upvotes: 11

Views: 16282

Answers (5)

Datanova Scientific
Datanova Scientific

Reputation: 59

Future.fromTry will run the Try code synchronously. From the documentation:

Creates an already completed Future with the specified result or exception.

Since your interface relies on Future, you may want to to run the Try itself asynchronously. This will be more efficient for most use cases. You can do it like this:

val f = Future { 
  val t = Try(...)
  t match {
    case Success(value) => value
    case Failure(exception) => throw exception
  }
}

f.recoverWith{...}

Upvotes: 0

sarveshseri
sarveshseri

Reputation: 13985

 // 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)
 }

Upvotes: 1

Phasmid
Phasmid

Reputation: 953

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

Upvotes: 1

Michael Zajac
Michael Zajac

Reputation: 55569

... 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

Upvotes: 25

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

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)
 }

Upvotes: 0

Related Questions