[Play 2.4.4] Enabling module in FakeApplication via additionalConfiguration causes guice errors.

800 views
Skip to first unread message

Scott Hathaway

unread,
Feb 1, 2016, 8:42:06 AM2/1/16
to play-framework
Upgrading from Play 2.3 to 2.4.4 and Secure Social 2.1.4 to 3.0-M4. Here is the setup for my FakeApplication in my test:

implicit override lazy val app = FakeApplication(
path = new File("webapp"),
withGlobal = Some(FakeGlobal),
additionalConfiguration = Map("play.modules.enabled" -> List("utility.securesocial.testkit.SecurityModule"))
)

If I run the test without the additional configuration and update the application.conf to include the correct module, the test execute correctly. When I run it as shown, I get the error pasted below. Anyone seen this or have thoughts on it? Thanks!



Exception encountered when invoking run on a nested suite - Unable to create injector, see the following errors:

1) Could not find a suitable constructor in play.api.Configuration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Configuration.class(Configuration.scala:197)
  while locating play.api.Configuration
    for parameter 2 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

2) Could not find a suitable constructor in play.api.Environment. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Environment.class(Environment.scala:17)
  while locating play.api.Environment
    for parameter 1 at play.api.test.FakePluginsProvider.<init>(Fakes.scala:231)
  at play.api.test.FakeApplication.<init>(Fakes.scala:214):
Binding(class play.api.Plugins to ProviderConstructionTarget(class play.api.test.FakePluginsProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3) Could not find a suitable constructor in play.api.Environment. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Environment.class(Environment.scala:17)
  while locating play.api.Environment
    for parameter 1 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

4) Could not find a suitable constructor in play.api.http.HttpConfiguration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.http.HttpConfiguration.class(HttpConfiguration.scala:22)
  while locating play.api.http.HttpConfiguration
    for parameter 3 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

4 errors
com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Could not find a suitable constructor in play.api.Configuration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Configuration.class(Configuration.scala:197)
  while locating play.api.Configuration
    for parameter 2 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

2) Could not find a suitable constructor in play.api.Environment. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Environment.class(Environment.scala:17)
  while locating play.api.Environment
    for parameter 1 at play.api.test.FakePluginsProvider.<init>(Fakes.scala:231)
  at play.api.test.FakeApplication.<init>(Fakes.scala:214):
Binding(class play.api.Plugins to ProviderConstructionTarget(class play.api.test.FakePluginsProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3) Could not find a suitable constructor in play.api.Environment. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.Environment.class(Environment.scala:17)
  while locating play.api.Environment
    for parameter 1 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

4) Could not find a suitable constructor in play.api.http.HttpConfiguration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.http.HttpConfiguration.class(HttpConfiguration.scala:22)
  while locating play.api.http.HttpConfiguration
    for parameter 3 at play.api.inject.RoutesProvider.<init>(BuiltinModule.scala:64)
  while locating play.api.inject.RoutesProvider
    for parameter 1 at play.api.test.FakeRouterProvider.<init>(Fakes.scala:258)
  at play.api.test.FakeApplication.<init>(Fakes.scala:215):
Binding(interface play.api.routing.Router to ProviderConstructionTarget(class play.api.test.FakeRouterProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

4 errors
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93)
at play.api.test.FakeApplication.<init>(Fakes.scala:216)
at controllers.TestController.app$lzycompute(TestController.scala:24)
at controllers.TestController.app(TestController.scala:24)
at controllers.TestController.app(TestController.scala:22)
at org.scalatestplus.play.OneAppPerSuite$class.run(OneAppPerSuite.scala:139)
at controllers.TestController.run(TestController.scala:22)
at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:55)
at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$3.apply(Runner.scala:2563)
at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$3.apply(Runner.scala:2557)
at scala.collection.immutable.List.foreach(List.scala:381)
at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:2557)
at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1044)
at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1043)
at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:2722)
at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1043)
at org.scalatest.tools.Runner$.run(Runner.scala:883)
at org.scalatest.tools.Runner.run(Runner.scala)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:138)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
 

Zaid Momin

unread,
Apr 11, 2016, 6:33:34 AM4/11/16
to play-framework
Any update on the issue? Im facing the same problem unable to resolve.

Greg Methvin

unread,
Apr 11, 2016, 10:00:40 PM4/11/16
to play-framework
play.modules.enabled is a list of all the enabled modules. When you override that configuration key, you are replacing all the enabled modules, including play.api.inject.BuiltInModule, which binds all the built-in components.

A better way to add modules is to add them to .bindings() in GuiceApplicationBuilder (note: FakeApplication is now deprecated and GuiceApplicationBuilder is the recommended alternative if you're using Guice):

new GuiceApplicationBuilder().bindings(new SecurityModule).build

The other option is to explicitly add BuiltInModule to the list of modules in play.modules.enabled, so those built-in components are bound properly.

Usually bindings() is the safest way to do what you want, so that's what I'd recommend using. See the documentation here: https://www.playframework.com/documentation/2.5.x/ScalaTestingWithGuice#Bindings-and-Modules

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/74fa1a8a-890b-4122-b286-db85611e9bf4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Senior Software Engineer

Justin

unread,
May 11, 2016, 2:30:04 AM5/11/16
to play-framework
If you want the way of adding 'play.modules.enabled' to 'additionalConfiguration', the following will work:

"play.modules.enabled" -> Seq(
"play.api.inject.BuiltinModule",
"play.api.i18n.I18nModule",
"play.api.libs.ws.ning.NingWSModule",
"play.api.libs.openid.OpenIDModule",
"play.api.db.DBModule",
"play.api.db.HikariCPModule",
"play.api.cache.EhCacheModule",
"play.filters.csrf.CSRFModule",
"play.filters.cors.CORSModule",
"play.filters.headers.SecurityHeadersModule",
"play.filters.gzip.GzipFilterModule",
"utility.securesocial.testkit.SecurityModule"
)
Reply all
Reply to author
Forward
0 new messages