joesan
joesan

Reputation: 15385

Play Framework Async Response Error

I have a Play framework controller method that returns either a Byte Array or a String based on the request header. Here is what it looks like:

  def returnResponse = Action(parse.anyContent) {
    request =>
      println(request.body)
      val buffer: RawBuffer = request.body.asRaw.get
      val js: String  = buffer.asBytes() match {
        case Some(x) => new String(x, "UTF-8")
        case None => scala.io.Source.fromFile(buffer.asFile).mkString
      }

      val resultJsonfut = scala.concurrent.Future { serviceCall.run(js) }

      Async {
        resultJsonfut.map(s => {
          val out = if(request.headers.toSimpleMap.exists(_ == (CONTENT_ENCODING, "gzip"))) getBytePayload(s) else s
          Ok(out)
        })
      }
  }

I do not see any error in IntelliJ, but when I compile it, it fails with the following error:

Cannot write an instance of java.io.Serializable to HTTP response. Try to define a Writeable[java.io.Serializable]

Why is that? But however if I modify it a little bit to look like as below:

  Async {
    if(request.headers.toSimpleMap.exists(_ == (CONTENT_ENCODING, "gzip"))) {
      resultJsonfut.map(s => Ok(getBytePayload(s)))
    } else {
        resultJsonfut.map(s => Ok(s))
    }
  }

It compiles fine. Any reasons why it behaves this way?

Upvotes: 2

Views: 841

Answers (1)

serejja
serejja

Reputation: 23851

This happens because the return types of getBytePayload(s) and s are different. Consider the simplier example:

val test = if (true) "1" else 0

The type of test value will be Any. In general the if-else in Scala produces the value and the type of this value will be the common type for both statements.

So considering the Int type hierarchy looks like this: Int --> AnyVal --> Any and the String type hierarchy looks like this: String --> AnyRef --> Any the first common type for them is Any and in your case it seems to be a Serializable

Upvotes: 1

Related Questions