1

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

F0RR
  • 1,590
  • 4
  • 16
  • 30

1 Answers1

1

The problem seems to be that I used the same name for implicit conversion as the one used in spray-json: pimpAny.

// my implicit
implicit def pimpAny[T: ExcelWriter](any: T) = new AnyExcelPimp(any)

// spray-json implicit
implicit def pimpAny[T](any: T) = new PimpedAny(any)

So a simple rename solved the problem.

Still, kinda strange to not see the root problem but its result at compile time. Guess I'm to sleepy...

F0RR
  • 1,590
  • 4
  • 16
  • 30