Why does the following Play syntax work
def handleForm = Action(parse.tolerantFormUrlEncoded) { implicit request =>
val username = request.body.get("username").map(_.head).getOrElse("");
Ok("Username was " + username)
}
Without specifying the type of request, how would the compiler know how to resolve the implicit?
An Action in Play can be seen as a function: Request[A] => Result. Internally an Action is defined like trait Action[A] extends EssentialAction
The type A is actually the one which allows you to put anything in there. As you can see from the code, the Request is defined like this: trait Request[+A] extends RequestHeader. Interesting here is also the plus sign (+). It is the so-called covariant annotation. This covariant type parameter is one which is allowed to vary down as the class is subtyped. It means that if you have something like
trait List[+A]
then List[Int] is a subtype of List[AnyVal] because Int is a subtype of AnyVal. This means that you may provide an instance of List[Int] when a value of type List[AnyVal] is expected.
All this allows you to have a super generic request which serves as a base for your action and therefore no compile time troubles should be expected.
And something as for why is this all necessary from a more user-related point of view:
From the Play Scala documentation:
It is often useful to mark the request parameter as implicit so it can
be implicitly used by other APIs that need it:
Action { implicit request =>
Ok("Got request [" + request + "]")
}
It doesn't actually resolve the implicit, you mark the parameter as implicit, for further method calls inside the request handler. Whenever you call a method which accepts an implicit Request parameter, the request argument from the request handler will be automatically passed to it. If you wouldn't mark the request argument as implicit, you'd have to explicitly pass the request argument for each method call who needs an implicit request parameter.
update: upon your comment I updated your code with type parameters to clarify. So even when you use different BodyParsers, your request parameter is still going to be of Request type, so there is no need to convert it, it's just going to be parametrized differently based on your body parser. request.body is going to have the same type as the type parameter, Map[String, Seq[String]] in this example. If you use a JSON body parser then your request parameter would be a Request[JsValue], and the request.body is a JsValue.
def handleForm: Action[Map[String, Seq[String]]] = Action(parse.tolerantFormUrlEncoded)({
implicit request: Request[Map[String, Seq[String]]] =>
val username = request.body.get("username").map(_.head).getOrElse("")
Ok("Username was " + username)
})
tl;dr You can just do Action(...) { request => ... } if you don't need an implicit Request for further method calls inside the request handler
Related
I'm quite new to scala, I will appreciate if you can help me with the following question.
i'm using akka-http to send http request I would like to declare a generic send request method which transforms the http response body using Unmarshall to the generic type.
How should i cast the Unmarshal response to T ???
the send request implementation:
def sendRequest[T](requestMessage :HttpRequestMessage) :Future[T] =
{
val promise = Promise[HttpResponse]()
val request = requestMessage.request -> promise
queue.offer(request).flatMap {
case QueueOfferResult.Enqueued => promise.future.flatMap[AnyRef] {
response => {
response.entity.toStrict(FiniteDuration(3,"seconds")).flatMap {
strict => Unmarshal(strict.getData).to[T]
}
}
}
}
}
If you take a look at the code of Unmarshal object, you can see that the type parameter used in to has a certain constraint - an implicit unmarshaller:
class Unmarshal[A](val value: A) {
/**
* Unmarshals the value to the given Type using the in-scope Unmarshaller.
*/
def to[B](implicit um: Unmarshaller[A, B], ec: ExecutionContext, mat: Materializer): Future[B] = um(value)
}
When unmarshalling a value of type A to a value of type B, there must be an implicit value of type Unmarshaller[A, B] available in scope. There are many predefined unmarshallers (e.g. here are some commonly used ones for converting from String to various types such as Int, Boolean etc.), but you can also define your own. This is known as the type class pattern.
So if you want your code to work for some type T, you must ensure that there is an implicit unmarshaller for that type available in scope. This means that your method sendRequest must have an implicit parameter of type Unmarshaller[Data, T], where Data should be replaced by whatever is the actual type of strict,getData (I can't tell from your code).
So something like this:
def sendRequest[T](requestMessage: HttpRequestMessage)(implicit m: Unmarshaller[Data, T]): Future[T] // replace Data with concrete type
This allows the compilation of to[T], but now you have the obligation to actually have this implicit value in scope at the point of invocation of to[T]. As said earlier, you have two options - either import predefined unmarshallers (such as PredefinedFromStringUnmarshallers shown earlier), or define your own. I can't tell what T can be so I can't advise you further than this, but the main point is that as long as you provide the unmarshaller for the concrete type behind T (via import or define it manually), it should work; otherwise akka will have no idea how to unmarshall to your T.
I have one controller action implemented like this:
def doChangePassword = deadbolt.Restrict(List(Array(Application.USER_ROLE_KEY)))()
{ request => // <<<<<<<<<<<< here is the request
Future {
val context = JavaHelpers.createJavaContext(request)
com.feth.play.module.pa.controllers.AuthenticateBase.noCache(context.response())
val filledForm = Account.PasswordChangeForm.bindFromRequest
// compilation error here, it can't see the request ^^^^^^^
if (filledForm.hasErrors) {
// User did not select whether to link or not link
BadRequest(views.html.account.password_change(userService, filledForm))
} else {
val Some(user: UserRow) = userService.getUser(context.session)
val newPassword = filledForm.get.password
userService.changePassword(user, new MyUsernamePasswordAuthUser(newPassword), true)
Redirect(routes.Application.profile).flashing(
Application.FLASH_MESSAGE_KEY -> messagesApi.preferred(request)("playauthenticate.change_password.success")
)
}
}
}
the implementation above leads to the compilation error:
[error] /home/bravegag/code/play-authenticate-usage-scala/app/controllers/Account.scala:74: Cannot find any HTTP Request here
[error] val filledForm = Account.PasswordChangeForm.bindFromRequest
[error] ^
[error] one error found
However, if I change line 2 from:
{ request => // <<<<<<<<<<<< here is the request
to
{ implicit request => // <<<<<<<<<<<< here is the request
then it compiles ... but why?
What you are looking for are Implicit Parameters. In short:
Implicit Parameters can be passed just like regular or explicit parameters. In case you do not provide an implicit parameter explicitly, then the compiler will try to pass one for you. Implicits can come from various places. From the FAQ Where does Scala look for implicits?:
First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Now look at associated types in
Companion objects of a type
Implicit scope of an argument’s type (2.9.1)
Implicit scope of type arguments (2.8.0)
Outer objects for nested types
Other dimensions
Implicits under number 1. take precedence over those under number 2.
By marking request as implicit in your example, you are declaring an "Implicit defined in current scope". You need to have an implicit request in place because bindFormRequest "asks" you to pass one. See its signature:
bindFromRequest()(implicit request: Request[_]): Form[T]
Now that you have an implicit request in scope, the compiler will automatically pass it to bindFormRequerst.
As I mentioned in the beginning, you could also pass request explicitly:
val filledForm = Account.PasswordChangeForm.bindFromRequest()(request)
In the latter case there is no need to declare request as implicit as you are obviously passing request explicitly. Both variants are equal. It's up to you which one you prefer.
you need an implicit request in scope, like this: https://github.com/pedrorijo91/play-slick3-steps/blob/master/app/controllers/ApplicationController.scala#L11
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.
I understand implicit parameters and implicit conversions in Scala but I saw this for the first time today: the implicit keyword in front of a parameter in an anonymous function:
Action { implicit request =>
Ok("Got request [" + request + "]")
}
What does the implicit keyword do here?
Are there resources on the web that describes more on what the use case is?
There are two distinct features here.
First, request isn't really an argument in a method invocation. It's the argument of an anonymous function. The anonymous function itself is the argument of the method invocation.
Second, declaring an implicit argument in an anonymous function have the convenience of saving you from "forcing" a val into a implicit:
Action { request =>
implicit val r = request
Ok("Got request [" + request + "]")
}
I happen to know this a Play framework code, but I am not sure what are the signatures for Action and Ok. I will guess that they are something like that:
def Action(r:Request => Result):Unit
case class Ok(str:msg)(implicit r:Request)
Again, it's pure guessing for illustrative purposes only.
Found a few resources:
https://issues.scala-lang.org/browse/SI-1492
https://stackoverflow.com/a/5015161/480674
search for "Implicit arguments in closures" on the second link
In my understanding, the keyword of Implicit means Let complier do the job
Declaring an implicit variable means it can be used for implicit parameter of other methods inside the scope. In other words, the variable is being considered by the compiler to fill in implicit parameters.
def index = Action { implicit request =>
val str = sayHi("Jason")
Ok(views.html.index("Your new application is ready." + str))
}
private def sayHi(name: String)(implicit req: Request[AnyContent]) = name + ", you can the following content" + req.body
I declare an implicit parameter req in sayHi with type Request[AnyContent], however, I can call the method with only first parameter sayHi("Jason") because the implicit parameter req is filled in by the compiler to reference the implicit variable request
I understand implicit parameters and implicit conversions in Scala but I saw this for the first time today: the implicit keyword in front of a parameter in an anonymous function:
Action { implicit request =>
Ok("Got request [" + request + "]")
}
What does the implicit keyword do here?
Are there resources on the web that describes more on what the use case is?
There are two distinct features here.
First, request isn't really an argument in a method invocation. It's the argument of an anonymous function. The anonymous function itself is the argument of the method invocation.
Second, declaring an implicit argument in an anonymous function have the convenience of saving you from "forcing" a val into a implicit:
Action { request =>
implicit val r = request
Ok("Got request [" + request + "]")
}
I happen to know this a Play framework code, but I am not sure what are the signatures for Action and Ok. I will guess that they are something like that:
def Action(r:Request => Result):Unit
case class Ok(str:msg)(implicit r:Request)
Again, it's pure guessing for illustrative purposes only.
Found a few resources:
https://issues.scala-lang.org/browse/SI-1492
https://stackoverflow.com/a/5015161/480674
search for "Implicit arguments in closures" on the second link
In my understanding, the keyword of Implicit means Let complier do the job
Declaring an implicit variable means it can be used for implicit parameter of other methods inside the scope. In other words, the variable is being considered by the compiler to fill in implicit parameters.
def index = Action { implicit request =>
val str = sayHi("Jason")
Ok(views.html.index("Your new application is ready." + str))
}
private def sayHi(name: String)(implicit req: Request[AnyContent]) = name + ", you can the following content" + req.body
I declare an implicit parameter req in sayHi with type Request[AnyContent], however, I can call the method with only first parameter sayHi("Jason") because the implicit parameter req is filled in by the compiler to reference the implicit variable request