Reputation: 3475
I am using play-framework 2.7 and following this tutorial https://github.com/swagger-api/swagger-play/tree/master/play-2.6/swagger-play2
i followed all the steps
added
play.modules.enabled += "play.modules.swagger.SwaggerModule"
in application.conf here is my build.sbt file
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"
here is the controller action
@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")
}
}
and here is the route file
GET /hello/:name controllers.CountController.sayHello(name:String)
GET /swagger.json controllers.ApiHelpController.getResources
hitting localhost:9000/hello/abc throws following exception
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)
i researched this and added "io.swagger" %% "swagger-scala-module" % "1.0.4"
but the problem persists
Upvotes: 2
Views: 1573
Reputation: 1848
If, like me, you got this exception while trying to run tests on your Play2 application, you can just disable Swagger for tests. Here's a workaround code:
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"
}
}
}
Upvotes: 0
Reputation: 8263
1. Swagger-play 1.6.0 does not support play 2.7 officially. It corresponds to play 2.6.x.
https://github.com/swagger-api/swagger-play#compatibility
https://github.com/swagger-api/swagger-play/issues/187
2. The reason for your issue is conflict in "jackson.databind" dependencies.
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"
as well as "io.swagger" %% "swagger-scala-module" % "1.0.4"
depends on "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.6"
"com.typesafe.play" %% "play" % "2.7.0"
depends on "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.8"
i researched this and added "io.swagger" %% "swagger-scala-module" % "1.0.4" but the problem persists
I guess you found something like Provider io.swagger.scala.converter.SwaggerScalaModelConverter could not be instantiated or https://github.com/swagger-api/swagger-play/issues/166. In those cases, the changes did shift the jackson-databind
to correct version but in your case, as I describe, it does not.
You need to update the jackson-databind
in the swagger-play2
to version 2.9.x or downgrade play server to version 2.6.x. Here is the pull request of the swagger update to 2.7: https://github.com/swagger-api/swagger-play/pull/188
Upvotes: 1