Skip to content
This repository has been archived by the owner on Nov 24, 2021. It is now read-only.

QueryParam of Option of scala primitive results in error #22

Open
joekarl opened this issue Nov 4, 2017 · 3 comments
Open

QueryParam of Option of scala primitive results in error #22

joekarl opened this issue Nov 4, 2017 · 3 comments

Comments

@joekarl
Copy link
Contributor

joekarl commented Nov 4, 2017

Been scratching my head at this one for a bit now after doing an upgrade from the old massrelevance version to the datasift maintained version.

Specifically the error I'm running into is whenever I try to add something like QueryParam("foo") foo: Option[Int] to a resource.

I've done some digging, and similar combinations of QueryParam("foo") foo: Option[java.lang.Integer] and QueryParam("foo") foo: Int work as expected.

This can be replicated by adding the following test/resource to ScalaApplicationSpecIT.scala (and actually just adding that resource path with the parameter Option[Int] will fail validation of the resource on test suite startup.

--- a/core/src/test/scala/com/datasift/dropwizard/scala/ScalaApplicationSpecIT.scala
+++ b/core/src/test/scala/com/datasift/dropwizard/scala/ScalaApplicationSpecIT.scala
@@ -37,6 +37,15 @@ case class ScalaTestConfiguration(
   def greetOrNotFound(@QueryParam("name") name: Option[String]): Option[List[String]] =
     name.map(greeting.format(_)).map(List(_))

+
+  @GET @Path("/opt-int-param")
+  def greetWithOptionInt(@QueryParam("i") i: Option[Int]): Option[Int] =
+    i
+
   @GET @Path("/option")
   def greetWithOption(@QueryParam("name") name: Option[String]): List[String] =
     name.map(greeting.format(_)).toList
@@ -313,6 +322,28 @@ class ScalaApplicationSpecIT extends FlatSpec with BeforeAndAfterAllMulti {
     assert(result === Success(expected))
   }

+
+  "GET /opt-int-param" should "yield results" in {
+    val fixture = 2
+    val expected = Option(2)
+    val result = request("/opt-int-param").map {
+      _.queryParam("i", fixture.toString)
+        .request(MediaType.APPLICATION_JSON)
+        .get(classOf[Option[Int]])
+    }
+    assert(result === Success(expected))
+  }
+
   "GET /complex_scala" should "yield results" in {
     val fixture: Set[BigDecimal] = Set(BigDecimal(1), BigDecimal(2))
     val expected = 2

I think this has something to do with some weirdness with either type resolution or erasure as by introspecting ScalaParamConvertersProvider during test time the call to getConverter as the parameter type is being listed at type=class scala.Option and the generic type at runtime is scala.Option[java.lang.Object]

Actual error the container spits out

Caused by: org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public scala.Option com.datasift.dropwizard.scala.ScalaTestResource.greetWithOptionInt(scala.Option) at index 0.; source='ResourceMethod{httpMethod=GET, consumedTypes=[application/json], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.datasift.dropwizard.scala.ScalaTestResource, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@6097f225]}, definitionMethod=public scala.Option com.datasift.dropwizard.scala.ScalaTestResource.greetWithOptionInt(scala.Option), parameters=[Parameter [type=class scala.Option, source=i, defaultValue=null]], responseType=scala.Option<java.lang.Object>}, nameBindings=[]}']
@joekarl
Copy link
Contributor Author

joekarl commented Nov 4, 2017

Unsurprisingly the same behavior is noted with scala Longs and Booleans.

@anant-indix
Copy link

anant-indix commented Nov 21, 2017

Option[java.lang.Long] is working but not Option[scala.Long] because
java.lang.Long implements java.lang.reflect.Type
whereas scala.Long doesn't

com.datasift.dropwizard.scala.jersey.inject.ScalaParamConvertersProvider overrides method
override def getConverter[T](rawType: Class[T], genericType: Type, annotations: Array[Annotation]): ParamConverter[T] = {
So essentially none of the native classes in "scala" package would work.

@G1GC
Copy link

G1GC commented Nov 21, 2017

Essentially, we need reflection compatibility between scala types and java types, to get the above to work, I guess - there's an open ticket - https://issues.scala-lang.org/browse/SI-7317

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants