[Play Scala 2.5.4] Multi-project ConfigurationException: Guice configuration errors

934 views
Skip to first unread message

Michael Slinn

unread,
Jul 22, 2016, 5:16:02 PM7/22/16
to play-framework
1) I've got a simple multiproject webapp, which works at https://github.com/mslinn/play25multiproject
In this git branch, the serviceA and serviceB SBT subprojects are siblings, and they depend on the common and nonPlay SBT subprojects. This is defined by build.sbt and project/CommonSettings.scala. All SBT subprojects have access to all routes. The subprojects include configuration from parent SBT projects.

2) The wtf branch is slightly more ambitious; it defines a module in each of serviceA and serviceB, and serviceA depends on serviceB. I attempt to have serviceB provide state to serviceA.

Unfortunately, this version throws:

Unexpected exception
ConfigurationException: Guice configuration errors:

1) No implementation for play.api.Application was bound.
  while locating play.api.Application

1 error
No source available, here is the exception stack trace:
->com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for play.api.Application was bound.
  while locating play.api.Application

1 error
     com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
     com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
     com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
     play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:405)
     play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:400)
     play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
     play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)


I think that build.sbt and project/CommonSettings.scala are properly structured. The aspects which I believe need to be looked at are:
  1. Routes - I was unsure on the best way to ensure that all SBT subprojects had access to all routes. This is probably messed up.
  2. Conf - The subprojects still include from parent conf files, but this got messy and is probably broken here

It would be great if someone forked the project and fussed with it until it displays web pages again. Failing that, any suggestions would be appreciated.


Mike

Greg Methvin

unread,
Jul 24, 2016, 4:30:47 AM7/24/16
to play-framework
Hi Mike,

Did you manage to get it working? Just downloaded and ran the project on the "wtf" branch and it seems to work fine now.

Greg

--
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/d8bf0b9f-b36c-4f6c-8b6d-428b315c7b33%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Senior Software Engineer

Michael Slinn

unread,
Jul 24, 2016, 7:06:16 AM7/24/16
to play-framework
Bizarre. It did not work last I checked. Must have fixed it without realizing it while writing docs.

Any comments on the two aspects I raised? You can see commented out routes and conf file entries. Because the Play docs do not describe how to set up a multiproject in detail I was going through a process of elimination. For example, the conf files assemble from the bottom up, instead of top down; what I mean is that conf files in subprojects include conf files in parent projects. Is this the most flexible way, or is there a way to make a multiproject work by arranging conf files in such a way that conf files in parent projects include conf files in subordinate projects?

The next step will be to ensure that Guice and play modules defined in serviceB can be accessed in serviceA. Will the current setup allow this? Are any additional config settings needed?

Thanks,

Mike

Michael Slinn

unread,
Jul 24, 2016, 10:45:59 AM7/24/16
to play-framework
I am guessing that filters defined in serviceA and serviceB won't be used, because the root subproject is actually the project that handles requests, and I am unaware of a co-operative mechanism between Play subprojects for request handling. Without any such cooperation, application.conf in the root subproject will need to specify and configure the filters.

That would be suboptimal for the scenario where a modified version of silhouette-seed-template is a subproject, because that project would need to be deconstructed and dispersed throughout the rest of the webapp in order to integrate it into a larger project. Dispersal  would make it harder to keep the project current with changes to silhouette-seed-template. I am also unaware of a partial import mechanism for Typesafe Config, so perhaps one way to keep things separate would be to extract silhouette-seed-template's http.filter section from silhouette.application.conf and save it as filters.silhouette.application.conf. Because SBT's dependsOn augments the project classpath with the classpath of subprojects, filters.silhouette.application.conf could be imported by application.conf and/or by silhouette.application.conf. Is there a better way to handle this?

I have a similar question about Guice modules defined in subprojects and bound in AbstractModule subclasses within their respective subprojects. Yes, they are all on the project classpath because of dependsOn, but I am unclear if the root project would need to mention them in a root-level AbstractModule subclass, or if Guice would automatically process every AbstractModule subclass on the classpath (I am guessing the latter is likely true, but I have not tested this yet). I am also unclear if application.conf in the root project would need to mention each subproject's Guice modules in play.modules.enabled, or if the subprojects would automatically forward their subproject.application.conf settings into the consolidated Configuration.

Many questions!

Mike

Will Sargent

unread,
Jul 24, 2016, 10:55:45 AM7/24/16
to play-fr...@googlegroups.com, Michael Slinn
There are submodules defined in the 


Where Play is one of the sub projects of SBT.

There’s also the TLS example:


This uses a SIRD router which can take over the routing between sub projects when you want to use virtual hosts:



Personally, I like using SIRD over the -> syntax in the routes file, because it gives more flexibilty and options.

Will.
--
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.

Michael Slinn

unread,
Jul 24, 2016, 11:02:13 AM7/24/16
to play-framework, msl...@gmail.com

Will,

None of these SBT projects demonstrates any of the issues I've mentioned.
Routing seems to work fine in the project I provided.

Mike

Will Sargent

unread,
Jul 24, 2016, 4:09:08 PM7/24/16
to play-framework, msl...@gmail.com
> Routes - I was unsure on the best way to ensure that all SBT subprojects had access to all routes. This is probably messed up.
> Conf - The subprojects still include from parent conf files, but this got messy and is probably broken here

If you're asking about the best way to check on how subprojects can work with routes and configuration, the projects I mentioned are good starting points.  

Will.

Michael Slinn

unread,
Jul 24, 2016, 5:09:47 PM7/24/16
to play-framework, msl...@gmail.com
Will,

I think you can see from the sample project I put together that I understand how the projects you reference work. I'll summarize the outstanding questions that I have been attempting to ask, and make some assertions so as to invite comments and corrections:
  1. Play will only consolidate subproject.application.conf settings into the root project Configuration if they are included into the root project's conf file.
  2. Which configuration pattern is recommended (and why) for subprojects: top-down (where parents include subproject conf files) or bottom-up (where subprojects include parent conf files)?
    1. Are there any special considerations for those subprojects that are customizations of other projects (like play-silhouette-seed) and it is desirable to track the upstream project?
  3. The root project performs all request handling:
    1. A subproject's filters are only invoked if they are mentioned in the root project's filter chain, and filter chains defined in subprojects are ignored. Filter settings in a subproject's conf file are ignored unless that file is included into the root project's config file.
    2. Action handlers in Play subprojects are not passed requests unless they are mentioned in the root project's route file, or a route file included in the root project route file
  4. Guice will load all AbstractModule subclasses, wherever they may be declared, but if they are not mentioned in the play.modules.enabled key of the root project's conf file, or an included conf file, Play won't manage them. 

Thanks,


Mike

Greg Methvin

unread,
Jul 24, 2016, 5:30:21 PM7/24/16
to play-framework
Mike,

I think your main point of confusion may be around how configuration works. Looking at your project it seems like there are a few things missing. For example, you have {serviceA,serviceB}-application.conf but don't have them referenced anywhere. You should explicitly define it like this: https://github.com/kifi/multiproject/blob/master/project/Build.scala#L41. By default your application will use application.conf.

On Sun, Jul 24, 2016 at 7:45 AM, Michael Slinn <msl...@gmail.com> wrote:
I am guessing that filters defined in serviceA and serviceB won't be used, because the root subproject is actually the project that handles requests, and I am unaware of a co-operative mechanism between Play subprojects for request handling. Without any such cooperation, application.conf in the root subproject will need to specify and configure the filters.

The filters won't be used, but that's because it's defined based on the play.http.filters setting in your main app's application.conf. Because of the way filters are bound, you can only bind one HttpFilters binding at once. So you should create one in each app and explicitly set the setting.
 
That would be suboptimal for the scenario where a modified version of silhouette-seed-template is a subproject, because that project would need to be deconstructed and dispersed throughout the rest of the webapp in order to integrate it into a larger project. Dispersal  would make it harder to keep the project current with changes to silhouette-seed-template. I am also unaware of a partial import mechanism for Typesafe Config, so perhaps one way to keep things separate would be to extract silhouette-seed-template's http.filter section from silhouette.application.conf and save it as filters.silhouette.application.conf. Because SBT's dependsOn augments the project classpath with the classpath of subprojects, filters.silhouette.application.conf could be imported by application.conf and/or by silhouette.application.conf. Is there a better way to handle this?

I'm not that familiar with the silhouette seed, but it should be fine to include other configuration files on the classpath in your main application.conf. You should only have one application.conf on the classpath. This is the reason for having differently named config files for services that are explicitly configured in the build, to prevent conflicts when subprojects are used in another main project.
 
I have a similar question about Guice modules defined in subprojects and bound in AbstractModule subclasses within their respective subprojects. Yes, they are all on the project classpath because of dependsOn, but I am unclear if the root project would need to mention them in a root-level AbstractModule subclass, or if Guice would automatically process every AbstractModule subclass on the classpath (I am guessing the latter is likely true, but I have not tested this yet). I am also unclear if application.conf in the root project would need to mention each subproject's Guice modules in play.modules.enabled, or if the subprojects would automatically forward their subproject.application.conf settings into the consolidated Configuration.

Neither Guice nor Play does any kind of classpath scanning to find modules. You need to set play.modules.enabled += "com.example.FooModule" to get it working.

Just import the subproject config files in your main project's application.conf, so you don't have to re-add those modules.
 
Many questions!

Mike

--
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.

For more options, visit https://groups.google.com/d/optout.

Michael Slinn

unread,
Jul 24, 2016, 6:08:50 PM7/24/16
to play-framework

 [...]you have {serviceA,serviceB}-application.conf but don't have them referenced anywhere. You should explicitly define it like this: https://github.com/kifi/multiproject/blob/master/project/Build.scala#L41. By default your application will use application.conf.

That is somewhat helpful, thank you. The Kifi example does not show each subproject using its own subproject.application.conf for dev and prod, just test, when the subproject is being tested.

Is it true that there is only one Configuration for the entire project, and it is consistent for all SBT subprojects? That would explain why each subproject does not have a setting like:

javaOptions += "-Dconfig.resource=serviceX-application.conf"



On Sun, Jul 24, 2016 at 7:45 AM, Michael Slinn <msl...@gmail.com> wrote:
I am guessing that filters defined in serviceA and serviceB won't be used, because the root subproject is actually the project that handles requests, and I am unaware of a co-operative mechanism between Play subprojects for request handling. Without any such cooperation, application.conf in the root subproject will need to specify and configure the filters.

The filters won't be used, but that's because it's defined based on the play.http.filters setting in your main app's application.conf. Because of the way filters are bound, you can only bind one HttpFilters binding at once. So you should create one in each app and explicitly set the setting.

Here is some code I wrote to define the root filter chain. It incorporates the filter chain for the silhouette subproject's filter chain, which would otherwise be ignored. Of course, this only works if Guice has bound the silhouetteFilters instance of utils.silhouette.Filters. Comments?

class FilterChain @Inject() (
    gzip: GzipFilter,
    silhouetteFilters: utils.silhouette.Filters
) extends HttpFilters {
  val filters: Seq[EssentialFilter] =
    Seq(PlayAccessFilter.playAccessLogger, leads, gzip, httpsRedirect) ++:
      silhouetteFilters.filters
}

 
 
That would be suboptimal for the scenario where a modified version of silhouette-seed-template is a subproject, because that project would need to be deconstructed and dispersed throughout the rest of the webapp in order to integrate it into a larger project. Dispersal  would make it harder to keep the project current with changes to silhouette-seed-template. I am also unaware of a partial import mechanism for Typesafe Config, so perhaps one way to keep things separate would be to extract silhouette-seed-template's http.filter section from silhouette.application.conf and save it as filters.silhouette.application.conf. Because SBT's dependsOn augments the project classpath with the classpath of subprojects, filters.silhouette.application.conf could be imported by application.conf and/or by silhouette.application.conf. Is there a better way to handle this?

I'm not that familiar with the silhouette seed, but it should be fine to include other configuration files on the classpath in your main application.conf. You should only have one application.conf on the classpath. This is the reason for having differently named config files for services that are explicitly configured in the build, to prevent conflicts when subprojects are used in another main project.

Got that, thanks. Any suggestions regarding the relative merits of bottom-up or top-down inclusion of config files?
 
 
I have a similar question about Guice modules defined in subprojects and bound in AbstractModule subclasses within their respective subprojects. Yes, they are all on the project classpath because of dependsOn, but I am unclear if the root project would need to mention them in a root-level AbstractModule subclass, or if Guice would automatically process every AbstractModule subclass on the classpath (I am guessing the latter is likely true, but I have not tested this yet). I am also unclear if application.conf in the root project would need to mention each subproject's Guice modules in play.modules.enabled, or if the subprojects would automatically forward their subproject.application.conf settings into the consolidated Configuration.

Neither Guice nor Play does any kind of classpath scanning to find modules. You need to set play.modules.enabled += "com.example.FooModule" to get it working.
 
That is helpful, thank you.

Just import the subproject config files in your main project's application.conf, so you don't have to re-add those modules.

Seems like each subproject's config files will need to be split up, so the subprojects can put them together as required for testing.

Mike

Greg Methvin

unread,
Jul 24, 2016, 8:16:10 PM7/24/16
to play-framework
On Sun, Jul 24, 2016 at 3:08 PM, Michael Slinn <msl...@gmail.com> wrote:
Is it true that there is only one Configuration for the entire project, and it is consistent for all SBT subprojects? That would explain why each subproject does not have a setting like:

javaOptions += "-Dconfig.resource=serviceX-application.conf"

If I try to run serviceA in your example (sbt 'project serviceA' run), it fails with a configuration error because there is no application.conf specified. So it is definitely an issue if you would like to use that module as an independent project. It needs to be configured that way so there is only application.conf (or whatever config.resource is) on the classpath, and the "root" project depends on it. Generally you only define application.conf at the top level.

Note that you only need to do this because you have a "root" project that depends on those subprojects and has to run as its own application. If you chose to run each service individually (as a top-level project), you could use application.conf as you usually do.

Here is some code I wrote to define the root filter chain. It incorporates the filter chain for the silhouette subproject's filter chain, which would otherwise be ignored. Of course, this only works if Guice has bound the silhouetteFilters instance of utils.silhouette.Filters. Comments?

Your subproject should provide a Guice module with bindings, and perhaps a separate configuration file adding the module that can be included.

Got that, thanks. Any suggestions regarding the relative merits of bottom-up or top-down inclusion of config files?

I think "top-down" is good, but you want to separate the configuration for running the application from the configuration meant to be imported. So maybe have a serviceA.conf (which you include in subprojects) and a serviceA-application.conf (which includes things like play.http.router that you would not want to define in a dependent project).

 Seems like each subproject's config files will need to be split up, so the subprojects can put them together as required for testing.

Well, for testing, you can usually define bindings programmatically to create test applications for different situations, so you often don't need separate config files.

Michael Slinn

unread,
Jul 24, 2016, 11:05:53 PM7/24/16
to play-framework
Right, my next tasks are to create some sample modules and configure filters in subprojects, and make them available for testing, perhaps some standalone projects, and combine them into an all-singing, all-dancing mega-webapp (tm).

I've been writing up how-to guidelines for some as-yet unreleased lectures on ScalaCourse using this material. Lots of work still remains.

I'll undoubtedly have follow-up questions. Thanks for all for your help.

Mike

Will Sargent

unread,
Jul 25, 2016, 12:12:27 PM7/25/16
to play-framework
I'd also recommend looking at 


for more tips on handling configuration from HOCON.

Will.

Michael Slinn

unread,
Jul 25, 2016, 12:18:55 PM7/25/16
to play-framework
Will,

Thanks for the link, but I did not learn anything new. My questions were more about how the Play classloaders work than how HOCON works. Play has many classloaders, but how they affect the Play programming model is not apparent from the Play docs. For example, if subprojects each had their own classloader (maybe they do?), and the classloaders are not consolidated by the root project's classloader, then each subproject could have distinct config, etc. Some info on this topic would be appreciated.

Mike

Will Sargent

unread,
Jul 25, 2016, 12:29:20 PM7/25/16
to play-framework
There's only one classloader for the application:


Play doesn't segment or isolate classes in sub projects in their own classloader -- there's some classloader logic in the SBT plugin to handle live restarts, but it's all flat at the application classloader level, and when packaging a Play app for distribution, everything is arranged on the classpath.

Will.

Michael Slinn

unread,
Jul 25, 2016, 1:33:41 PM7/25/16
to play-framework

There's only one classloader for the application:


Play doesn't segment or isolate classes in sub projects in their own classloader -- there's some classloader logic in the SBT plugin to handle live restarts, but it's all flat at the application classloader level, and when packaging a Play app for distribution, everything is arranged on the classpath.

Thanks, that was the source of a lot of wonderment for me.


Another question related to this thread: the master branch of my project has this routes file:

->  / common.Routes

->  /a serviceA.Routes

->  /b serviceB.Routes


The wtf branch has serviceA dependsOn serviceB. Does the routes file need to change, or should the routes file for root become:

->  / common.Routes

->  /a serviceA.Routes



... and add the following the serviceA routes file:

->  /b serviceB.Routes


Mike

Will Sargent

unread,
Jul 25, 2016, 2:03:57 PM7/25/16
to play-fr...@googlegroups.com
Routes are contextual.  If you define a routes file with /a pointing to servicesA.Routes, then you have a servicesA.routes file and you have a reference in it to /b, then you'll get /a/b -- I don't think this is what you want.  


This is why I tend to go with a SIRD router, because you have more flexibility.

You can also checkout Adrian Hurt's multidomain example, which is a good deal more complex but really shows what you can do:


--
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.

Mike Slinn

unread,
Jul 25, 2016, 2:17:31 PM7/25/16
to play-fr...@googlegroups.com

Routes are contextual.  If you define a routes file with /a pointing to servicesA.Routes, then you have a servicesA.routes file and you have a reference in it to /b, then you'll get /a/b
Aha!


-- I don't think this is what you want. 
Quite right.




This is why I tend to go with a SIRD router, because you have more flexibility.

You can also checkout Adrian Hurt's multidomain example, which is a good deal more complex but really shows what you can do:

That is a good resource, thanks. An update to Play 2.5 would be nice, but not essential for my immediate purpose.

Mike

Michael Slinn

unread,
Jul 25, 2016, 8:16:40 PM7/25/16
to play-framework
If a non-Play subproject dependsOn a Play subproject, how might the reverse routes from the Play subproject be made available to the non-Play 'parent' subproject? The Play docs for aggregateReverseRoutes make it sound like only Play subprojects can use this SBT task. I did not get an error when I tried using aggregateReverseRoutes on a non-Play subproject. What is the story here?

Mike

Greg Methvin

unread,
Jul 25, 2016, 9:38:46 PM7/25/16
to play-framework
aggregateReverseRoutes is a setting specific to the Play routes compiler, so it needs to be used in a Play project, or at least one that uses the RoutesCompiler plugin. The actual value "aggregateReverseRoutes" in build.sbt is still defined if you've included the Play SBT plugin, since it is auto-imported for convenience, but it wouldn't actually do anything unless you have the plugin enabled in your project. In addition, the routing API uses types defined by Play, so at the very minimum you would need the Play library for the generated reverse router to compile. I think the simplest working project would be:

lazy val routes: Project = project.in(file("modules/routes"))
  .enablePlugins(RoutesCompiler)
  .settings(
    aggregateReverseRoutes := Seq(serviceA, serviceB),
    scalaVersion := "2.11.8",
    libraryDependencies += "com.typesafe.play" %% "play" % play.core.PlayVersion.current
  )

So the bottom line is that you need some kind of Play dependency to make it work. You could make a project like the above to aggregate the routes and simply depend on that in your non-Play projects, though.

On Mon, Jul 25, 2016 at 5:16 PM, Michael Slinn <msl...@gmail.com> wrote:
If a non-Play subproject dependsOn a Play subproject, how might the reverse routes from the Play subproject be made available to the non-Play 'parent' subproject? The Play docs for aggregateReverseRoutes make it sound like only Play subprojects can use this SBT task. I did not get an error when I tried using aggregateReverseRoutes on a non-Play subproject. What is the story here?

Mike

--
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.

For more options, visit https://groups.google.com/d/optout.

Michael Slinn

unread,
Jul 26, 2016, 3:56:12 AM7/26/16
to play-framework
I have a message from attempting to run unit tests on a Play subproject (in a different project) that says:

Error: object routes is not a member of package controllers.silhouette
import controllers.silhouette.routes.MyController

The subproject has a file called conf/silhouette.routes. According to the docs, it looks like I need to set something like:

PlayKeys.devSettings += ("play.http.router", "silhouette.Routes")

However, I want to run unit tests, not run in dev mode. Seems there is no support for PlayKeys.testSettings and PlayKeys.prodSettings. Instead, I must create conf/test.silhouette.application.conf and put something this in it:

  play.http.router = silhouette.Routes
  include "silhouette.application.conf"

The point of this email is to say, if PlayKeys.devSettings exists, why not also support PlayKeys.testSettings and PlayKeys.prodSettings?

Mike

Greg Methvin

unread,
Jul 26, 2016, 4:49:21 AM7/26/16
to play-framework
Hi Mike,

On Tue, Jul 26, 2016 at 12:56 AM, Michael Slinn <msl...@gmail.com> wrote:
The point of this email is to say, if PlayKeys.devSettings exists, why not also support PlayKeys.testSettings and PlayKeys.prodSettings?

It's meant to be a simple override for development purposes. The original PR explains it pretty well.

Play controls how your app is created in Dev mode, so it's possible to pass that configuration directly. In Prod mode, we're not using SBT, and in Test mode, you're generally creating fake apps yourself with config loaded from the classpath, so in both cases there's no simple mechanism to explicitly pass extra configuration. I think having some kind of hack through SBT to create some extra configuration that can be loaded would make things more complicated to reason about.

In general, you have more control if you just specify alternate configuration files.

Michael Slinn

unread,
Jul 26, 2016, 10:24:17 AM7/26/16
to play-framework
Thanks for the explanation.

The extra control in test mode costs extra complexity / additional indirection: a new Java property, pointing at a new config file containing the desired setting (3 steps), instead of just providing the desired setting in the subproject build definition (1 step). 3 steps means 3 things to consider when writing / debug / maintain.

Being able to debug a subproject independently is one of the strongest reasons for organizing a webapp into subprojects. Anything that simplifies the care and feeding of subproject unit tests is likely to directly contribute to the quality of the resulting webapps.

Mike

Michael Slinn

unread,
Jul 26, 2016, 12:44:03 PM7/26/16
to play-framework
Greg,

I've written a trait for ScalaTest+Play tests using your suggestions. Looks good.
My compulsive need for symmetry is driving me to seek testSettings and prodSettings, but you are right, they are not essential.

Mike

Michael Slinn

unread,
Jul 27, 2016, 1:20:37 PM7/27/16
to play-framework
When running unit tests for a subproject, I get 'No implementation for akka.actor.ActorSystem was bound. while locating akka.actor.ActorSystem"

The test Application was built this way:

implicit override lazy val app = GuiceApplicationBuilder(configuration = conf)
.bindings(new JobModule)
.bindings(new BaseModule)
.bindings(new SilhouetteTestModule)
.bindings(new MailerModule)
.build()

Are there additional modules I need to bind to resolve Play's ActorSystem?

Mike

Will Sargent

unread,
Jul 27, 2016, 2:44:26 PM7/27/16
to play-fr...@googlegroups.com
Hi Mike -- that error message could be a number of things in isolation.  Do you see a stacktrace or error messages in Akka configuration before that point?

Also, normally you'd append configuration to the application builder like this:

val application = new GuiceApplicationBuilder()
  .configure(Configuration("a" -> 1))
  .configure(Map("b" -> 2, "c" -> "three"))
  .configure("d" -> 4, "e" -> "five")
  .build



--
Will Sargent
Engineer, Lightbend, Inc.


--
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.

Michael Slinn

unread,
Jul 27, 2016, 2:51:57 PM7/27/16
to play-framework
I added the following and that error went away:

.bindings(new play.api.inject.BuiltinModule)

Should I need to do that?

Did you notice that I provided a Configuration called conf to the GuiceApplicationBuilder constructor? This is currently what I have:

  private val env = Environment.simple(new File("modules/model/"))
  private val conf = Configuration.load(env, Map("play.http.router" -> "silhouette.Routes"))
  assert(conf.getString("akka.quartz.schedules.AuthTokenCleaner.timezone").exists(_.nonEmpty))
  assert(conf.getString("play.http.filters").contains("utils.silhouette.Filters"))
  assert(conf.getString("play.http.router").contains("silhouette.Routes"))
  assert(conf.getString("sitePubConfigId").exists(_.nonEmpty))


  implicit override lazy val app = GuiceApplicationBuilder(configuration = conf)
    .bindings(new BuiltinModule)

    .bindings(new JobModule)
    .bindings(new BaseModule)
    .bindings(new SilhouetteTestModule)
    .bindings(new MailerModule)
    .build()


Now I'm trying to figure out why all the Silhouette bindings are not showing up, and neither is MailerModule:

Could not find a suitable constructor in play.api.libs.mailer.SMTPConfiguration. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
  at play.api.libs.mailer.SMTPConfiguration.class(MailerPlugin.scala:303)
  while locating com.google.inject.Provider<play.api.libs.mailer.SMTPConfiguration>
    for parameter 0 at play.api.libs.mailer.SMTPDynamicMailer.<init>(MailerPlugin.scala:114)
  at play.api.libs.mailer.MailerModule.bindings(MailerPlugin.scala:23):
Binding(interface play.api.libs.mailer.MailerClient to ConstructionTarget(class play.api.libs.mailer.SMTPDynamicMailer)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)


Mike

Michael Slinn

unread,
Jul 27, 2016, 2:54:24 PM7/27/16
to play-framework
Just noticed I did not properly answer your question. Prior to the 39 errors like the one I showed for MailerModule, this appears:

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


Mike

Michael Slinn

unread,
Jul 27, 2016, 4:35:21 PM7/27/16
to play-framework
I've explicitly bound all the relevant internal Play modules and thereby reduced the number of missing modules to 6:

  implicit override lazy val app = GuiceApplicationBuilder(configuration = conf)
    .bindings(new play.api.inject.BuiltinModule)
    .bindings(new play.api.libs.mailer.SMTPConfigurationModule)
    .bindings(new play.api.libs.mailer.MailerModule)
    .bindings(new play.api.libs.openid.OpenIDModule)
    .bindings(new play.api.libs.ws.ahc.AhcWSModule)
    .bindings(new play.api.i18n.I18nModule)
    .bindings(new play.filters.csrf.CSRFModule)
    .bindings(new play.api.cache.EhCacheModule)
    .bindings(new SilhouetteTestModule) // Silhouette module
    .bindings(new BaseModule)
// Silhouette module
    .bindings(new JobModule)  // Silhouette module
    .build()
    .build()

All the missing bindings are for types defined within the com.mohiva.play.silhouette package, and I think I might have a clue how to proceed with them.

One important detail I did not mention is that this subproject is not a play project, however it does have Play dependencies ("com.typesafe.play" %% "play", PlayImport.cache, PlayImport.filters, PlayImport.ws, and "com.typesafe.play" %% "play-mailer"). That means the normal Play startup sequence is not followed. I wonder if I need to provide an ApplicationLoader for the tests?

Mike

Will Sargent

unread,
Jul 27, 2016, 4:58:43 PM7/27/16
to play-fr...@googlegroups.com
> Did you notice that I provided a Configuration called conf to the GuiceApplicationBuilder constructor? 

I did -- that's why I mentioned that normally you append configuration, rather than what you're doing in the example, which looks like it's overriding it completely.

--
Will Sargent
Engineer, Lightbend, Inc.


--
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.

Will Sargent

unread,
Jul 27, 2016, 5:08:54 PM7/27/16
to play-fr...@googlegroups.com
One important detail I did not mention is that this subproject is not a play project, however it does have Play dependencies ("com.typesafe.play" %% "play", PlayImport.cache, PlayImport.filters, PlayImport.ws, and "com.typesafe.play" %% "play-mailer"). That means the normal Play startup sequence is not followed. I wonder if I need to provide an ApplicationLoader for the tests?

If you're doing something using functional tests, then you should be using the functional tests assuming a fully functional application -- this means you have to start from the root Play project, with any subprojects and modules you want loaded.  If you want to swap out any implementation details, you should provide stubs for those, or break it out into something that doesn't require any Play specific code at all.

I'm still getting used to marketing, but the first couple of chapters in Play in Practice deal with setting up modules and swapping out implementations specifically, and I think you'd probably find it helpful:



--
Will Sargent
Engineer, Lightbend, Inc.


--
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.

Michael Slinn

unread,
Jul 27, 2016, 5:17:40 PM7/27/16
to play-framework
Marketing makes our world go around! I'll follow up on your suggestion, thanks.

Looks like the subproject tests are rolling along now :)
This subproject under test will be used in non-Play apps, this effort is not just for functional tests. I shudder to think of the enormous fat jar it will create!

Mike
Reply all
Reply to author
Forward
0 new messages