Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

class not found exceptions when parsing in sbt tasks #38

Closed
softprops opened this Issue · 5 comments

2 participants

@softprops

I noticed that jerkson will throw a class not found exception when case class parsing occurs within an sbt task.

package baz    

import com.codahale.jerkson.Json._

case class Foo(bar: String)

(TaskKey[Unit]("jerkson", "parse with jerkson")) <<= (streams) map { (out) => 
   out.log.info(parse[Foo]("""{"bar":"boom"}"""))
 }

The relevant stack trace will look something like

    java.lang.ClassNotFoundException: baz.Foo
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at com.codahale.jerkson.util.CaseClassSigParser$.loadClass(CaseClassSigParser.scala:135)
at com.codahale.jerkson.util.CaseClassSigParser$.findRootClass(CaseClassSigParser.scala:49)
at com.codahale.jerkson.util.CaseClassSigParser$.parseScalaSig(CaseClassSigParser.scala:42)
at com.codahale.jerkson.util.CaseClassSigParser$.findSym(CaseClassSigParser.scala:56)
at com.codahale.jerkson.util.CaseClassSigParser$.parse(CaseClassSigParser.scala:83)
at com.codahale.jerkson.deser.CaseClassDeserializer.<init>(CaseClassDeserializer.scala:20)
at com.codahale.jerkson.deser.ScalaDeserializers.findBeanDeserializer(ScalaDeserializers.scala:94)
at org.codehaus.jackson.map.deser.BeanDeserializerFactory._findCustomBeanDeserializer(BeanDeserializerFactory.java:391)
at org.codehaus.jackson.map.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:433)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createDeserializer(StdDeserializerProvider.java:398)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:307)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:287)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:136)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findTypedValueDeserializer(StdDeserializerProvider.java:157)
at org.codehaus.jackson.map.ObjectMapper._findRootDeserializer(ObjectMapper.java:2461)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2376)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1166)
at com.codahale.jerkson.Parser$class.parse(Parser.scala:81)
at com.codahale.jerkson.Json$.parse(Json.scala:6)
at com.codahale.jerkson.Parser$class.parse(Parser.scala:14)
at com.codahale.jerkson.Json$.parse(Json.scala:6)
@codahale
Owner

Jerkson uses the current thread's ClassLoader, and SBT runs (well, ran—I haven't paid attention to 0.10+) with a highly-restricted class loader, which means you may not be able to parse the @ScalaSig annotation on your case classes.

@softprops

Thanks. I'll repost this on the sbt mailing list to see if I can't conjure of some bites of info.

@codahale
Owner

So I'd say this boils down to:

  • Find a class loader with which you can load Foo and use it as the current thread's class loader.

or

  • Get SBT to loosen its class loader restrictions.
@codahale codahale closed this
@softprops

Okay thanks. The relevant post on the sbt list is at http://groups.google.com/group/simple-build-tool/browse_thread/thread/9878b1dc2631f20 if you wanted to listen in, in case some else asks here in the future

@softprops

bada-bing, bada-boom.

When I explicitly set the current threads class loader to the one the case class was loaded in, the issue disappears. I'll let the the sbt list know for future reference

  private def inClassLoader[T](cls: Class[_])(f: => T): T = {
    val prev = Thread.currentThread.getContextClassLoader
    try {
      Thread.currentThread.setContextClassLoader(
         cls.getClassLoader
      )
      f
    } finally {
     Thread.currentThread.setContextClassLoader(prev)
    }
  }

  // works now
  (TaskKey[Unit]("jerkson", "parse with jerkson")) <<= (streams) map { (out) => 
     inClassLoader(classOf[Foo]) { out.log.info(parse[Foo]("""{"bar":"boom"}""")) }
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.