Play Framework: how to display a Future[List[String]]? - scala

I'm exploring the Play Framework and have run in to a bit of a corner.
After making an API call to Google Analytics with the WS library, I receive a Future[Response] object. After digesting that Response object, I get the data I really care about, but because it's wrapped in a Future, I'm having some trouble writing it to the browser.
OK( gaApiString )
This gives me an error that reads:
Cannot write an instance of scala.concurrent.Future[String] to HTTP
response. Try to define a Writeable[scala.concurrent.Future[String]]
I'm having some trouble finding & understanding how to use a Writable object. Little help?

You need to map the Future to a Future[Result], passing it to Action.async.
def test = Action.async {
val wsResult: Future[String] = ...
wsResult.map { gaApiString =>
Ok(gaApiString)
}
}
If gaApiString is actually List[String], then it depends on what you want to do with it. Displaying it as a comma-separated list you could just change it to Ok(gaApiString.mkString(",")). The key here is mapping the Future to manipulate the value after it's completed.

Related

Concatenate a vector in Gatling

I'm trying to concatenate a vector into a string in order to insert it into a get call.
Previously in my code I use the following:
.exec(http("request_11")
.get("/api/data/users/${userId}")
.headers(headers_3)
.check(jsonPath("$..users[0].links.orgRoles[*]").findAll.saveAs("orgRoles")))
Which gives me an orgRoles session variable of:
Vector(b2b5fb81-4025-48a5-9890-a6ec7d64f317, 744db047-1477-4bb6-9c55-70071ce41cb8, 423b0b07-7bfa-416a-9b95-cc1d75d7d781)
I'd then like to use this concatenated session variable like so:
.exec(http("request_50")
.get("/api/data/orgRoles/${orgRoles}")
Which would, in effect, do the following get call:
.exec(http("request_50")
.get("/api/data/orgRoles/b2b5fb81-4025-48a5-9890-a6ec7d64f317,744db047-1477-4bb6-9c55-70071ce41cb8,423b0b07-7bfa-416a-9b95-cc1d75d7d781")
.headers(headers_3))
I'm brand new to Gatling and Scala, and have done a ton of research. I found the following answer which offers that
session => session("itemIds").validate[Seq[String]].map(_.mkString(","))
is the right approach. In turn, I've tried to manipulate the session variable with the following:
...
.exec { session =>
session("orgRoles").map(_.mkString(","))
}
.exec(http("request_50")
.get("/api/data/orgRoles/${orgRoles}")
.headers(headers_3))
...
Yet end up with the error:
value mkString is not a member of io.gatling.core.session.SessionAttribute
Any suggestions on moving forward?
The error you are getting is because by:
session("orgRoles")
you are calling Session.apply method at session instance (for more see source code). The apply method returns SessionAttribute instance, which has following methods:
// Use when you are certain that key exists in session, otherwise you'll get exception which you has to handle
def as[T: NotNothing]: T
// Use when you want to handle also not existing key and you can react to `None` case
def asOption[T: TypeCaster: ClassTag: NotNothing]: Option[T]
// Use when you want to code against success path and use combinators provided by `Validation`
def validate[T: TypeCaster: ClassTag: NotNothing]: Validation[T]
Each servers different purpose (see comments). All above mentioned methods of SessionAttribute are just getters from session. Their only purpose is to provide you a value of the key stored in session in any form.
Only after getting the value you can do anything with it. The safest bet is to use validate method which provides common combinators (used in all Scala collections) map and flatMap to manipulate the value when it exist. You can find more about Validation concept here. Hence your code should look like:
// Just getting from session and concatenating
session => session("orgRoles").validate[Seq[String]].map( _.mkString(",") )
// also storing back to session
session => session.set("orgRoles", session("orgRoles").validate[Seq[String]].map( _.mkString(",") ))
This is also what you already wrote above. But you are already using check DSL method and thus you can use transform() directly in your first call as:
.exec(
http("request_11")
.get("/api/data/users/${userId}")
.headers(headers_3)
.check(
jsonPath("$..users[0].links.orgRoles[*]")
.findAll
.transform( _.mkString(",") )
.saveAs("orgRoles")
)
)
It's straightforward, easier to follow and there is no temporary save to Session. Even the function which you put to transform is easier, while it is defined as A => B thus plain transformation. Check-out more about transforming here.
Have you tried calling the toString or maybe groupHierarchy?
session => session("itemIds").validate[Seq[String]].map(_.toString.mkString(","))
session => session("itemIds").validate[Seq[String]].map(_.groupHierarchy.mkString(","))
take a look at: https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/session/Session.scala
I ended up solving it with this:
.exec(session =>
session.set("orgRolesConcat", session("orgRoles").as[Seq[String]].mkString(",")))

How to Design and Call Scala API with Futures

Getting started learning scala and designing/implementing for asynchronous execution. My questions is around how to design APIs (and then call) them for operations that return Unit but may not right away. For example in the snippet below, the function (using Slick 3.0) inserts a user into the DB. Is Unit the correct return type for this function, and if so, how do callers know if/when the newly inserted user is successful?
override def insertOrUpdate(entity: User): Unit = {
database.run(users.insertOrUpdate(entity))
}
For example, if the above executes asynchronously and a caller looks something like
//create and insert new user with id = 7
val newUser = User(7, "someName")
userRepo.insertOrUpdate(newUser)
How does a caller know whether or not it is safe to do
userRepo.findById(7)
In unit testing, I know that if I follow up the insert call immediately by a findById call, the findById will return nothing, but if I introduce some latency between the insert and find call, it finds the new user. To summarize, what is the proper way to design an API for a function that executes asynchronously but has no natural return value to wrap in a Future?
Generally when working with Futures, you'll want to do any further processing via methods called on the returned Future. Eg.:
val newUser = User(7, "someName")
val future = userRepo.insertOrUpdate(newUser)
future.onSuccess { outcome => // Here, 'outcome' will hold whatever was contained in the Future - Unit in your description above.
val storedUser = userRepo.findById(7) // This will only execute once the future completes (successfully).
...
}
There are plenty of other useful methods for manipulating a Future (or a collection of them), such as "onFailure", "recover", "map" and "flatMap".
Try not to wait on the Future until as late as possible - preferably let Play or Spray or whatever other framework you might happen to be using take care of it for you (see here for Play documentation on doing this, for example).
Finally, in terms of your DB call to insert, I'd look into having the call return at least a boolean, or better still the primary key the new entry was inserted with, rather than Unit.

How do I return a File from an Akka Worker to Spray Routing

I have a akka actor that generates a bunch of files then zips them up, and returns that zip file. I want to then pass this file back to the complete method of spray routing to allow downloading of the zip file.
I would really like to be able to use getFileFrom, but I can't seem to figure out a way to utilize that with the future returned. I have also tried passing the file back to the complete function, but get a very cryptic error.
How do I chain futures to get the result I want to be downloaded in the browser?
Here is some of the code I am working with
get {
path("test") {
respondWithMediaType(`application/zip`) {
complete {
val pi = new PackageInfo("Test")
doCreate(pi)
}
}
}
}
def doCreate(pi: PackageInfo) = {
val response = (worker ? Create(pi))
.mapTo[Ok]
.map(result => result.zipFile: File)
.recover { case _ => "error" }
response
}
One of the many errors recieved while trying different things
could not find implicit value for parameter marshaller: spray.httpx.marshalling.ToResponseMarshaller[scala.concurrent.Future[Comparable[_ >: java.io.File with String <: Comparable[_ >: java.io.File with String <: java.io.Serializable] with java.io.Serializable] with java.io.Serializable]]
There are a few things to address here.
One is that after creating that file and sending it to the client you probably want to delete it. If you simply send it with getFromFile (doc) then you will not know when the client finished downloading the file and won't be able to delete that file. Here is how you can implement that functionality: Is it possible to install a callback after request processing is finished in Spray?.
The error with missing implicit means that Spray needs to know how to marshal your data back to the client. By default it can marshal only basic types like Strings, but you can implement your own custom marshallers. If you use approach described in the link I provided then you don't need to worry about that.
Finally that answer also provides a chunked response which is useful if your files are large enough.
If you decide to go with getFromFile look at this answer: Spray send xls file to client. I think that's exactly what you need.

What effect does using Action.async have, since Play uses Netty which is non-blocking

Since Netty is a non-blocking server, what effect does changing an action to using .async?
def index = Action { ... }
versus
def index = Action.async { ... }
I understand that with .async you will get a Future[SimpleResult]. But since Netty is non-blocking, will Play do something similar under the covers anyway?
What effect will this have on throughput/scalability? Is this a hard question to answer where it depends on other factors?
The reason I am asking is, I have my own custom Action and I wanted to reset the cookie timeout for every page request so I am doing this which is a async call:
object MyAction extends ActionBuilder[abc123] {
def invokeBlock[A](request: Request[A], block: (abc123[A]) => Future[SimpleResult]) = {
...
val result: Future[SimpleResult] = block(new abc123(..., result))
result.map(_.withCookies(...))
}
}
The take away from the above snippet is I am using a Future[SimpleResult], is this similar to calling Action.async but this is inside of my Action itself?
I want to understand what effect this will have on my application design. It seems like just for the ability to set my cookie on a per request basis I have changed from blocking to non-blocking. But I am confused since Netty is non-blocking, maybe I haven't really changed anything in reality as it was already async?
Or have I simply created another async call embedded in another one?
Hoping someone can clarify this with some details and how or what effect this will have in performance/throughput.
def index = Action { ... } is non-blocking you are right.
The purpose of Action.async is simply to make it easier to work with Futures in your actions.
For example:
def index = Action.async {
val allOptionsFuture: Future[List[UserOption]] = optionService.findAll()
allOptionFuture map {
options =>
Ok(views.html.main(options))
}
}
Here my service returns a Future, and to avoid dealing with extracting the result I just map it to a Future[SimpleResult] and Action.async takes care of the rest.
If my service was returning List[UserOption] directly I could just use Action.apply, but under the hood it would still be non-blocking.
If you look at Action source code, you can even see that apply eventually calls async:
https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/api/mvc/Action.scala#L432
I happened to come across this question, I like the answer from #vptheron, and I also want to share something I read from book "Reactive Web Applications", which, I think, is also great.
The Action.async builder expects to be given a function of type Request => Future[Result]. Actions declared in this fashion are not much different from plain Action { request => ... } calls, the only difference is that Play knows that Action.async actions are already asynchronous, so it doesn’t wrap their contents in a future block.
That’s right — Play will by default schedule any Action body to be executed asynchronously against its default web worker pool by wrapping the execution in a future. The only difference between Action and Action.async is that in the second case, we’re taking care of providing an asynchronous computation.
It also presented one sample:
def listFiles = Action { implicit request =>
val files = new java.io.File(".").listFiles
Ok(files.map(_.getName).mkString(", "))
}
which is problematic, given its use of the blocking java.io.File API.
Here the java.io.File API is performing a blocking I/O operation, which means that one of the few threads of Play's web worker pool will be hijacked while the OS figures out the list of files in the execution directory. This is the kind of situation you should avoid at all costs, because it means that the worker pool may run out of threads.
-
The reactive audit tool, available at https://github.com/octo-online/reactive-audit, aims to point out blocking calls in a project.
Hope it helps, too.

When should I make methods with implicit argument in Scala?

I made codes using play framework in scala which look like the following:
object Application extends Controller {
def hoge = Action( implicit request =>
val username = MyCookie.getName.get
Ok("hello " + username)
}
}
object MyCookie {
def getName( implicit request: RequestHeader ) = {
request.cookies.get("name").map(_.value)
}
}
I got a code review from my coworker. He said this code is not readable because of implicit parameter. I couldn't reply to his opinion. So could you tell me what is the best way to use implicit parameters? When should I use implicit parameters?
You should use implicit parameters when there is almost always a "right" way to do things, and you want to ignore those details almost all the time; or when there often is no way to do things, and the implicits provide the functionality for those things that work.
For an example of the first case, in scala.concurrent.Future, almost every method takes an implicit ExecutionContext. You almost never care what your ExecutionContext is from call to call; you just want it to work. But when you need to change the execution context you can supply it as an explicit parameter.
For an example of the second case, look at the CanBuildFroms in the collections library. You cannot build anything from anything; certain capabilities are supplied, and the lack of an implicit that, say, lets you package up a bunch of Vector[Option[String]]s into a HashSet[Char] is one major way to keep the library powerful and flexible yet sane.
You are doing neither: apparently you're just using it to save a little typing in one spot at the expense of the other spot. And, in this case, in doing so you've made it less obvious how things work, as you have to look all over the place to figure out where that implicit request actually gets used. If you want to save typing, you're much better off using short variable names but being explicit about it:
Action{ req => val name = MyCookie.getName(req).get; Ok("hello "+name) }