No QueryString binder found for type Option[java.util.UUID]

3,100 views
Skip to first unread message

Drew Kutcharian

unread,
Apr 30, 2012, 9:55:17 PM4/30/12
to play-fr...@googlegroups.com
Hi All,

I'm getting "No QueryString binder found for type Option[java.util.UUID]" even though I have an implicit QueryStringBinder for UUID in scope. Do I need to create a separate binder for Option[UUID]? How does Play's bindableOption work then?

Here's the compiler output

[error] /Users/drew/Projects/Shopper/workspace/Shopper/target/scala-2.9.1/src_managed/main/routes_reverseRouting.scala:231: No QueryString binder found for type Option[java.util.UUID]. Try to implement an implicit QueryStringBindable for this type.
[error] Call("GET", Routes.prefix + { if(Routes.prefix.endsWith("/")) "" else "/" } + "api/circles/" + implicitly[PathBindable[UUID]].unbind("cid", cid) + "/connections" + queryString(List(if(from == None) None else Some(implicitly[QueryStringBindable[Option[UUID]]].unbind("from", from)), if(limit == None) None else Some(implicitly[QueryStringBindable[Option[Int]]].unbind("limit", limit)))))
[error] ^
[error] /Users/drew/Projects/Shopper/workspace/Shopper/target/scala-2.9.1/src_managed/main/routes_reverseRouting.scala:893: No JavaScript litteral binder found for type Option[java.util.UUID]. Try to implement an implicit JavascriptLitteral for this type.
[error] return _wA({method:"GET", url:"""" + Routes.prefix + { if(Routes.prefix.endsWith("/")) "" else "/" } + """" + "api/circles/" + (""" + implicitly[PathBindable[UUID]].javascriptUnbind + """)("cid", cid) + "/connections" + _qS([(from == """ + implicitly[JavascriptLitteral[Option[UUID]]].to(None) + """ ? null : (""" + implicitly[QueryStringBindable[Option[UUID]]].javascriptUnbind + """)("from", from)), (limit == """ + implicitly[JavascriptLitteral[Option[Int]]].to(None) + """ ? null : (""" + implicitly[QueryStringBindable[Option[Int]]].javascriptUnbind + """)("limit", limit))])})
[error] ^
[error] /Users/drew/Projects/Shopper/workspace/Shopper/target/scala-2.9.1/src_managed/main/routes_routing.scala:537: No QueryString binder found for type Option[java.util.UUID]. Try to implement an implicit QueryStringBindable for this type.
[error] call(params.fromPath[UUID]("cid", None), params.fromQuery[Option[UUID]]("from", Some(None)), params.fromQuery[Option[Int]]("limit", Some(None))) { (cid, from, limit) =>
[error] ^



Thanks,

Drew


Julien Richard-Foy

unread,
May 1, 2012, 3:52:14 AM5/1/12
to play-fr...@googlegroups.com
Hi,
It should work. How are you sure there is an implicit
QueryStringBindable[UUID] available in your scope?
Regards.

Drew Kutcharian

unread,
May 1, 2012, 4:00:49 AM5/1/12
to play-fr...@googlegroups.com
Hi Julien,

I'm importing a QueryStringBindable[UUID] using routesImport in Build.scala. I also looked at the generated Routes Scala class and my imports were imported at the top. I even tried making a QueryStringBindable[Option[UUID]] and that didn't work also. I pretty much followed your blog post regarding PathBindables. Are QueryStringBindables any different?

- Drew
> --
> You received this message because you are subscribed to the Google Groups "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.
>

Julien Richard-Foy

unread,
May 1, 2012, 4:14:59 AM5/1/12
to play-fr...@googlegroups.com
It should work, can you paste the code showing how is the
QueryStringBindable defined (including its package declaration) and
how is the route defined?

dres

unread,
Nov 13, 2012, 12:02:00 PM11/13/12
to play-fr...@googlegroups.com
I have the same issue with a scala binder in a java project.  Is that possible?

Build.scala:
<code>
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(

// Add your own project settings here

routesImport += "binders._"

)
</code>

binders/CustomBinders.scala:
<code>

package binders;


import org.joda.time.DateTime

import java.util.Date

import java.text.SimpleDateFormat

import play.api.mvc.QueryStringBindable

import java.net.URLEncoder

import org.joda.time.format.DateTimeFormat

import org.joda.time.DateTimeZone


object CustomBinders {


  implicit def dateTimeQueryBinder = new QueryStringBindable[DateTime] {

  def bind(key: String, params: Map[String, Seq[String]]) = 

   

    params.get(key).flatMap(_.headOption).map { s =>

    try {

      val formatter = new SimpleDateFormat(

"EEE, d MMM yyyy HH:mm:ss z");

val someDate = formatter.parse(s);

      Right(new DateTime(someDate.getTime(),DateTimeZone.UTC))

    } catch {

      case e: NumberFormatException => Left("Cannot parse parameter " + key + " as Int: " + e.getMessage)

    }

  }

  def unbind(key: String, value: DateTime) = {

    val fmt = DateTimeFormat

.forPattern("EEE, d MMM yyyy HH:mm:ss z");

    key + "=" + (URLEncoder.encode(fmt.print(value), "utf-8"))

  }


  }

}

</code>

dres

unread,
Nov 13, 2012, 12:05:21 PM11/13/12
to play-fr...@googlegroups.com
Sorry, it's 
routesImport += "binders.CustomBinders._"

I know the scala is being compiled because if I can file compilation of my implicit binder def with a typo.

James Roper

unread,
Nov 14, 2012, 7:33:04 PM11/14/12
to play-fr...@googlegroups.com
I think it actually should be:

routesImport ++= "binders.CustomBinders._"

If that doesn't work, then in target/scala-2.9.1/src_managed/main you should find the two compile routes files, routes_reverseRouting.scala and routes_routing.scala.

Can you check that your routes import is somewhere at the top of those files?  If it is, then could you paste the logs of the compile error?

dres

unread,
Nov 15, 2012, 4:44:21 PM11/15/12
to play-fr...@googlegroups.com
Still a failure:

[info] Compiling 3 Scala sources and 2 Java sources to /Users/andres/source/plaor-git/hwp-bi/target/scala-2.9.1/classes...
[error] /Users/andres/source/plaor-git/hwp-bi/target/scala-2.9.1/src_managed/main/routes_reverseRouting.scala:68: No QueryString binder found for type org.joda.time.DateTime. Try to implement an implicit QueryStringBindable for this type.
[error]    Call("GET", "/tables/clicks" + queryString(List(Some(implicitly[QueryStringBindable[org.joda.time.DateTime]].unbind("startDateTime", startDateTime)))))
[error]                                                                   ^
[error] /Users/andres/source/plaor-git/hwp-bi/target/scala-2.9.1/src_managed/main/routes_reverseRouting.scala:220: No QueryString binder found for type org.joda.time.DateTime. Try to implement an implicit QueryStringBindable for this type.
[error]       return _wA({method:"GET", url:"/tables/clicks" + _qS([(""" + implicitly[QueryStringBindable[org.joda.time.DateTime]].javascriptUnbind + """)("startDateTime", startDateTime)])})
[error]                                                                              ^
[error] /Users/andres/source/plaor-git/hwp-bi/target/scala-2.9.1/src_managed/main/routes_routing.scala:96: No QueryString binder found for type org.joda.time.DateTime. Try to implement an implicit QueryStringBindable for this type.
[error]    call(params.fromQuery[org.joda.time.DateTime]("startDateTime", None)) { (startDateTime) =>
[error]                                                 ^
[error] three errors found
[error] {file:/Users/andres/source/plaor-git/hwp-bi/}hwp-bi/compile:compile: Compilation failed
[error] application - 

! Internal server error, for request [GET /] ->

sbt.PlayExceptions$CompilationException: Compilation error [No QueryString binder found for type org.joda.time.DateTime. Try to implement an implicit QueryStringBindable for this type.]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$4$$anonfun$apply$12$$anonfun$apply$13.apply(PlayReloader.scala:236) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$4$$anonfun$apply$12$$anonfun$apply$13.apply(PlayReloader.scala:236) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.3]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$4$$anonfun$apply$12.apply(PlayReloader.scala:236) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$4$$anonfun$apply$12.apply(PlayReloader.scala:233) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.3]

It looks like the import isn't including the object in the import path:

import play.core._
import play.core.Router._
import play.core.j._

import play.api.mvc._
import play.libs.F
--> import binders._

import Router.queryString

object Routes extends Router.Routes {

dres

unread,
Nov 16, 2012, 11:19:00 AM11/16/12
to play-fr...@googlegroups.com
I figured it out, I think.  The routes don't seem to get regenerated unless I run play clean.  I had the wrong route like you pointed out but I had tried importing the object before and it didn't work.  Thanks for pointing me to the generated scala code. It wasn't getting updated just by exiting the console and restarting play run.  Is this a bug or expected behavior?

James Roper

unread,
Nov 16, 2012, 8:59:46 PM11/16/12
to play-fr...@googlegroups.com
This is expected behaviour... the routes classes are regenerated if the routes file changes.  Changing any configuration in Build.scala will usually require a clean to ensure that it takes effect.

Andres March

unread,
Nov 17, 2012, 6:38:10 PM11/17/12
to play-fr...@googlegroups.com
Any chance you would take a enhancement request to change that behavior? It seems contrary to most development cycles to have to clean when the project build file is changed IMHO.  I'd at least like to contribute to the documentation to clarify the lifecycle.  I may have just missed but I haven't seen much on the topic.


--
 
 

James Roper

unread,
Nov 18, 2012, 11:27:26 PM11/18/12
to play-fr...@googlegroups.com
I don't think it is contrary... and I don't know any other build tools that work any different.  For example, if you were using Maven, and you changed the target JVM version in the configuration, and then did a normal build, it wouldn't recompile anything.  If you remove a dependency in SBT or maven, and then build, again, it won't recompile anything, it's not until you do a clean build that it breaks.  The reason why things behave this way is that there's no way for the build tool to know which changes to your build configuration should require a clean build, only you can know this, so the build tool has two options, always do a clean build when the build configuration changes, or trust you to know what you're doing.  Personally, I'd rather the build tool trust me and only do a (much slower) clean build when I tell it to.

Andres March

unread,
Nov 18, 2012, 11:45:21 PM11/18/12
to play-fr...@googlegroups.com
I agree with your point about the build tool trusting the user and we can leave it at that.  But I think source code generation is a whole different ball game than changing dependencies or runtime.  In both your examples if the source code had changed as it must for the routes, the code would be recompiled.  Just my perspective.  Thanks again for your help.



--
 
 

Reply all
Reply to author
Forward
0 new messages