0

I would like to create a custom action which takes away the boilerplate of writing actions like this:

Action[MyClass](BodyParsers.parse.json[MyClass]) { req => ...

However, I keep running into class definition errors. Here has been my most successful attempt:

class JsonAction[A: Reads] extends ActionBuilder[Request] {
  def hardcodedJson[A: Reads](action: Action[A]) = 
    Action.async(BodyParsers.parse.json[A]) { request => action(request) }

  def invokeBlock[A: Reads](request: Request[A], block: (Request[A]) => Future[Result]) = {
    block(request)
  }
  override def composeAction[A: Reads](action: Action[A]) = hardcodedJson(action)
}

but I get the following error: method composeAction overrides nothing.

If I change composeAction[A: Reads] to composeAction[A] it tells me there isn't a Json Serializer for type A.

Is there some other way to define this custom action?

TheDarkSaint
  • 457
  • 3
  • 13

2 Answers2

1

Yep, I tried to get this to work with the official ActionBuilder way-of-doing-it and just could not get the types to line up.

Here's something that worked for me though:

object JsonActionHelper {
  def withReads[A](act: Request[A] => Future[Result])(implicit reads:Reads[A]) = 
    Action.async(BodyParsers.parse.json(reads))(act)
}

Usage in your controller (FooJson is an object containing an implicit Reads[Foo]):

import models.FooJson._
import JsonActionHelper._

def handleIncomingFoo(fooId:String) = withReads[Foo] { req =>
  val foo:Foo = req.body
  ...
  Ok(...)
}
millhouse
  • 9,817
  • 4
  • 32
  • 40
1

ActionBuilder is not generic enough for your use-case; there's nowhere for you to pass in your Reads[T].

There's nothing special about ActionBuilder though. It's a collection of apply and async factory methods. You can define your own Action type with whatever factory methods you need:

object JsonAction {
  def apply[A : Reads](request: Request[A] => Result) = Action(BodyParsers.parse.json[A])(request)
}

// these are equivalent:
Action[MyClass](BodyParsers.parse.json[MyClass]) { req => ??? }
JsonAction[MyClass] { req => ??? }
dwickern
  • 3,519
  • 1
  • 14
  • 21