Where is the object Action in play.api.mvc? - scala

I am a novice of Play Framework. When I learn it on its webpages. I found some code like this:
import play.api.mvc._
def logging[A](action: Action[A]) = Action.async(action.parser) { request =>
logger.info("Calling action")
action(request)
}
I checked its document and there is a function async in ActionBuilder.
How does Action.async works? It seems there is no object Action in play.api.mvc

object Action has been removed in Play 2.8 by Remove deprecated play.api.mvc.Action #9288, and has been replaced by BaseController.Action method which refers to injected controllerComponents.actionBuilder rather than the global objects
/**
* ...
* This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
*/
def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
Notice how, perhaps unconventionally, the method name begins with an uppercase letter. My assumption is this was done to maintain familiar usage
def foo(query: String) = Action {
Ok
}

Related

What is this Scala construct doing?

I've been using Play! Framework with Java and would like to try it out with Scala.
I've started on a Scala book but the most basic Play! sample has me completely puzzled:
def index(): Action[AnyContent] = Action { implicit request =>
Ok(views.html.index())
}
What Scala construct is Play! using here? I understand that we are defining a function that returns an Action with a generic parameter AnyContent. But the next part has me puzzled. What does the assignment mean in this context?
If I go to definition of Action[AnyContent] it's defined as trait Action[A] extends EssentialAction { ... }
If I go to the definition of Action after equals it's defined as:
trait BaseController extends BaseControllerHelpers {
/**
* The default ActionBuilder. Used to construct an action, for example:
*
* {{{
* def foo(query: String) = Action {
* Ok
* }
* }}}
*
* This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
*/
def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
}
Note: I'm interested in the Scala construct that's used I don't care what Play! is actually doing here which I kind of understand.
You are essentially calling Action.apply(), which is defined here in ActionBuilder. The first and only parameter of the apply() function being the function request => Ok(...).

ActionBuilder is returning requestBody as null

I'm developing a scala Web application with play framework, the first time i used filter in order to validate the request but i had no result then i tried to use action builder i had to override 2 methods here is my ActionBuilder Object
object MyJsonAction extends ActionBuilder[Request, Response] with Results {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
println (request.body)// returning null everytime why ?
block(request)
}
override def parser = { // what does this method do, i think the problem started from here :/ ?
null;
}
override protected def executionContext = {
null;
}
}
Well, there are no much resource with play framework just simple examples and there is no example briefly explain what those methods are doing, they tell that you can get request body without telling you how ! everything is ambiguous ! im stuck with it since 3 days a go, and i have no idea what should i do now. thanks
An ActionBuilder is an object that build an Action. An Action combines a BodyParser[T], which reads the request body and constructs a T, with a function Request[T] => Future[Result] to process the T.
The default ActionBuilder does this in a very simple way. It chains together the BodyParser's result and feeds it to the function. If you make a custom ActionBuilder then you can override this process, perhaps by injecting your own logic before or after the function call.
If you're making your own ActionBuilder I'd suggest starting with something like the following as a template:
#Singleton
class MyJsonAction #Inject() (
bodyParsers: PlayBodyParsers,
ec: ExecutionContext) extends ActionBuilder[Request, JsValue] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
println(request.body) // DO SOMETHING HERE
block(request)
}
override def parser = bodyParsers.json
override protected def executionContext = ec
}
Then you can use it in your controllers like this:
class MyController #Inject() (myJsonAction: MyJsonAction) {
def index = myJsonAction { req: Request[JsValue] => ??? }
}
The important piece is the parser: BodyParser[A] it takes the incoming bytes and convert them into a type A.
For instance BodyParser[JsValue] will produce a body of type JsValue. It is used to read Json.
If you are trying to validate an object, maybe an action builder is not the right place to start. You may focus more on the BodyParsers and the json validation

Understanding syntax of a scala function

I am trying to learn scala. I know how to write a function. This is how I write a function.
def test_function: Unit = {
println("This is just a test")
}
But then I started learning playframework. This is how they write a function in controller in play.
def test_function: Unit = Action{
println("This is just a test")
}
My question is what is this Action doing before the curly braces? What is it called? How can I write my own? I hope I have made my question clear. Thanks in advance.
You can get this kind of behavior by defining an apply method on an object called Action:
object Action {
def apply(block: => Unit): Unit = {
println("before")
block // do the action in the block
println("after")
}
}
Then both of these:
Action { println("hi") }
Action(println("hi"))
Produce this:
before
hi
after
The thing in braces after Action is just the argument to the apply method. Scala allows either parentheses or braces, but using braces allows you to put multiple statements in:
Action {
println("a")
println("b")
}
yields:
before
a
b
after
Action is a trait (play.api.mvc.Action). Essentially it represents this type: play.api.mvc.Request => play.api.mvc.Result (doc1, doc2).
In your case you are using Action {...} which is equivalent to Action(...) and converted by compiler to Action.apply(...) call. If you check source code you'll see the apply method signatures defined not only on the Action trait and it's companion object, but also in here:
/**
* Provides helpers for creating `Action` values.
*/
trait ActionBuilder[+R[_]] extends ActionFunction[Request, R]
In your case you are not taking any request and not producing any response, so essentially your Action is a function call of a form apply(block: => Result) where Result is thrown away since you define return type of your function as Unit.
Action supports many ways you can handle its body (including Futures) so pick the right apply method to cover your needs.
You can extend Action if you need to since it's not a final implementation. Here is an example:
case class Logging[A](action: Action[A]) extends Action[A]
Action is basically a function alias of the shape play.api.mvc.Request => play.api.mvc.Result. When you see Action { }, you are actually seeing apply function of the companion object of that type and are passing a body that should provide that Request => Result function.
The companion object has roughly the shape of:
object Action {
def apply(f: Request => Response): Action = ...
}
so that when you call Action { ... }, the { ... } is that function that will be executed when the action is invoked.
In your example, println("This is just a test") serves as the provider of the Result.

Mocking Scala Trait using Scala, ScalaTest, and Mocktio

For whatever reason Mocktio will not mock a method I have in a trait, it will call the actual method. Here is my test:
"displays the index page" in {
val mockAuth = mock[AuthMethods]
when(mockAuth.isAllowed(-1, "", "")).thenReturn(true)
val controller = new TestController()
val result = controller.index().apply(FakeRequest())
val bodyText = contentAsString(result)
bodyText must include ("Name")
}
Here is the trait and object:
trait AuthMethods {
def isAllowed(userID:Long, method:String, controller:String) : Boolean = {
//do stuff..
}
object Authorized extends AuthMethods with ActionBuilder [Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
if(isAllowed(userID, method, controller) {
//do some more stuff..
}
Any thoughts on why its calling the actual method verses the mocked method? I am using Scala 2.10.4. Any help would be appreciated.
I forgot to mention, Authorized is a Action Composition and here is how it is being used:
def index = Authorized {
Ok(html.Stations.index(Stations.retrieveAllStations))
}
You have created a mock implementation mockAuth but have not done anything with it. Creating a mock implementation will not magically cause it to replace some other object. It looks like you want to create a mock of the Authorized object and arrange for your TestController to use it. You'll probably have to break a dependency somewhere.
(updated) Since this is in the context of the Play framework, you might find this blog post helpful. It describes a situation similar to yours. It appears you will have to change the way the Authorized object is referenced in order to supply a mock implementation.

How to test Zentasks sample app from Play 2.0

I play with Play 2.0, Scala version. Currently, I analyze Zentasks sample app.
One of the part of this app is authentication mechanism mostly covered in Secured trait. I'm wondering how I can test secured actions, ex. index from Projects controller.
For not-secured action, I'd probably do something like
val result = controllers.Projects.index(FakeRequest())
to run an action and get its result.
What should I do in case of the secured action?
Disclaimer: I'm totally new to both Scala and Play, so all hints are very valuable. Thanks!
There is a fix for the integrated approach to this in Playframewrk v2.1 I have a backport of the fix on the 2.0.x branch
Until it gets merged and released, here is what I did (it works on Play 2.0.3+):
I defined my own Helpers object in a libs package like so.
package libs
import play.api.mvc._
import play.api.libs.iteratee._
import play.api.libs.concurrent._
import play.api.test._
object Helpers {
def routeAndCall[T](request: FakeRequest[T]): Option[Result] = {
routeAndCall(this.getClass.getClassLoader.loadClass("Routes").asInstanceOf[Class[play.core.Router.Routes]], request)
}
/**
* Use the Router to determine the Action to call for this request and executes it.
*/
def routeAndCall[T, ROUTER <: play.core.Router.Routes](router: Class[ROUTER], request: FakeRequest[T]): Option[play.api.mvc.Result] = {
val routes = router.getClassLoader.loadClass(router.getName + "$").getDeclaredField("MODULE$").get(null).asInstanceOf[play.core.Router.Routes]
routes.routes.lift(request).map {
case a: Action[_] =>
val action = a.asInstanceOf[Action[T]]
val parsedBody: Option[Either[play.api.mvc.Result, T]] = action.parser(request).fold(
(a, in) => Promise.pure(Some(a)),
k => Promise.pure(None),
(msg, in) => Promise.pure(None)
).await.get
parsedBody.map{resultOrT =>
resultOrT.right.toOption.map{innerBody =>
action(FakeRequest(request.method, request.uri, request.headers, innerBody))
}.getOrElse(resultOrT.left.get)
}.getOrElse(action(request))
}
}
}
Then in my test I import my Helpers and the whole play Helpers context, except for routeAndCall :
import libs.Helpers._
import play.api.test.Helpers.{routeAndCall => _,_}
I then use an Around to setup my app (I need the provide an application.secret as I store the authenticated user name in the session which is based on a signed cookie)
def appWithSecret():Map[String,String]={
Map(("application.secret","the answer is 42 !"))
}
object emptyApp extends Around {
def around[T <% Result](t: => T) = {
running(FakeApplication(additionalConfiguration = inMemoryMongoDatabase("emptyApp")++appWithSecret())) {
User(new ObjectId, "Jane Doe", "foobar#example.com", "id1").save()
t // execute t inside a http session
}
}
}
This allows me to write the following tests:
"respond to the index Action" in emptyApp {
val request: FakeRequest[AnyContent] = FakeRequest(GET, "/expenses").withSession(("email", "foobar#example.com"))
val Some(result) = routeAndCall(request)
status(result) must equalTo(OK)
contentType(result) must beSome("application/json")
charset(result) must beSome("utf-8")
contentAsString(result) must contain("Hello Bob")
}
It allows you to exercise the secured code even though it is not a unit test.
ok, I am no great expert either, but here is an idea.
Create a trait InSecure trait extends Secured which overrides the Secured actions and always permits access.
Then you can make an object InSecureProjects extends Projects with InSecture in your test, this should override just the security checks and let you test the actions without any security.
Now, instead of running the tests on Projects, you run them on InSecureProjects. You can do exactly the same for the other secured controllers.
I haven't tested it, so let me know if it works ;)