mashupbots / socko

A Scala web server powered by Netty networking and AKKA processing.
Other
255 stars 51 forks source link

No resource for my/package in RestRegistry #91

Closed chenweiyj closed 10 years ago

chenweiyj commented 10 years ago

I am using restful api of socko. When I run my application via sbt run, it is ok to run without any problem. However, when I package my application by one-jar and run it via java -jar myapp-onejar.jar, a runtime error occur. So I wonder what the problem with the jar file and my application is. Thank you.

veebs commented 10 years ago

What is your error?

chenweiyj commented 10 years ago

Following is my sbt about result:

[info] Loading project definition from /path/to/myapp/project
[info] Set current project to root (in build file:/path/to/myapp/)
[info] This is sbt 0.13.1
[info] The current project is {file:/path/to/myapp/}root 0.1-SNAPSHOT
[info] The current project is built against Scala 2.10.3
[info] Available Plugins: com.github.retronym.SbtOneJar
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.3

Following is the runtime error message:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.simontuffs.onejar.Boot.run(Boot.java:340)
    at com.simontuffs.onejar.Boot.main(Boot.java:166)
Caused by: java.lang.ExceptionInInitializerError
    at com.netease.cloudstudyindex.httpapi.IndexService.main(IndexService.scala)
    ... 6 more
Caused by: java.lang.RuntimeException: No resource for com/pkgpath/httpapi
    at org.mashupbots.socko.infrastructure.ReflectUtil$.getClasses(ReflectUtil.scala:43)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$3.apply(RestRegistry.scala:127)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$3.apply(RestRegistry.scala:127)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
    at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:127)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:102)
    at com.netease.cloudstudyindex.httpapi.IndexService$.<init>(IndexService.scala:40)
    at com.netease.cloudstudyindex.httpapi.IndexService$.<clinit>(IndexService.scala)
    ... 7 more

Following is the part of the result of jar -tf myapp_2.10-1.0.jar, where myapp_2.10-1.0.jar is in myapp_2.10-1.0-onejar.jar generated by one-jar:

com/pkgpath/httpapi/StatIndexProcessor$$anonfun$paginate$1.class
com/pkgpath/httpapi/LessonSourceIndexRegistration$.class
com/pkgpath/httpapi/RankIndexProcessor$$anonfun$1.class
com/pkgpath/httpapi/StatContent$$anonfun$merge$1.class
com/pkgpath/httpapi/RankIndexProcessor$$anonfun$getRankContents$1.class
com/pkgpath/httpapi/CourseRankIndexResponse$.class

And the error code is:

val restRegistry = RestRegistry("com.pkgpath.httpapi", RestConfig("1.0", "http://localhost:8888/api", reportRuntimeException = ReportRuntimeException.All))

veebs commented 10 years ago

Maybe it has something to do with the class loader.

If you don't specify a class loader in the constructor of the RestRegistry, then the default is used (see https://github.com/mashupbots/socko/blob/master/socko-rest/src/main/scala/org/mashupbots/socko/rest/RestRegistry.scala#L102).

You can set the log level to Debug to see what directory is being used in order to locate the classes (see https://github.com/mashupbots/socko/blob/master/socko-webserver/src/main/scala/org/mashupbots/socko/infrastructure/ReflectUtil.scala#L45)

chenweiyj commented 10 years ago

@veebs It didn't go to the log.debug statement of L45 in ReflectUtil.scala. It got error in throw new RuntimeException("No resource for " + relPath), and printed relPath as Caused by: java.lang.RuntimeException: No resource for com/pkgpath/httpapi

However, com/pkgpath/httpapi is in the jar file.

Could you tell me how to load classes for RestRegistry in a packaged jar file, since I need to deploy it in jar? thank you.

veebs commented 10 years ago

You might have to try to get the class loader for your class and pass it into RestRegistry (https://github.com/mashupbots/socko/blob/master/socko-rest/src/main/scala/org/mashupbots/socko/rest/RestRegistry.scala#L113).

    Class cls = Class.forName("com.pkgpath.httpapi.YourClassName");
    ClassLoader cLoader = cls.getClassLoader();

Failing that, you can see in ReflectUtil that I'm just trying to get the folder where the class files are:

val relPath = packageName.replace('.', '/')
val resource = classLoader.getResource(relPath)
if (resource == null) {
  throw new RuntimeException("No resource for " + relPath);
}

If you have the time, can you play around and let me know what works in your JAR setup so that resource is not null.

chenweiyj commented 10 years ago

I found one-jar has a different classloader. So the resource will be null.

But if I get all libs into a lib directory and export the CLASSPATH by adding those libs in lib file and run my jar file (generated by sbt package), it still got an error as follows:

Caused by: scala.ScalaReflectionException: <none> is not a module

The log printed shows:

2014-04-30 10:33:02,595 [main] DEBUG o.m.s.infrastructure.ReflectUtil$  - Package: com.pkgpath.httpapi becomes Path: com/pkgpath/httpapi 
2014-04-30 10:33:02,595 [main] DEBUG o.m.s.infrastructure.ReflectUtil$  - Resource = jar:file:/Users/path/to/jarfile/httpapi_2.10-1.0.jar!/com/pkgpath/httpapi
veebs commented 10 years ago

Did you try to pass the one-jar class loader into RestRegistry?

chenweiyj commented 10 years ago

No, I want my project to be generic with both sbt run command and one-jar package.

veebs commented 10 years ago

Can you please provide a stack trace. Thanks

chenweiyj commented 10 years ago
Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.netease.cloudstudyindex.httpapi.IndexService.main(IndexService.scala)
Caused by: scala.ScalaReflectionException: <none> is not a module
    at scala.reflect.api.Symbols$SymbolApi$class.asModule(Symbols.scala:301)
    at scala.reflect.internal.Symbols$SymbolContextApiImpl.asModule(Symbols.scala:73)
    at scala.reflect.runtime.JavaMirrors$JavaMirror.moduleSymbol(JavaMirrors.scala:208)
    at scala.reflect.runtime.JavaMirrors$JavaMirror.moduleSymbol(JavaMirrors.scala:65)
    at org.mashupbots.socko.rest.RestRegistry$.findRestRegistration(RestRegistry.scala:195)
    at org.mashupbots.socko.rest.RestRegistry$.buildRestOperation(RestRegistry.scala:170)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:131)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:130)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:130)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:114)
    at com.netease.cloudstudyindex.httpapi.IndexService$.<init>(IndexService.scala:44)
    at com.netease.cloudstudyindex.httpapi.IndexService$.<clinit>(IndexService.scala)
    ... 1 more
veebs commented 10 years ago

I'm going to have to add more debugging to find out why it is not working for you. I'll try to do so this weekend.

chenweiyj commented 10 years ago

Besides, I also tried sbt-pack, which does not pack all dependencies into one jar file, but a lib/ directory and call my jar file in java command. However, it still failed to register the RestRequest. Following is the stack trace.

13:42:35.186 [RestExampleActorSystem-akka.actor.default-dispatcher-4] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
13:42:35.203 [RestExampleActorSystem-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - logger log1-Slf4jLogger started
13:42:35.207 [RestExampleActorSystem-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - Default Loggers started
13:42:36.008 [main] DEBUG o.m.s.infrastructure.ReflectUtil$ - Package: com.pkgpath.httpapi becomes Path: com/pkgpath/httpapi 
13:42:36.009 [main] DEBUG o.m.s.infrastructure.ReflectUtil$ - Resource = jar:file:/path/to/httpapi_2.10-1.0.jar!/com/pkgpath/httpapi
Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.pkgpath.httpapi.RestApp.main(RestApp.scala)
Caused by: org.mashupbots.socko.rest.RestDefintionException: Cannot find corresponding RestRequest 'com.pkgpath.httpapi.GetPetRegistration$Request' for RestRegistration 'com.pkgpath.httpapi.GetPetRegistration$'
    at org.mashupbots.socko.rest.RestRegistry$.findRestRequest(RestRegistry.scala:233)
    at org.mashupbots.socko.rest.RestRegistry$.buildRestOperation(RestRegistry.scala:171)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:131)
    at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:130)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:130)
    at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:102)
    at com.pkgpath.httpapi.RestApp$.<init>(RestApp.scala:202)
    at com.pkgpath.httpapi.RestApp$.<clinit>(RestApp.scala)
    ... 1 more
veebs commented 10 years ago

I've just added a lot more logging to the code to help track down the problem. I'll release it as soon as I get some time (hopefully in the next few days). I'm just a bit busy with work at the moment.

On 13 May 2014 15:53, chenweiyj notifications@github.com wrote:

Besides, I also tried sbt-pack, which does not pack classes into one jar file, but a lib/ directory and call my jar file in java command. However, it still failed to register the RestRequest. Following is the stack trace.

13:42:35.186 [RestExampleActorSystem-akka.actor.default-dispatcher-4] INFO akka.event.slf4j.Slf4jLogger - Slf4jLogger started 13:42:35.203 [RestExampleActorSystem-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - logger log1-Slf4jLogger started 13:42:35.207 [RestExampleActorSystem-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - Default Loggers started 13:42:36.008 [main] DEBUG o.m.s.infrastructure.ReflectUtil$ - Package: com.pkgpath.httpapi becomes Path: com/pkgpath/httpapi 13:42:36.009 [main] DEBUG o.m.s.infrastructure.ReflectUtil$ - Resource = jar:file:/path/to/httpapi_2.10-1.0.jar!/com/pkgpath/httpapi Exception in thread "main" java.lang.ExceptionInInitializerError at com.pkgpath.httpapi.RestApp.main(RestApp.scala) Caused by: org.mashupbots.socko.rest.RestDefintionException: Cannot find corresponding RestRequest 'com.pkgpath.httpapi.GetPetRegistration$Request' for RestRegistration 'com.pkgpath.httpapi.GetPetRegistration$' at org.mashupbots.socko.rest.RestRegistry$.findRestRequest(RestRegistry.scala:233) at org.mashupbots.socko.rest.RestRegistry$.buildRestOperation(RestRegistry.scala:171) at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:131) at org.mashupbots.socko.rest.RestRegistry$$anonfun$4.apply(RestRegistry.scala:130) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) at scala.collection.AbstractTraversable.map(Traversable.scala:105) at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:130) at org.mashupbots.socko.rest.RestRegistry$.apply(RestRegistry.scala:102) at com.pkgpath.httpapi.RestApp$.(RestApp.scala:202) at com.pkgpath.httpapi.RestApp$.(RestApp.scala) ... 1 more

— Reply to this email directly or view it on GitHubhttps://github.com/mashupbots/socko/issues/91#issuecomment-42919749 .

chenweiyj commented 10 years ago

I have solved this problem, and made a pull request. thank you.