I have a case class in the model package called CoordinatesTranslationDTO:
case class CoordinatesTranslationDTO(locale: String, lat: BigDecimal, lng: BigDecimal)
I'm importing this in the QueryStringBinders controller like so:
import models.CoordinatesTranslationDTO
My implementation of the object in the QueryStringBinders controller looks like this:
object QueryStringBinders {
implicit def coordinatesTranslationStringBinder(
implicit bigDecimalBinder: QueryStringBindable[BigDecimal],
stringBinder: QueryStringBindable[String]
): QueryStringBindable[CoordinatesTranslationDTO] =
new QueryStringBindable[CoordinatesTranslationDTO] {
private def subBind[T](key: String, subkey: String, params: Map[String, Seq[String]])
(implicit b: QueryStringBindable[T]): Either.RightProjection[String, Option[T]] = {
b.bind(s"$key.$subkey", params).map(_.right.map(r => Option(r))).getOrElse(Right(None)).right
}
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, CoordinatesTranslationDTO]] = Some {
def bnd[T](s: String)(implicit b: QueryStringBindable[T]) = subBind[T](key, s, params)
for {
locale <- bnd[String]("locale")
lat <- bnd[BigDecimal]("lat")
lng <- bnd[BigDecimal]("lng")
} yield CoordinatesTranslationDTO(locale, lat, lng)
}
override def unbind(key: String, coordinates: CoordinatesTranslationDTO): String = {
def ubnd[T](key: String, s: Option[T])(implicit b: QueryStringBindable[T]) = s.map(f => b.unbind(key, f))
val keys = Seq(
ubnd("lat", coordinates.lat),
ubnd("lng", coordinates.lng),
ubnd("locale", coordinates.locale)
).flatten
keys.mkString("&")
}
}
}
And my route in the routes file looks like this:
GET /people/translation controllers.PeopleController.getOrCreatePersonLocation(p: models.CoordinatesTranslationDTO)
I already run sbt clean, set cleanFiles and God knows how many commands more. But nothing seems to work. All I get is:
[error] /Users/developmentuser/Desktop/Jobs/parent/solar/conf/routes:269:1: No QueryString binder found for type models.CoordinatesTranslationDTO. Try to implement an implicit QueryStringBindable for this type
I think the problem is actually that Play can't find an implicit
QueryStringBindable[BigDecimal], which is required for yourcoordinatesTranslationStringBinder.The error message is misleading. It is generated by the following code in Play, which cannot distinguish between either i)
QueryStringBindable[A]not being implemented at all, or ii) there is an implementation ofQueryStringBindable[A]but its implicit requirements cannot be met:I had the same problem and had to figure out what was going on by reading the source closely then narrow it down by calling for each of my implicitly provided sub-binders one by one until I found the culprit. Too much magic!
(You can implement a binder for
BigDecimalusing theParsinghelper class frommvc/Binders.scala.)I can't see how Play can easily fix this error message. Perhaps they could just add "(or its implicit dependencies cannot be resolved)" to this message.