title: Generic type for play case classes
body: <p>I am using play 2.2.0 built with Scala 2.10.2 (running Java 1.7.0_45).  Most of the routes/endpoints in my application receive a json request, parse parse the data into a case class using a form and then do business logic on the received data.  I have abstracted this.  It works, but one thing I don't like is that I am casting the case class instance to java.lang.Object.  Then, the specific handler function has to re-cast the case class instance back to its original type.  </p>
  
  <p>I'm pretty new to play/scala.  Is there a cleaner way in scala to change the signature on my handler function so that casting isn't necessary.  It feels wrong to have to cast and then re-cast back.  Perhaps this is just the price of abstraction in this case (no pun intended)?</p>
  
  <p>The code below has:</p>
  
  <ol>
  <li>The RefreshTokenController which calls the plumbing method.  Notice the unnecessary cast.</li>
  <li>The ControllerUtil.handleJsonRequest method which does an unnecessary cast.</li>
  </ol>
  
  <p>I think what I'm looking for is correct usage of scala generics.  This doesn't compile, but something like:</p>
  
  <pre>
      def handleJsonRequest(form: Form[T], handlerFunction: (T) => SimpleResult, request: Request[Object]):     SimpleResult {
  </pre>
  
  <p>Look for the "TODO" comments in the code below.  Bonus points if you have a better, more "play-like" way of abstracting the parsing and business logic.  For example, should I have my own application specific Action?</p>
  
  <pre><code>{"paramA": "paramA_Value", "paramB": "paramB_Value"}
  
  
  object RefreshTokenController extends Controller {
  
    private case class RequestData(paramA: String, paramB: String)
  
    private val requestForm = Form(
      mapping(
        "paramA" -&gt; nonEmptyText,
        "ParamB" -&gt; nonEmptyText
      )(RequestData.apply)(RequestData.unapply)
    )
  
    def myEndPoint = Action(ControllerUtil.formOrJsonParser) {
      request =&gt;  {
        val response = ControllerUtil.handleJsonRequest(requestForm, requestHandlerFunction, request)
        response
      }
    }
  
    val requestHandlerFunction: (Object) =&gt; SimpleResult = processRequest
  
    def processRequest(refreshDataObj: Object) : SimpleResult = {
      //TODO: Yuck, how can I get rid of the unnecessary cast
      val refreshData: RequestData = refreshDataObj.asInstanceOf[RequestData]
  
      //Business logic removed since it's not relevant
    }
  }
  
  
  object ControllerUtil {
  
    /**
     * Handles the plumbing of parsing a json request and applying business logic.
     */
    def handleAsyncJsonRequest(form: Form[_],
      handlerFunction: (Object) =&gt; Future[SimpleResult],
      request: Request[Object]): Future[SimpleResult] = {
      // Convert the request body to JSON even if using URL-Form-Encoding
      val formData: Object = parseUsingForm(form, request)
      handlerFunction(formData)
    }
  
    /**
     * Handles the plumbing of parsing a json request and applying business logic.
     *
     */
    def handleJsonRequest(form: Form[_],
      handlerFunction: (Object) =&gt; SimpleResult,
      request: Request[Object]): SimpleResult = {
      //TODO: How can I change the function signature so I can avoid casting/recasting.
      val formData: Object = parseUsingForm(form, request)
      handlerFunction(formData)
    }
  
    def parseUsingForm(form: Form[_], request: Request[Object]): Object = {
      val jsonData: JsValue = parseRequestToJson(request)
      parseUsingForm(form, jsonData)
    }
  
    def parseUsingForm(form: Form[_], jsData: JsValue): Object = {
      form.bind(jsData).fold(
        formWithErrors =&gt; {
          val error = Results.BadRequest(formWithErrors.errorsAsJson)
          throw new UserErrorException(error)
        },
        parsedData =&gt; {
          //TODO: Yuck, I don't like having to cast here.
          val formData: Object = parsedData.asInstanceOf[Object]
          formData
        }
      )
    }
  
    def parseRequestToJson(request: Request[Object]): JsValue = {
      var jsonLoginRequest: JsValue = null
      request.body match {
        case json: JsObject =&gt; jsonLoginRequest = json
        case form: Map[String, Seq[String]] =&gt; jsonLoginRequest = Json.toJson(form.map {
          case (k, v) =&gt; (k, v.head)
        })
      }
  
      jsonLoginRequest
    }
  
    /**
     *  parse html encoded form containing json data or String json data
     */
    val formOrJsonParser = parse.using {
      request =&gt;
        request.contentType.map(_.toLowerCase(Locale.ENGLISH)) match {
          case Some("application/json") | Some("text/json") =&gt; parse.json
          case Some("application/x-www-form-urlencoded") | Some("text/x-www-form-urlencoded") =&gt;
            parse.urlFormEncoded
          case _ =&gt;
            parse.error(Future.successful(Results.UnsupportedMediaType("Invalid content type specified")))
        }
    }
  }
  </code></pre>