【问题标题】:swagger:CreationException: in play framework 2.7招摇:CreationException:在播放框架2.7
【发布时间】:2019-08-11 04:22:09
【问题描述】:

我正在使用 play-framework 2.7 并遵循本教程 https://github.com/swagger-api/swagger-play/tree/master/play-2.6/swagger-play2

我遵循了所有步骤

添加

play.modules.enabled += "play.modules.swagger.SwaggerModule"

在 application.conf 中 这是我的 build.sbt 文件

scalaVersion := "2.12.8"

routesGenerator := InjectedRoutesGenerator
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "4.0.1" % Test
libraryDependencies += "com.h2database" % "h2" % "1.4.197"
libraryDependencies += "io.swagger" %% "swagger-play2" % "1.6.0"
libraryDependencies += "io.swagger" %% "swagger-scala-module" % "1.0.4"

这里是控制器动作

@Api
@Singleton
class CountController @Inject() (cc: ControllerComponents,
                                 counter: Counter) extends AbstractController(cc) {
  @ApiResponses(Array(
    new ApiResponse(code = 400, message = "Invalid name supplied"),
    new ApiResponse(code = 404, message = "Name not found")))
  def sayHello(@ApiParam(value = "Name to say hello") name: String) = Action {
    Ok(s"hello $name")
  }
}

这里是路由文件

GET        /hello/:name         controllers.CountController.sayHello(name:String)

GET     /swagger.json           controllers.ApiHelpController.getResources

点击 localhost:9000/hello/abc 抛出以下异常

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.util.ServiceConfigurationError: io.swagger.converter.ModelConverter: Provider io.swagger.scala.converter.SwaggerScalaModelConverter could not be instantiated
  at play.modules.swagger.SwaggerPluginImpl.<init>(SwaggerPlugin.scala:35)
  while locating play.modules.swagger.SwaggerPluginImpl
  at play.modules.swagger.SwaggerModule.bindings(SwaggerModule.scala:11):
Binding(interface play.modules.swagger.SwaggerPlugin to ConstructionTarget(class play.modules.swagger.SwaggerPluginImpl) eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
  while locating play.modules.swagger.SwaggerPlugin

1 error]
    at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:196)
    at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:127)
    at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:253)
    at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:149)
    at akka.stream.impl.fusing.MapAsync$$anon$30.onPush(Ops.scala:1207)
    at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
    at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:411)
    at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:588)
    at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:472)
    at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:563)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.util.ServiceConfigurationError: io.swagger.converter.ModelConverter: Provider io.swagger.scala.converter.SwaggerScalaModelConverter could not be instantiated
  at play.modules.swagger.SwaggerPluginImpl.<init>(SwaggerPlugin.scala:35)
  while locating play.modules.swagger.SwaggerPluginImpl
  at play.modules.swagger.SwaggerModule.bindings(SwaggerModule.scala:11):
Binding(interface play.modules.swagger.SwaggerPlugin to ConstructionTarget(class play.modules.swagger.SwaggerPluginImpl) eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
  while locating play.modules.swagger.SwaggerPlugin

1 error
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:543)
    at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:186)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109)
    at com.google.inject.Guice.createInjector(Guice.java:87)
    at com.google.inject.Guice.createInjector(Guice.java:78)
    at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:186)
    at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:139)
    at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
    at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:176)
    at play.utils.Threads$.withContextClassLoader(Threads.scala:22)
Caused by: java.util.ServiceConfigurationError: io.swagger.converter.ModelConverter: Provider io.swagger.scala.converter.SwaggerScalaModelConverter could not be instantiated
    at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:581)
    at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:803)
    at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
    at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1394)
    at io.swagger.converter.ModelConverters.<clinit>(ModelConverters.java:114)
    at play.modules.swagger.PlayReader.parseMethod(PlayReader.java:487)
    at play.modules.swagger.PlayReader.read(PlayReader.java:139)
    at play.modules.swagger.PlayReader.read(PlayReader.java:63)
    at play.modules.swagger.PlayReader.read(PlayReader.java:57)
    at play.modules.swagger.ApiListingCache$.$anonfun$listing$1(ApiListingCache.scala:17)
Caused by: java.lang.ExceptionInInitializerError: null
    at io.swagger.scala.converter.SwaggerScalaModelConverter.<init>(SwaggerScalaModelConverter.scala:19)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at java.base/java.util.ServiceLoader$ProviderImpl$2.run(ServiceLoader.java:787)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:792)
    at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
    at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1394)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Scala module 2.8.6 requires Jackson Databind version >= 2.8.0 and < 2.9.0
    at com.fasterxml.jackson.module.scala.JacksonModule.setupModule(JacksonModule.scala:66)
    at com.fasterxml.jackson.module.scala.JacksonModule.setupModule$(JacksonModule.scala:51)
    at com.fasterxml.jackson.module.scala.DefaultScalaModule.setupModule(DefaultScalaModule.scala:18)
    at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:751)
    at io.swagger.scala.converter.SwaggerScalaModelConverter$.<init>(SwaggerScalaModelConverter.scala:15)
    at io.swagger.scala.converter.SwaggerScalaModelConverter$.<clinit>(SwaggerScalaModelConverter.scala)
    at io.swagger.scala.converter.SwaggerScalaModelConverter.<init>(SwaggerScalaModelConverter.scala:19)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

我对此进行了研究并添加了"io.swagger" %% "swagger-scala-module" % "1.0.4",但问题仍然存在

【问题讨论】:

    标签: java scala playframework swagger play-framework-2.7


    【解决方案1】:

    1。 Swagger-play 1.6.0 官方不支持 play 2.7。它对应于播放 2.6.x。

    https://github.com/swagger-api/swagger-play#compatibility

    https://github.com/swagger-api/swagger-play/issues/187

    2。您的问题的原因是“jackson.databind”依赖项中的冲突。

    Caused by: com.fasterxml.jackson.databind.JsonMappingException: Scala module 2.8.6 requires Jackson Databind version >= 2.8.0 and < 2.9.0
    

    "io.swagger" %% "swagger-play2" % "1.6.0" 以及 "io.swagger" %% "swagger-scala-module" % "1.0.4" 取决于 "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.6"

    "com.typesafe.play" %% "play" % "2.7.0" 依赖于"com.fasterxml.jackson.core" % "jackson-databind" % "2.9.8"

    我对此进行了研究并添加了 "io.swagger" %% "swagger-scala-module" % "1.0.4" 但问题仍然存在

    我猜你找到了类似Provider io.swagger.scala.converter.SwaggerScalaModelConverter could not be instantiatedhttps://github.com/swagger-api/swagger-play/issues/166 的东西。在这些情况下,更改确实将jackson-databind 转换为正确的版本,但在您的情况下,正如我所描述的那样,它没有。

    您需要将swagger-play2 中的jackson-databind 更新到2.9.x 版本或将播放服务器降级到2.6.x 版本。这是 2.7 的 swagger 更新的拉取请求:https://github.com/swagger-api/swagger-play/pull/188

    【讨论】:

    • 如何将 swagger-play2 中的 jackson-databind 更新到 2.9.x 版本?
    • 从这个拉取请求 github.com/swagger-api/swagger-play/pull/188 构建它,它将 jackson-databind 更新为 "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.8"
    【解决方案2】:

    如果您像我一样在尝试在 Play2 应用程序上运行测试时遇到此异常,您可以禁用 Swagger 进行测试。这是一个解决方法代码:

    import org.scalatestplus.play.PlaySpec
    import org.scalatestplus.play.guice.GuiceOneAppPerSuite
    import controllers.YourController
    import play.api._
    import play.api.inject.guice.GuiceApplicationBuilder
    
    import scala.concurrent.Future
    import play.api.mvc._
    import play.api.test._
    import play.api.test.Helpers._
    import play.modules.swagger.SwaggerModule
    
    class RecommendationsControllerSpec extends PlaySpec with GuiceOneAppPerSuite with Results {
      /* Here's the override part: */
      override def fakeApplication(): Application =
        new GuiceApplicationBuilder()
          .disable[SwaggerModule]
          .build()
    
      val controller: YourController = app.injector.instanceOf[YourController]
    
      "Health check#health" should {
        "should be valid" in {
          val result: Future[Result] = controller.health.apply(FakeRequest())
          val bodyText: String       = contentAsString(result)
          bodyText mustBe "OK"
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多