How to pass a Future data to the view? - scala

Iam trying to get data from a web weather API, I'am getting the data by using WSClient.
Actually, I can println and visualize the data like this :
val futureResponse: Future[WSResponse] = complexRequest.get()
def weather = Action {
futureResponse.map {
response =>
println(response.json)
}
println(futureResponse)
Ok(views.html.weather("data"))
}
but I have trouble passing it to the view layer using Ok(views.html.weather("data")) cause when i println(futureResponse) its not json data it shows :
Future(Success(AhcWSResponse(StandaloneAhcWSResponse(200, OK))))
only println(response.json) shows the valid data i want to send but its unreachable outside.

You need something on the lines of
def weather = Action.async {
complexRequest.get().map(response => Ok(views.html.weather(response.json)))
}
So basically, the json is only available when the future is completed, so you can only pass it to the view inside the map function, also notice that I've used Action.async this creates an action that expects a Future[WsResponse] rather than just a WsResponse
Also bear in mind that the Futures are memoised, so if you store the reference to it in a val it will only execute once
EDIT: Fixed the future being stored in a val to avoid problems with the memoisation

It's unreachable because you will have to use a callback method to access/pass the content inside Future. That's the reason println(response.json) inside map callback shows the data/content you are interested.
You may refer to Accessing value returned by scala futures

Related

How to handle a multiple singles?

I'm writing messenger server on grpc with rxjava2 stubs, and I stuck on combining my singles.
I'm have tried some sort of
val user:Single<User> = getUser()
val conversation:Single<Conversation> = getConversation(user.blockingGet())
return conversation.map{
someMethod(user.blockingGet(), conversation.it())
it
}
It looks so unbeauty then all of the examples, so is there a way to combine all of this singles to one line?
First a small comment, usually you don't want to use blockingGet. Instead you use other combinators to compose your solution and in the end you use subscribe to evaluate it.
I'm assuming you want to combine multiple calls that return a Single where the result of the next call depends on the previous.
The combinator you are looking for is flatMap.
val user: Single<User> = getUser()
val singleOfSomething: Single<Conversation> = user.flatMap { user->
getConversation(user).flatMap {conversation ->
someMethod(user, conversation)
}
}
here the return type would be Single of whatever someMethod returns.
You would use subscribe to get that value out when you need it.

Scala remote method injection

I have a requirement, I have a method, which takes another function. I want to get the result of this parameter function in my caller.
I have created a code snippet for this scenario:
class ProcessHandler {
def executeInstructions(x:String=>Array[String])
{
//print the resultant list here
}
}
object ProcessHandlerMain {
def main(args: Array[String]) {
val handler = new ProcessHandler
handler.executeInstructions( instruction)
}
def instruction(x:String):Array[String] =
{
List("words", "from", "book").toArray
}
}
This call handler.executeInstructions( instruction) will be made by another process. Here I am using main method to test it out.
Here is what I do not know:
How can I print the result of parameter function
If I have to expose this method executeInstructions() to client side, what is the best approach? Here we will not be passing text instructions, rather a function similar to instruction().
Thanks
Updated: From the response received, my code is updated to
class ProcessHandler {
def executeInstructions(x:String=>Array[String])
{
//print the resultant list here
val result = x("some string here")
//this array will be sent to another service
// dispatcher.dispatch(result)
}
}
My requirements are updated:
How can I print the result of parameter function : Done
If I have to expose this method executeInstructions() to client side, what is the best approach? Here we will not be passing text instructions, rather a function similar to instruction(). Pending
The client interface has will work as below:
1. client will be calling executeInstructions() remotely and pass function as parameter.
2. InstructionId will be passed to the injected function, the resultant array will be dispatched to another service.

Play Framework Search Bar

I'm trying to make a search bar with only one variable - the search input. I'm sure there's a fairly simple way to do this, but everything that I've found about getting input from the DOM (the views file) has been about using a Form and getting multiple variables. Is there a simpler way to do this if it's just a single variable?
I have a function in my Applications
def singleElement = Action { implicit request =>
val databaseSupport = new InteractWithDatabase(comm, db)
val put = Future {
while (true) {
val data = databaseSupport.getFromDatabase()
if (data.nonEmpty) {
comm.communicator ! data.head
}
}
}
Ok(views.html.singleElement)
}
I want to take some input from the user on the page singleElement and pass it into getFromDatabase which calls a MySQL query. How do I do this?
You can use restful and do something like this
routs file
GET /content/search/:search controllers.ContentController.search(search:String)
and in controller:
public Result search(String saerch) {}

Have a List in Play framework web service parameters

I have written this web service in play framework.
controller
def getByGenre(genre: String) = Action {
val result = Await.result(Movies.getByGenre(genre), 5 seconds)
Ok(toJson(result))
}
routes
GET /movies/genre/:genre controllers.MoviesController.getByGenre(genre: String)
However a user may select multiple Genre. Therefore I need to convert the genre parameter to a List[String]
I also need to know how to pass that Array parameter to the web service using CURL.
If you can pass the genres parameter as part of the query string, just repeat the parameter with different values and then retrieve it like this:
def getByGenre() = Action.async { implicit request =>
val genres = request.queryString.get("genres")
Movies.getByGenre(genres).map { movies =>
Ok(toJson(movies))
}
}
Your route will be:
GET /movies/genre controllers.MoviesController.getByGenre()
Also, notice that you will need to change the Movies.getByGenre signature to:
def getByGenre(genres: Option[Seq[String]]): Seq[Movies]
An final url will be something like #mfirry showed:
myhost.com/movies/genre?genre=action&genre=drama
Finally, as you may have noticed, I've removed the blocking code from you action. Using Await at your controller means that you action would be blocking for at least 5 seconds at the worst case scenario. I suggest you to take a look at the following page of Play docs:
https://www.playframework.com/documentation/2.5.x/ScalaAsync

Setting the property of an object using a variable value in scala

I'm trying to create a restful method to update data in the database, I'm using Scala on Play! framework. I have a model called Application, and I want to be able to update an application in the database. So the put request only requires the id of the application you want to update, then the optional properties you want to update.
So in my routes I have this:
PUT /v1/auth/application controllers.Auth.update_application(id: Long)
The method I currently have is this:
def update_application(id: Long) = Action { implicit request =>
var app = Application.find(id)
for((key, value) <- request.queryString) {
app."$key" = value(0)
//app.name = value(0)
}
val update = Application.update(id, app)
Ok(generate(
Map(
"status" -> "success",
"data" -> update
)
)).as("application/json")
}
In the method above I am looping through the request and the app object as a map instance, then updating the app model to be updated using the model. I know there is an easier way is to create the request string as map and just iterate through the object, but I am doing it this way for learning purposes. I'm new to Play! and Scala, barely a week new.
Is there a way to set a property using a variable dynamically that way? In the above method at the end of the loop that is how I would update a object's property in Groovy. So I'm looking for the equivalent in Scala. If Scala can't do this, what is the best way about going about accomplishing this task? Reflection? I don't want to over-complicate things
Play! provides play.api.data.Forms which allows creating a Form that uses the apply() and unapply() methods of a case class. Then you can call form.fill(app) to create a form with the initial state, bindFromRequest(request) to update the form with the request parameters, and get() to obtain a new instance with updated fields.
Define the form only once:
val appForm = Form(
mapping(
"field1" -> text,
"field2" -> number
)(Application.apply)(Application.unapply)
)
Then in your controller:
val app = appForm.fill(Application.find(id)).bindFromRequest(request).get
val update = Application.update(id, app)
Check out Constructing complex objects from the documentation.