Note that there are some explanatory texts on larger screens.

plurals
  1. POComposing multiple Try objects in Scala/Play
    text
    copied!<p>We have a Scala/Play application in which we have several implicit classes that create Try objects from the Request, e.g.</p> <pre><code>implicit class RequestUtils[+T](req: Request[T]) { def user: Try[User] = // pull the User from the Session, or throw an UnauthorizedException def paging: Try[Paging] = // create a Paging object, or throw an IllegalArgumentException } </code></pre> <p>We then access the wrapped objects via flatMaps</p> <pre><code>def route(pathParam: String) = BasicAction { request =&gt; request.user.flatMap(user =&gt; request.paging.flatMap(paging =&gt; Try{ ... } ))} </code></pre> <p>And finally, an ActionBuilder generates a SimpleResult from the Try</p> <pre><code>case class BasicRequest[A](request: Request[A]) extends WrappedRequest(request) class BasicActionBuilder extends ActionBuilder[BasicRequest] { def invokeBlock[A](request: Request[A], block: (BasicRequest[A]) =&gt; Future[SimpleResult]) = { block(BasicRequest(request)) } } def BasicAction[T](block: BasicRequest[AnyContent] =&gt; Try[T]) = { val f: BasicRequest[AnyContent] =&gt; SimpleResult = (req: BasicRequest[AnyContent]) =&gt; block(req) match { case Success(s) =&gt; Ok(convertToJson(s)) case Failure(e: UnauthorizedException) =&gt; Unauthorized(e.getMessage) case Failure(e: Exception) =&gt; BadRequest(e.getMessage) case Failure(t: Throwable) =&gt; InternalServerError(e.getMessage) } val ab = new BasicActionBuilder ab.apply(f) } </code></pre> <p>We're trying to find a way to essentially compose multiple Try objects together (or something along those lines - we're not wedded to using Trys) - the flatMaps are working fine for one or two Trys, but nesting them more than that hampers program readability. We can manually compose the objects together, e.g.</p> <pre><code>case class UserAndPaging(user: User, paging: Paging) implicit class UserAndPagingUtils[+T](req: Request[T]) { def userAndPaging: Try[UserAndPaging] = req.user.flatMap(user =&gt; req.paging.flatMap(paging =&gt; UserAndPaging(user, paging)) } </code></pre> <p>but that's going to result in an explosion of case class + implicit class def combinations. Ideally I'd like to be able to compose multiple Try objects together in an ad hoc fashion, e.g.</p> <pre><code>def route(pathParam: String) = BasicAction { request =&gt; compose(request.user, request.paging).flatMap(userWithPaging =&gt; ...) } </code></pre> <p>and have a Try[User with Paging] magically composed for me, but I have no idea how I'd go about doing this - I've been wrestling with the type system to try to assign a meaningful type to "compose" without any success.</p> <p>How can I compose multiple Try objects together, or something equivalent using another language construct?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload