pickling icon indicating copy to clipboard operation
pickling copied to clipboard

Issue with Play's classloader

Open oscar-broman opened this issue 10 years ago • 4 comments

When Play is running with hot reloating (sbt run), pickling can't load a very simple, sealed class.

play.api.Application$$anon$1: Execution exception[[RuntimeException: java.lang.ExceptionInInitializerError]]
    at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.8.jar:2.3.8]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:205) [play_2.11-2.3.8.jar:2.3.8]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:202) [play_2.11-2.3.8.jar:2.3.8]
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.6.jar:na]
Caused by: java.lang.RuntimeException: java.lang.ExceptionInInitializerError
    at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:523) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:130) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:129) ~[play_2.11-2.3.8.jar:2.3.8]
Caused by: java.lang.ExceptionInInitializerError: null
    at controllers.DrugBank$$anonfun$search$1.apply(DrugBank.scala:36) ~[classes/:na]
    at controllers.DrugBank$$anonfun$search$1.apply(DrugBank.scala:31) ~[classes/:na]
    at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:433) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:432) ~[play_2.11-2.3.8.jar:2.3.8]
    at play.api.mvc.Action$.invokeBlock(Action.scala:556) ~[play_2.11-2.3.8.jar:2.3.8]
Caused by: java.lang.RuntimeException: error: cannot find class or module with type name 'models.Ingredient'
full type string: 'models.Ingredient'
    at scala.sys.package$.error(package.scala:27) ~[scala-library-2.11.6.jar:na]
    at scala.pickling.internal.package$.liftedTree1$1(package.scala:59) ~[scala-pickling_2.11-0.10.0.jar:0.10.0]
    at scala.pickling.internal.package$.typeFromString(package.scala:54) ~[scala-pickling_2.11-0.10.0.jar:0.10.0]
    at scala.pickling.FastTypeTag$$anon$2.tpe$lzycompute(FastTags.scala:141) ~[scala-pickling_2.11-0.10.0.jar:0.10.0]
    at scala.pickling.FastTypeTag$$anon$2.tpe(FastTags.scala:141) ~[scala-pickling_2.11-0.10.0.jar:0.10.0]

The class is declared in another file as such:

sealed class Ingredient(name: String, id: Option[String])

oscar-broman avatar May 05 '15 15:05 oscar-broman

The reason this happened was I did streamPickle.unpickle[Any] followed by pattern matching. It worked when it was used via the console or in production, but not during dev mode. Being explicit about what I want to unpickle works in all modes.

oscar-broman avatar May 05 '15 15:05 oscar-broman

@phaller, @heathermiller Is this a known behavior that can be solved by a stoke of a pen (or a membrane keyboard)?

eed3si9n avatar May 05 '15 19:05 eed3si9n

This is a general issue with all serialization frameworks that use any form of runtime reflection in the presence of classloaders (e.g. ObjectInputStream). What you have to do is set the currentMirror in the internal package of pickling to the appropriate one so pickling can find your classes. Otherwise, pickling assumes System classloader (or current thread context classloader) which is probably wrong for play dev-mode.

I think we'll have to doucment this usage explicitly and provide some nice hooks for dealing with this issue.

jsuereth avatar Aug 12 '15 17:08 jsuereth

Also, the 0.11.x branch should be removing the need for reflection on pickling tags, whcih MAY help solve your issue if you can compile with staticOnly imported.

jsuereth avatar Aug 12 '15 17:08 jsuereth