Im using play2 and seem to do the following alot:
def someFunction(request: RequestHeader) = {...}
is there a way to implicitly define the request so that I don't have to always pass it in to various functions that require having the request?
thanks.
You should use implicits, that way you dont have to pass the request explicitly.
def index = Action { implicit req =>
someOtherFunction("hi")
Ok(someFunction)
}
def someFunction(implicit request: RequestHeader) = {...}
def someOtherFunction(otherArgs:String)(implicit req: RequestHeader) = { .. }
Related
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
I've built a microservice using Scala and Play and now I need to create a new version of the service that returns the same data as the previous version of the service but in a different JSON format. The service currently uses implicit Writes converters to do this. My controller looks something like this, where MyJsonWrites contains the implicit definitions.
class MyController extends Controller with MyJsonWrites {
def myAction(query: String) = Action.async {
getData(query).map {
results =>
Ok(Json.toJson(results))
}
}
}
trait MyJsonWrites {
implicit val writes1: Writes[SomeDataType]
implicit val writes2: Writes[SomeOtherDataType]
...
}
Now I need a new version of myAction where the JSON is formatted differently. The first attempt I made was to make MyController a base class and have subclasses extend it with their own trait that has the implicit values. Something like this.
class MyNewContoller extends MyController with MyNewJsonWrites
This doesn't work though because the implicit values defined on MyNewJsonWrites are not available in the methods of the super class.
It would be ideal if I could just create a new action on the controller that somehow used the converters defined in MyNewJsonWrites. Sure, I could change the trait to an object and import the implicit values in each method but then I'd have to duplicate the method body of myAction so that the implicits are in scope when I call Json.toJson. I don't want to pass them as implicit parameters to a base method because there are too many of them. I guess I could pass a method as a parameter to the base method that actually does the imports and Json.toJson call. Something like this. I just thought maybe there'd be a better way.
def myBaseAction(query: String, toJson: Seq[MyResultType] => JsValue) = Action.async {
getData(query).map {
results =>
Ok(Json.toJson(results))
}
}
def myActionV1(query: String) = {
def toJson(results: Seq[MyResultType]) = {
import MyJsonWritesV2._
Json.toJson(results)
}
myBaseAction(query, toJson)
}
Instead of relying on scala implicit resolution, you can call your writes directly:
def myBaseAction(query: String, writes: Writes[MyResultType]) = Action.async {
getData(query).map { results =>
val seqWrites: Writes[Seq[MyResultType]] = Writes.seq(writes)
Ok(seqWrites.writes(results))
}
}
def myActionV1(query: String) = myBaseAction(query, MyJsonWritesV1)
def myActionV2(query: String) = myBaseAction(query, MyJsonWritesV2)
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.
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 */ }