Playframework: staying in the async monad Subscribe

You know that the Play framework is massively asynchronous, where you do not really compute values, but create Action(s) which will be invoked later to create the actual response.

I had an issue recently trying to compose actions... basically a simple logic dictated if I had a result right now or I had to delegate to another action.

Good luck doing that - it's not as straight forward as it seems.

So, without further ado, if you just call a method returning a simple action, you just apply() it and return the resulting Future:

  def asyncStuff () = Action.async { implicit request =>
    if(some result up front)
       Future.successful(Redirect("someone/else"))
    else  // later => return the future
       syncStuff(request)
    }

  def syncStuff () = Action { implicit request =>
     Ok("hello")
    }

As you can see, if the internal result is another Action, I am calling it and propagating the result to the current action. But if you switch from Action {} builder to the Action.async{} builder, all results must become Future[SimpleResult] instead, so you have to wrap results yo have up-front into a Future, with Future.successful.

This is play 2.2.2 ... I'm still reeling from upgrading my Bootstrap, so moving to play 2.3 will wait a bit.

Enjoy!

Screwier case

This the quasi-synchronous piece that what I had before:

  def bigSecurityHole (j: String, lang: String) = Action { implicit request =>
    val (_,res) = dynamicBlock (j, lang)(request,au)
    Ok(res.toString)
    }

This is the async bit that I ended up with:

  def bigSecurityHole (j: String, lang: String) = Action.async { implicit request =>
    val (_,res) = dynamicBlock (j, lang)(request,au)

    // special stuff for calling actions, if the j delegates
    if(res.isInstanceOf[Action[_]])
       res.asInstanceOf[Action[_]](request).run
    else
       Future.successful(Ok(res.toString))
    }

What happened ihere was the compiler using the "wrong" methods due to me messing with the types: the res.asInstanceOf[Action[_]](request).run actually used the

def apply(rh : play.api.mvc.RequestHeader) : play.api.libs.iteratee.Iteratee

version of Action.apply.

The one we're actually interested in was

def apply(request : play.api.mvc.Request[A]) : scala.concurrent.Future[play.api.mvc.SimpleResult]

But the compiler didn't use it this way because of the missing certainty of [A] and instead, since Request is also a RequestHeader, decided the other one was a better bet.

By: Razie | 2015-05-13 .. 2016-05-16 | Tags: post , play , playframework , scala , reactive , async , programming |


See more in: Cool Scala Subscribe

Viewed 1098 times ( | Print ) this page.


This content is Copyrighted, all rights reserved.

You need to log in to post a comment!