0
votes

This Play for Scala method (that should return Future[play.api.mvc.Result]) invokes another method run that is a future that may throw an exception. If run doesn't throw an exception, then the method should return a Json with ret equals 0. If run does throw an exception, then the method should retun a Json with ret equals 1.

Problem is that the OnComplete is throwing a compilation error:

type mismatch; found : Unit required: scala.concurrent.Future[play.api.mvc.Result]

how to fix this?

   def test (req:Int) : Future[play.api.mvc.Result] = {

       val future = run(req)  
       future.map {
          result => 
               val json = JsObject(Seq(
                          "rs" -> Json.toJson(result),
                          "ret" -> JsString("0")
                      ))
               Ok(json)
           }

       future.onComplete { // <-- compilation error
              case Success(_) => // do nothing
              case Failure(ex) => {
                  val json = JsObject(Seq(
                         "msg" -> JsString(ex.getMessage),
                         "ret" -> JsString("1")
                    ))
                  Ok(json)
              }
            }

   }
1

1 Answers

1
votes

In Scala result of last expression in a method becomes return value of the method. future.onComplete returns a Unit, which makes function body "return" a Unit.

What you actually want is recover

def test (req:Int) : Future[play.api.mvc.Result] = {
    run(req)
        .map(result => Ok(JsObject("rs" -> ..., "ret" -> 0)))
        .recover({ case NonFatal(ex) => 
            Ok(JsObject(Seq("msg" -> ..., "ret" -> 1))
        })
}

Also, note that map returns new future, so in your example you're attaching onComplete callback to the future returned by run, which does not include that json processing; so failure in the map call will not be captured by onComplete Failure(ex) branch. As you can see I've corrected that in the snippet above.