This repository has been archived by the owner. It is now read-only.

Exception with case classes nested within case classes #67

Open
jxtps opened this Issue Aug 8, 2012 · 5 comments

Comments

Projects
None yet
2 participants
@jxtps

jxtps commented Aug 8, 2012

For a Play framework project I'm trying to parse nested case classes like so:

case class Inner(foo: String, bar: Int)
case class Outer(hello: String, world: Inner)
val o = Outer("adam", Inner("eve", 4))
val oJson = com.codahale.jerkson.Json.generate(o)
val o2 = com.codahale.jerkson.Json.parse\[Outer\]\(oJson\)

This breaks on the last line with an exception:

Caused by: org.codehaus.jackson.map.JsonMappingException: Unable to find a case accessor for controllers.Outer
at com.codahale.jerkson.deser.CaseClassDeserializer$$anonfun$4.apply(CaseClassDeserializer.scala:39) ~[jerkson_2.9.1.jar:na]
at com.codahale.jerkson.deser.CaseClassDeserializer$$anonfun$4.apply(CaseClassDeserializer.scala:39) ~[jerkson_2.9.1.jar:na]

(at least when I run it within Play, see: https://groups.google.com/d/msg/play-framework/MKNPYOj9LBA/Ll6Fch98ZBkJ )

The issue seems to stem from: https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala#L36 where it looks like it doesn't find the relevant constructor?

???

@imikushin

This comment has been minimized.

Show comment
Hide comment
@imikushin

imikushin Aug 9, 2012

Contributor

Try to use Jerkson from git master branch. For that you should use the following dependencies:

"org.codehaus.jackson" % "jackson-core-asl" % "1.9.8",
"org.codehaus.jackson" % "jackson-mapper-asl" % "1.9.8",
"com.codahale" %% "jerkson" % "0.7.0-SNAPSHOT"

jackson-core-asl and jackson-mapper-asl are needed for Play Framework. Jerkson (master HEAD) uses Jackson 2.

Contributor

imikushin commented Aug 9, 2012

Try to use Jerkson from git master branch. For that you should use the following dependencies:

"org.codehaus.jackson" % "jackson-core-asl" % "1.9.8",
"org.codehaus.jackson" % "jackson-mapper-asl" % "1.9.8",
"com.codahale" %% "jerkson" % "0.7.0-SNAPSHOT"

jackson-core-asl and jackson-mapper-asl are needed for Play Framework. Jerkson (master HEAD) uses Jackson 2.

@imikushin

This comment has been minimized.

Show comment
Hide comment
@imikushin

imikushin Aug 9, 2012

Contributor

Actually, this issue arises if the case classes are inner classes: in classes, objects or package objects. Move your case classes to the outer space :)

Contributor

imikushin commented Aug 9, 2012

Actually, this issue arises if the case classes are inner classes: in classes, objects or package objects. Move your case classes to the outer space :)

@jxtps

This comment has been minimized.

Show comment
Hide comment
@jxtps

jxtps Aug 9, 2012

The case classes are defined in "the outer space" (see the code snippet on https://groups.google.com/forum/#!msg/play-framework/MKNPYOj9LBA/Ll6Fch98ZBkJ%5B1-25%5D ).

Tried adding those dependencies, but despite adding:

resolvers += "CodaHale repository" at "http://repo.codahale.com"

to my plugins.sbt, sbt doesn't check repo.codahale.com which is very weird (see http://www.playframework.org/documentation/2.0/Repositories ).

Regardless though, there doesn't seem to be a 0.7.0-SNAPSHOT in that repo: http://repo.codahale.com/com/codahale/jerkson_2.9.1/

jxtps commented Aug 9, 2012

The case classes are defined in "the outer space" (see the code snippet on https://groups.google.com/forum/#!msg/play-framework/MKNPYOj9LBA/Ll6Fch98ZBkJ%5B1-25%5D ).

Tried adding those dependencies, but despite adding:

resolvers += "CodaHale repository" at "http://repo.codahale.com"

to my plugins.sbt, sbt doesn't check repo.codahale.com which is very weird (see http://www.playframework.org/documentation/2.0/Repositories ).

Regardless though, there doesn't seem to be a 0.7.0-SNAPSHOT in that repo: http://repo.codahale.com/com/codahale/jerkson_2.9.1/

@imikushin

This comment has been minimized.

Show comment
Hide comment
@imikushin

imikushin Aug 9, 2012

Contributor

You could place it to your own repo. Here is mine (that's what I have in build.sbt):

resolvers += Resolver.url(
  "Local repository", url("http://dl.dropbox.com/u/24364253/repo/local-IHRmxcxtp7/")
)(Resolver.ivyStylePatterns)
Contributor

imikushin commented Aug 9, 2012

You could place it to your own repo. Here is mine (that's what I have in build.sbt):

resolvers += Resolver.url(
  "Local repository", url("http://dl.dropbox.com/u/24364253/repo/local-IHRmxcxtp7/")
)(Resolver.ivyStylePatterns)
@jxtps

This comment has been minimized.

Show comment
Hide comment
@jxtps

jxtps Aug 10, 2012

I have debugged this further. It seems to be an interaction issue between play and jerkson. On the first load in dev mode (from a fresh start) it works fine. If there is then a recompilation involving the nested classes, then it barfs on subsequent loads.

I suspect this is because the classes are effectively refreshed / updated, but jerkson keeps a static cache of the JavaTypes (see https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/Types.scala#L9 ) and then presumably the matching done around https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala#L21 fails, but I'm not sure.

If that is the case, then a potential fix could be to clear the Jerkson Types.cachedTypes on each reload in development. However, Types is private[jerkson] and Types.cachedTypes is private, so this is a little tricky to do.

Haven't found a workaround - right now I have to restart the dev server on each change to pretty much any part of the code. :(

Minor additional points:

  • When I download and build the latest on github I get a 0.6.0-SNAPSHOT which is identical to the jar on http://repo.codahale.com/com/codahale/jerkson_2.9.1/0.6.0-SNAPSHOT/ (diffing the jars, identical class files).

  • It works & breaks as outlined above with both 0.6.0 and 0.5.0 (the latter is the play 2.0.2 default).

  • For some reason play/sbt doesn't pick up the resolvers added in plugins.sbt. However, adding them in Build.scala works:

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
    // Add your own project settings here
    resolvers += "CodaHale repository" at "http://repo.codahale.com"
    )

jxtps commented Aug 10, 2012

I have debugged this further. It seems to be an interaction issue between play and jerkson. On the first load in dev mode (from a fresh start) it works fine. If there is then a recompilation involving the nested classes, then it barfs on subsequent loads.

I suspect this is because the classes are effectively refreshed / updated, but jerkson keeps a static cache of the JavaTypes (see https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/Types.scala#L9 ) and then presumably the matching done around https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala#L21 fails, but I'm not sure.

If that is the case, then a potential fix could be to clear the Jerkson Types.cachedTypes on each reload in development. However, Types is private[jerkson] and Types.cachedTypes is private, so this is a little tricky to do.

Haven't found a workaround - right now I have to restart the dev server on each change to pretty much any part of the code. :(

Minor additional points:

  • When I download and build the latest on github I get a 0.6.0-SNAPSHOT which is identical to the jar on http://repo.codahale.com/com/codahale/jerkson_2.9.1/0.6.0-SNAPSHOT/ (diffing the jars, identical class files).

  • It works & breaks as outlined above with both 0.6.0 and 0.5.0 (the latter is the play 2.0.2 default).

  • For some reason play/sbt doesn't pick up the resolvers added in plugins.sbt. However, adding them in Build.scala works:

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
    // Add your own project settings here
    resolvers += "CodaHale repository" at "http://repo.codahale.com"
    )

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.