No QueryString binder found for type Double. Try to implement an implicit QueryStringBindable for this type

java, playframework-2.0

Solution

In Play 2.0 I found the easiest solution was to use Scala - even in a Java project (I explained this in one of my Play Basics blog posts.

If you don't know Scala, just paste the following in a file called `Binders.scala` and add `routesImport += "util.Binders._"` to your `Build.scala`.

package util

object Binders {

  implicit object DoubleQueryBindable extends QueryStringBindable[Double] {
    def bind(key: String, params: Map[String, Seq[String]]) = params.get(key).flatMap(_.headOption).map { value =>
      try {
        Right(value.toDouble)
      } catch {
        case e: Exception =>  Left("Cannot parse parameter " + key + " as Double")
      }
    }
    def unbind(key: String, value: Double) = key + "=" + value.toString
  }

  implicit object DoublePathBindable extends PathBindable[Double] {
    def bind(key: String, value: String) = try {
      Right(value.toDouble)
    } catch {
      case e: Exception => Left("Cannot parse parameter '" + key + "' as Double")
    }

    def unbind(key: String, value: Double): String = value.toString
  }
}

Problem

So I am using play 2.0 and I am trying to pass doubles from my view back to controller application and I get this error: No QueryString binder found for type Double. Try to implement an implicit QueryStringBindable for this type. I found this thread and see that java binders only work with self-recursive types in play 2.0 but they will be supported in play 2.1. Unfortunately I am not in a position to migrate my project to 2.1 so I tried to follow the answer to the question linked. I created a util package in my project and inside it is the DoubleW class: ``` package util; import java.util.Map; import play.libs.F; import play.libs.F.Option; import play.mvc.QueryStringBindable; public class DoubleW implements QueryStringBindable<DoubleW> { public Double value = null; @Override public Option<DoubleW> bind(String key, Map<String, String[]> data) { String[] vs = data.get(key); if (vs != null && vs.length > 0) { String v = vs[0]; value = Double.parseDouble(v); return F.Some(this); } return F.None(); } @Override public String unbind(String key) { return key + "=" + value; } @Override public String javascriptUnbind() { return value.toString(); } } ``` I imported this where it was needed in the controller/application and one of the model classes where I need to use doubles. I replaced the double data types with the new DoubleW in the application and model methods concerned. Finally I modified my routing table so it would expect the new parameters: GET /findMatch controllers.Application.matcher(sLat: util.DoubleW, sLon: util.DoubleW, eLat: util.DoubleW, eLon: util.DoubleW) Inside the model method which the Application matcher method uses I need to perform arithmetic. However when I run my project I get this error: error: bad operand types for binary operator '<='. It seems this new type to handle doubles (DoubleW) is regarded as a string, I cannot perform arithmetic on it and I can not assign a standard java double its value. I am not sure if I have missed a step in the previous post but I am rather lost on what to do.

Original source

Related problems