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
Related
Using Play 2.5.3, I have this filter setup:
#Singleton
class Filters #Inject() (
env: Environment,
postRequestLoggingFilter: PostRequestLoggingFilter) extends HttpFilters {
override val filters = {
Seq(postRequestLoggingFilter)
}
}
This works great for regular http web requests, but does not trigger for a WebSocket route (ws://) such as:
class Controller3 #Inject() (implicit system: ActorSystem, materializer: Materializer) extends play.api.mvc.Controller {
def socket = WebSocket.acceptOrResult[String, String] { request =>
...
How can I include this route type in my filters or is there another mechanism for intercepting this type of request?
After spending some time looking into this, the way the Filter system currently works it doesn't lend itself well to being applied to WebSocket requests.
The issue is that Filters work with an apply method taking a
nextFilter: RequestHeader => Future[Result]
where as WebSocket functions take a
f: RequestHeader => Future[Either[Result, Flow[In, Out, _]]]
So passing the WebSocket result through the Filter system doesn't really work.
However for my case, I was primarily interested in the logging filter. So as a workaround I created a custom version of acceptOrResult as follows:
def acceptOrResult[TIn, TOut](f: RequestHeader => Future[Either[Result, Flow[TIn, TOut, _]]])(implicit transformer: MessageFlowTransformer[TIn, TOut], materializer: Materializer, ec: ExecutionContext): WebSocket = {
WebSocket { request =>
f(request).map { fResult =>
PostRequestLoggingFilter.apply(request,fResult.left.getOrElse(Ok))
fResult.right.map(transformer.transform)
}
}
}
I needed to break the logic out of the PostRequestLoggingFilter into it's companion object's apply method so the above could function.
If the WebSocket request is Left, we have a Result; if it's Right then I just pass an Ok result. This could be applied to other filters as long as you don't mind the fact that they'll run after the WebSocket request.
I am developing a REST API using play framework. I would like to implement a centralized error handling for all my actions.
What is the best way to achieve this?
An alternative way do this is to use a filter, e.g:
object ExceptionFilter extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
val next: Iteratee[Array[Byte], Result] = nextFilter(requestHeader)
// Say your backend throws an ItemNotFound exception.
next recoverWith {
case e: ItemNotFound => Iteratee.ignore[Array[Byte]]
.map(_ => Results.NotFound("Item not in the database!"))
}
}
}
}
Then hook that up in your global settings:
object Global extends WithFilters(CSRFFilter(), ExceptionFilter) with GlobalSettings
This potentially allows you to do something with the request body if needed. I agree in most cases using GlobalSettings.onError is probably the easiest approach.
You should have a look at the GlobalSettings: https://www.playframework.com/documentation/2.3.x/ScalaGlobal
Especially, it allows you to override:
def onError(request: RequestHeader, ex: Throwable)
def onHandlerNotFound(request: RequestHeader)
def onBadRequest(request: RequestHeader, error: String)
onError is probably the one you are looking for, but the others may be useful too :)
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.
the function consume an action, return the same action, what's the purpose of it, it has neither side effect nor any transformation. Looks to me it doesn't nothing, like var a=a,how is it useful?
protected def composeAction[A](action: Action[A]): Action[A] = action
By itself, it doesn't do anything, as you say. It's meant as a placeholder to be overridden when composing Actions, as described in the Play 2.2 release highlights :
We now provide an ActionBuilder trait for Scala applications that
allows more powerful building of action stacks. For example:
object MyAction extends ActionBuilder[AuthenticatedRequest] {
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[SimpleResult]) = {
// Authenticate the action and wrap the request in an authenticated request
getUserFromRequest(request).map { user =>
block(new AuthenticatedRequest(user, request))
} getOrElse Future.successful(Forbidden)
}
// Compose the action with a logging action, a CSRF checking action, and an action that only allows HTTPS
def composeAction[A](action: Action[A]) =
LoggingAction(CheckCSRF(OnlyHttpsAction(action)))
}
Our Play application uses Slick as a data access layer. This means that in almost every action in our app we need to have both the current Request and Slick's database Session implicitly available on the scope.
I want to write a custom Action to do this so we only need one line to do this. What I want to do is write it in such a way that I can write something like this:
def someAction = DBAction { implicit request, session =>
// body with implicit request and session on scope
But this is not valid syntax. Using a tuple does not work because it cannot implicitly unpack the tuple in action body. Is it possible to create a custom action that passes multiple implicit arguments to the body? How do I do this?
You cannot implicit 2 variables like that.
But your Custom action can return a WrappedRequest (an object which encapsulates the request and your session), and you can define an implicit conversion between this wrapped request and your Session.
Try this example, derived from this class.
sealed case class DBRequest(session: Session, private val request: Request[AnyContent])
extends WrappedRequest(request)
trait DBController extends Controller {
// Implicit conversion from DBRequest to Session
implicit def session(implicit request: DBRequest) = request.session
def DBAction(action: DBRequest => Result) = Action { request =>
database.withSession { session =>
action(DBRequest(session, request))
}
}
}
object MyController extends Controller with DBController {
def myAction = DBAction { implicit request =>
println(session)
}
}
#senia was right, currying needs to be used to do this. This is actually addressed in the Play docs but it's a recent addition I missed.
For future reference for people looking for this, my custom action now looks like this:
def DBAction(action: Request[AnyContent] => Session => Result) = {
Action { request =>
database.withSession { session =>
action(request)(session)
}
}
}
Which I can then use in the following way:
def someAction = DBAction { implicit request => implicit session => /* body */ }