matiwinnetou / swagger-play24

Port of swagger 1.3.12 to Play 2.4
Apache License 2.0
21 stars 7 forks source link

Initialisation error #6

Open szuzul opened 9 years ago

szuzul commented 9 years ago

Hi Im getting exception when trying to use the module for play 2.4. (Java application) compilation passed successfully but when i run the app I get:

Caused by: java.lang.ExceptionInInitializerError: null at java.lang.Class.forName0(Native Method) ~[na:1.8.0_45] at java.lang.Class.forName(Class.java:348) ~[na:1.8.0_45] at com.wordnik.swagger.core.SwaggerContext$.loadClass(SwaggerContext.scala:21) ~[swagger-core_2.11-1.3.12.jar:1.3.12] at pl.matisoft.swagger.PlayApiScanner$$anonfun$classes$1.applyOrElse(PlayApiScanner.scala:52) ~[swagger-play24_2.11-1.4.jar:1.4] at pl.matisoft.swagger.PlayApiScanner$$anonfun$classes$1.applyOrElse(PlayApiScanner.scala:49) ~[swagger-play24_2.11-1.4.jar:1.4] at scala.collection.immutable.List.collect(List.scala:295) ~[scala-library-2.11.6.jar:na] at pl.matisoft.swagger.PlayApiScanner.classes(PlayApiScanner.scala:49) ~[swagger-play24_2.11-1.4.jar:1.4] at play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2$$anonfun$apply$3.apply(ApiListingCache.scala:34) ~[swagger-play24_2.11-1.4.jar:1.4] at play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2$$anonfun$apply$3.apply(ApiListingCache.scala:32) ~[swagger-play24_2.11-1.4.jar:1.4] at scala.Option.map(Option.scala:146) ~[scala-library-2.11.6.jar:na] Caused by: java.lang.RuntimeException: DataSource user is null? at com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.(DataSourcePool.java:204) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebeaninternal.server.core.DefaultContainer.getDataSourceFromConfig(DefaultContainer.java:325) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebeaninternal.server.core.DefaultContainer.setDataSource(DefaultContainer.java:291) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:99) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:73) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:38) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebean.EbeanServerFactory.create(EbeanServerFactory.java:54) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebean.Ebean$ServerManager.getWithCreate(Ebean.java:210) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebean.Ebean$ServerManager.get(Ebean.java:197) ~[avaje-ebeanorm-4.6.2.jar:na] at com.avaje.ebean.Ebean$ServerManager.access$200(Ebean.java:133) ~[avaje-ebeanorm-4.6.2.jar:na]

Any Idea ?

pycloux commented 9 years ago

Similar issue for me:

java.lang.ExceptionInInitializerError:

 java.lang.Class.forName0(Native Method)

 java.lang.Class.forName(Class.java:348)

 com.wordnik.swagger.core.SwaggerContext$.loadClass(SwaggerContext.scala:21)

 pl.matisoft.swagger.PlayApiScanner$$anonfun$classes$1.applyOrElse(PlayApiScanner.scala:52)

 pl.matisoft.swagger.PlayApiScanner$$anonfun$classes$1.applyOrElse(PlayApiScanner.scala:49)

 scala.collection.immutable.List.collect(List.scala:295)

 pl.matisoft.swagger.PlayApiScanner.classes(PlayApiScanner.scala:49)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2$$anonfun$apply$3.apply(ApiListingCache.scala:34)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2$$anonfun$apply$3.apply(ApiListingCache.scala:32)

 scala.Option.map(Option.scala:145)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2.apply(ApiListingCache.scala:32)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1$$anonfun$apply$2.apply(ApiListingCache.scala:31)

 scala.Option.map(Option.scala:145)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1.apply(ApiListingCache.scala:31)

 play.modules.swagger.ApiListingCache$$anonfun$listing$1.apply(ApiListingCache.scala:29)

 scala.Option.orElse(Option.scala:266)

 play.modules.swagger.ApiListingCache$.listing(ApiListingCache.scala:29)

 pl.matisoft.swagger.SwaggerPluginProvider.onStart(SwaggerPluginProvider.scala:64)

 pl.matisoft.swagger.SwaggerPluginProvider.get(SwaggerPluginProvider.scala:36)

 pl.matisoft.swagger.SwaggerPluginProvider.get(SwaggerPluginProvider.scala:18)

 com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)

 com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72)

 com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)

 com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62)

 com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)

 com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)

 com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)

 com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)

 com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)

 com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:205)

 com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:199)

 com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)

 com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:199)

 com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180)

 com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)

 com.google.inject.Guice.createInjector(Guice.java:96)

 com.google.inject.Guice.createInjector(Guice.java:73)

 com.google.inject.Guice.createInjector(Guice.java:62)

 play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126)

 play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93)

 play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:153)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:150)

 play.utils.Threads$.withContextClassLoader(Threads.scala:21)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:150)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:121)

 scala.Option.map(Option.scala:145)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:121)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:119)

 scala.util.Success.flatMap(Try.scala:230)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:119)

 play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:111)

 scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)

 scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)

 java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)

 java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)

 java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)

 java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1689)

 java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
michalzubkowicz commented 9 years ago

It's not a swagger issue: Caused by: java.lang.RuntimeException: DataSource user is null?

michalzubkowicz commented 9 years ago

Check your application.conf

pycloux commented 9 years ago

Hello actually it is, if you look to my stacktrace it is not "triggered" by Ebean or any other exception. This happens in the PlayApiScanner. I'll try to figure out what it is.

michalzubkowicz commented 9 years ago

@pycloux in your case it's not a full stacktrace, also Play 2.4 is using dependency injection and in such case any error in initialization will put swagger on top of stacktrace.

pycloux commented 9 years ago

Hi @michalzubkowicz

I think I found the error. In my application I still have a GlobalSettings (not easy to get rid of it quickly). For some reason your module is "triggered" while the Global has not completed which cause the following root error : Caused by: java.lang.RuntimeException: There is no started application. This happens here: SwaggerContext.loadClass(className).getAnnotation(classOf[Api]) != null

I suspect that the root error of @szuzul is actually the same.

pycloux commented 9 years ago

So here is the conclusion (which explains the error from @szuzul). Your controler analyzer loads the classes (in order to check the annotation). The problem is that, some of these controllers may have dependencies with other artifacts which cannot be loaded at the moment where the scan happens (in the case of @szuzul this was probably a static dependency with a Ebean bean).

So the solution would pobably be either to: 1) switch to DI for everything in my application (not sur it would solve the issue but may be). I fear that the application loading would still potentially be an issue since your are loading some classes aside the DI mechanism. 2) delay the load to a later stage 3) allow the users to filter the components "scanned"

Here is what I have done with your code (I included it into my application to modify it):

controllers.collect {
      case className: String if {
        try {
          Logger("swagger").info("Loading class:  %s.".format(className))
          !className.indexOf("controllers.api.core").equals(-1) && SwaggerContext.loadClass(className).getAnnotation(classOf[Api]) != null
        } catch {
          case ex: Exception => {
            Logger("swagger").error("Problem loading class:  %s. %s: %s".format(className, ex.getClass.getName, ex.getMessage))
            false}
          case ex: Throwable => {
            Logger("swagger").error("Problem loading class:  %s. %s: %s".format(className, ex.getClass.getName, ex.getMessage))
            false}
            throw ex
        }
      } =>
        Logger("swagger").info("Found API controller:  %s".format(className))
        SwaggerContext.loadClass(className)
    }

First I added a Throwable catch (just to log such kind of issue which are not Exceptions). I added a filter on the class name (my API controllers are in the same package). That's a bit crap but I am able to load and now it is working.

michalzubkowicz commented 9 years ago

@pycloux It's not my code ;). Maybe you could create PR and @matiwinnetou would be so kind to include something like that in distribution? It should solve problems with finding source of problem and blaming for errors that are not caused by swagger