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

Exception with case classes nested within case classes #67

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

Exception with case classes nested within case classes #67

jxtps opened this issue Aug 8, 2012 · 5 comments

Comments

@jxtps
Copy link

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
Copy link
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.

@imikushin
Copy link
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 :)

@jxtps
Copy link
Author

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
Copy link
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)

@jxtps
Copy link
Author

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.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants