Spray: factor out onSuccess directive - scala

I would like to change the following code fragment in a way that I want to factor out the onSuccess block into a new method. JSON marshalling should still work.
(patch & parameterMap & asJson) { params =>
...
val f:Future[ResposeData]=createResponse(...)
onSuccess(f){complete(_)}
}
I would like to have a method like:
def handleSuccess(f:Future/FutureMagnet)(implicit ...)
A simple refactoring doesn't work for me. I tried a lot of combinations but I can't find either the correct signature or the code working.
Example:
def handleSuccess(f: Future[ResposeData]): Unit = {
onSuccess(f) { complete(_) }
}
Error:(43, 15) type mismatch;
found : scala.concurrent.Future[ResponseData]
required: spray.routing.directives.OnSuccessFutureMagnet
onSuccess(f) {
^
If I now change signature I get another error:
def handleSuccess(f: OnSuccessFutureMagnet)
Error:(44, 18) spray.routing.Directive[f.Out] does not take parameters
onSuccess(f) {
^
Maybe this is just a simple thing to do but I'm new to spray.
So it would be nice if somebody could give a hint.
Thanks

onSuccess takes a function, basically when you use that on your future the value inside the future becomes available and you can complete your route using that value if you want:
case class ResponseData(data: String)
def handleSuccess(f: Future[ResponseData]): Unit = {
onSuccess(f) { responseData =>
complete(_)
}
}
From the comments:
"Unwraps" a Future[T] and runs its inner route after future completion with the future's value as an extraction of type T.
Note also that
If the future fails its failure throwable is bubbled up to the nearest ExceptionHandler.
Maybe you want to use onComplete which returns a Try and you can then match on Success or Failure.

Related

how get the result of Future without using "await"

I want to get the result of a Future without blocking operations.
If I write my code with "await", it works but it is not good for me because it is blocking:
val t: Future[MatchResult[Personne]] = db.getPersonne(userId).map(_.get must beEqualTo(personne))
t.await
I tried to change my code with map:
val r: Future[MatchResult[Personne]] = db.getPersonne(userId).map(_.get must beEqualTo(personne))
r.map {
case r#isWhatIExpected => r
case isNot => isNot
}
but I have this error:
found :
scala.concurrent.Future[org.specs2.matcher.MatchResult[Personne]]
[error] required: org.specs2.specification.create.InterpolatedFragment
Using Specs2 as it appears, there are helpers to test async functions.
import org.specs2.concurrent.{ExecutionEnv => EE}
"Foo" in { implicit ee: EE => // take care of ee
myAsyncFunWithFuture must beEqualTo(expectedVal).await(timeToWait)
}
#user4650183 I think I don't understand your question then. Something somewhere has to wait, or block if you prefer, on the result before using it.

Scala :Returning a Function with variable argument from another function

My requirement is to return a function from another function in scala which takes variable argument i.e while executing the returned function , i can pass multiple argument at runtime.
My code looks like :
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any={
(arg:Map[String,String], arg2:Map[String,Any]*) => "random"//this gives compilation error
}
}
In code , i want to return a function which take , Map[String,String] as one argument ,while the other Map[String,Any] should be optional to it.
But i get compilation error in return statement as follow:
type mismatch; found : (Map[String,String], Map[String,Any]) required: (Map[String,String], Map[String,Any]*) ⇒ Any
Can anyone help , what have i missed here?
Note: My requirement is that returned function can take either one argument (Map[String,String]) or it can take two arguments max (Map[String,String], Map[String,Any])
Thanks
It's impossible to use varargs in anonymous function.
You can get your piece of code working by making the returned function nested instead of anonymous like this:
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any = {
def nestedFunction(arg:Map[String,String], arg2:Map[String,Any]*) = "random"
nestedFunction
}
}
However since you don't need multiple instances of Map[String, Any] but either none or one, you would be better off using Option[Map[String, Any]], providing None when it is not needed.

Scala: "required: scala.concurrent.Future[?]"

Edit
Still haven't found a solution so I ended up creating two someFuture methods. One that returns a future & one that doesn't (to get otherFuture to compile)
I'm trying to return Future[Option[JsObject]] but keep getting this error:
required: scala.concurrent.Future[?]
What I'm doing
def someFuture:Future[Option[JsObject]] =
Future {
Option(JsObject())
}
def otherFuture:Future[Option[JsObject]] =
Future {
Option(JsObject(
someFuture.flatMap(_.get)
))
}
// get error here
found : JsObject
[error] required: scala.concurrent.Future[?]
How can I return the JsObject without getting an error?
The problem is that someFuture.flatMap(_.get) won't compile—you need to provide a function that takes a JsObject and returns a Future[Whatever] to use flatMap on someFuture.
You probably want something like this:
def otherFuture: Future[Option[JsObject]] = someFuture.map { opt =>
Option(JsObject(opt.get))
}
There's not really any reason to use Option if you're just going to call .get on it like this, though, so the following might be better:
def otherFuture: Future[Option[JsObject]] = someFuture.map(_.map(JsObject(_)))
Now if the future is satisfied by a non-empty option, the contents of the option will be wrapped in another layer of JsObject, which seems to be what you're aiming for?
Note that if you're using Option to represent failure, you may want to consider the failure-handling that's built into Future instead.

implicit keyword in Play Action

Can someone explain to me what's the use of implicit keyword in the following Play Action:
def index = Action { implicit request =>
Async {
val cursor = collection.find(
BSONDocument(), BSONDocument()).cursor[Patient]
val futureList = cursor.toList
futureList.map { patients => Ok(Json.toJson(patients)) }
}
}
Thanks in advance.
In all Scala (not just Play), an argument to an anonymous function can be marked implicit just as with methods. Within the body of the function, the implicit parameter is visible and can be resolved to an appropriate value in scope.
In this case, request is the argument of the anonymous function that describes what the action will do. The implicit lets the function be called with any value of type Request that happens to be in scope so you don't have to provide the Request instance yourself. You can trust it will be there so you can focus on the work of handling the request.

Scala Implicit parameters by passing a function as argument To feel the adnvatage

I try to feel the advantage of implicit parameters in Scala. (EDITED: special case when anonymous function is used. Please look at the links in this question)
I try to make simple emulation based on this post. Where explained how Action works in PlayFramework. This also related to that.
The following code is for that purpose:
object ImplicitArguments extends App {
implicit val intValue = 1 // this is exiting value to be passed implicitly to everyone who might use it
def fun(block: Int=>String): String = { // we do not use _implicit_ here !
block(2) // ?? how to avoid passing '2' but make use of that would be passed implicitly ?
}
// here we use _implicit_ keyword to make it know that the value should be passed !
val result = fun{ implicit intValue => { // this is my 'block'
intValue.toString // (which is anonymous function)
}
}
println(result) // prints 2
}
I want to get "1" printed.
How to avoid passing magic "2" but use "1" that was defined implicitly?
Also see the case where we do not use implicit in definition, but it is there, because of anonymous function passing with implicit.
EDITED:
Just in case, I'm posting another example - simple emulation of how Play' Action works:
object ImplicitArguments extends App {
case class Request(msg:String)
implicit val request = Request("my request")
case class Result(msg:String)
case class Action(result:Result)
object Action {
def apply(block:Request => Result):Action = {
val result = block(...) // what should be here ??
new Action(result)
}
}
val action = Action { implicit request =>
Result("Got request [" + request + "]")
}
println(action)
}
Implicits don't work like this. There is no magic. They are just (usually) hidden parameters and are therefore resolved when invoking the function.
There are two ways to make your code work.
you can fix the implicit value for all invocations of fun
def fun(block: Int=>String): String = {
block(implicitly[Int])
}
implicitly is a function defined in Predef. Again no magic. Here's it's definition
def implicitly[A](implicit value: A) = value
But this means it will resolve the implicit value when declaring the fun and not for each invocation.
If you want to use different values for different invocations you will need to add the implicit paramter
def fun(block: Int=>String)(implicit value: Int): String = {
block(value)
}
This will now depend on the implicit scope at the call site. And you can easily override it like this
val result = fun{ _.toString }(3)
and result will be "3" because of the explicit 3 at the end. There is, however, no way to magically change the fun from your declaration to fetch values from implicit scope.
I hope you understand implicits better now, they can be a bit tricky to wrap your head around at first.
It seems that for that particular case I asked, the answer might be like this:
That this is not really a good idea to use implicit intValue or implicit request along with implicitly() using only one parameter for the function that accept (anonymous) function.
Why not, because:
Say, if in block(...) in apply() I would use implicitly[Request], then
it does not matter whether I use "implicit request" or not - it will use
request that is defined implicitly somewhere. Even if I would pass my
own request to Action { myOwnRequest =Result }.
For that particular case is better to use currying and two arguments and.. in the second argument - (first)(second) to use implicit
Like this:
def apply(block:Request => Result)(implicit request:Request):Action2
See my little effort around this example/use case here.
But, I don't see any good example so far in regards to how to use implicit by passing the (anonymous) function as argument (my initial question):
fun{ implicit intValue => {intValue.toString}
or that one (updated version):
val action = Action { implicit request =>
Result("Got request [" + request + "]")
}