Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle an exception that happens in a future in scala

I'm writing a controller method in play framework that calls a function that returns a Future that may also throw an Exception. I'm having trouble figuring out how to catch and handle that Exception.

Here's what I tried:

  def openIDCallback = Action { implicit request =>
    Async (
      Try(OpenID.verifiedId) match {
        case Failure(thrown) => {
          PurePromise(Ok("failed: " + thrown))
        }
        case Success(successResult) => {
          successResult.map( userInfo => {
            Ok(userInfo.id + "\n" + userInfo.attributes)
          })
        }
      }
    )
  }

OpenID.verifiedId is the function from Play's OpenId api that returns Future[UserInfo]. Here's the source of that function:

def verifiedId(queryString: Map[String, Seq[String]]): Future[UserInfo] = {
    (queryString.get("openid.mode").flatMap(_.headOption),
      queryString.get("openid.claimed_id").flatMap(_.headOption)) match { // The Claimed Identifier. "openid.claimed_id" and "openid.identity" SHALL be either both present or both absent.
      case (Some("id_res"), Some(id)) => {
        // MUST perform discovery on the claimedId to resolve the op_endpoint.
        val server: Future[OpenIDServer] = discovery.discoverServer(id)
        server.flatMap(directVerification(queryString))(internalContext)
      }
      case (Some("cancel"), _) => PurePromise(throw Errors.AUTH_CANCEL)
      case _ => PurePromise(throw Errors.BAD_RESPONSE)
    }
  }

As shown above, function can return PurePromise(throw Errors.AUTH_CANCEL) and PurePromise(throw Errors.BAD_RESPONSE). My attempt at solution handles successes correctly, but on exceptions I get:

play.api.Application$$anon$1: Execution exception[[AUTH_CANCEL$: null]]

My question is how do I catch and handle these exceptions in my controller method?

like image 828
Krešimir Nesek Avatar asked Sep 29 '13 12:09

Krešimir Nesek


People also ask

How do you handle Future Scala?

Handle the result of a future with methods like onComplete , or combinator methods like map , flatMap , filter , andThen , etc. The value in a Future is always an instance of one of the Try types: Success or Failure.

How do you handle exceptions in Scala?

However, Scala doesn't actually have checked exceptions. When you want to handle exceptions, you use a try{...} catch{...} block like you would in Java except that the catch block uses matching to identify and handle the exceptions.

What is Future and promise in Scala?

The Promise is a writable, single-assignment container that completes a Future. The Promise is similar to the Future. However, the Future is about the read-side of an asynchronous operation, while the Promise is about the write-side.

What is await result in Scala?

Await. result tries to return the Future result as soon as possible and throws an exception if the Future fails with an exception while Await. ready returns the completed Future from which the result (Success or Failure) can safely be extracted.


1 Answers

You should use recover method of Future instead of Try like this:

Async (
  OpenID.verifiedId.
    map{userInfo => Ok(userInfo.id + "\n" + userInfo.attributes)}.
    recover{ case thrown => Ok("failed: " + thrown) }
)

Try can help you in case verifiedId throws an exception instead of returning Future. In your case verifiedId successfully returns Future (even if there will be an exception in this Future).

like image 184
senia Avatar answered Sep 23 '22 13:09

senia