I wrote a small service with Scalatra that does two things:
- serve JSON data
- serve same data as an Excel sheet
JSON is done with spray-json, Excel - with apache POI
Basically, I wrote two methods in my ScalatraServlet implementation:
def serveJson[T: JsonWriter](data: T) = {
contentType = "text/json"
data.toJson.prettyPrint
}
def serveExcel[T: ExcelWriter](data: T) = {
contentType = "application/excel"
data.toExcel.getBytes
}
Here, toJson is implemented with spray-json, so I just provide a JsonWriter implicit conversion. So I decided to write a similar toExcel conversion.
// ExcelWriter.scala
package com.example.app.excel
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import annotation.implicitNotFound
@implicitNotFound(msg = "Cannot find ExcelWriter type class for ${T}")
trait ExcelWriter[T] {
def write(obj: T): HSSFWorkbook
}
object ExcelWriter {
implicit def func2Writer[T](f: T => HSSFWorkbook): ExcelWriter[T] = new ExcelWriter[T] {
def write(obj: T) = f(obj)
}
}
// Imports.scala
package com.example.app.excel
import org.apache.poi.hssf.usermodel.HSSFWorkbook
object Imports {
type ExcelWriter[T] = com.example.app.excel.ExcelWriter[T]
implicit def pimpAny[T](any: T) = new AnyExcelPimp(any)
private[excel] class AnyExcelPimp[T](any: T) {
def toExcel(implicit writer: ExcelWriter[T]): HSSFWorkbook = writer.write(any)
}
}
Now, the problem is:
If I import import cc.spray.json._
, then import excel.Imports._
, scalac throws error in serveJson
(value toJson is not a member of type parameter T)
If I import import excel.Imports._
, then import cc.spray.json._
, scalac throws analogous error in serveExcel
(value toExcel is not a member of type parameter T)
Surprisingly, if I use only one of the imports, everything compiles and works just fine (well, half of it, since I comment out the half, that uses removed import).
What is wrong with my implementation?
Link to spray-json source, which I used as a reference: https://github.com/spray/spray-json/tree/master/src/main/scala/cc/spray/json
Scala version - 2.9.2