Play 2.4 - Dependency Injection

5,129 views
Skip to first unread message

James Roper

unread,
Jun 3, 2014, 2:05:53 AM6/3/14
to play-fram...@googlegroups.com
Hi all,

It's now time to start talking about Play 2.4 features.  One of the major features of Play 2.4 is going to be dependency injection.

Until now, Play has remained completely unopinionated about dependency injection, both in what it provides, and how it documents and encourages users to write Play apps.  One of the reasons for this is that on the Scala side, the Scala ecosystem hasn't yet decided on what the best way to tackle dependency injection is.  Broadly speaking, there are two camps, those that think runtime dependency injection is the way to go (eg Guice), and those that think that compile time dependency injection is the way to go.  The second group is wildly divided in approach, from manual wiring, to the cake pattern, to implicit wiring, to implicit parameter passing, to the reader monad.

At the core, we want to keep Play unopinionated, allowing either compile time or runtime dependency injection.  However, we think it's time to stop being unopinionated in what we provide out of the box, a well as in our documentation.  Also, given Play's focus on productivity, on convention over configuration, the dynamic nature of a Play application in dev mode, we think that runtime dependency injection is the direction that we should point users in in our documentation, and provide out of the box support for.  Also I might add, in a typical Play dev loop, starting an app (and therefore wiring dependencies) happens immediately after compilation - the most touted advantage of compile time dependency injection - getting errors at compile time - doesn't hold during normal Play development.

We also have a goal for Play 3.0 to remove the need for global state - specifically play.api.Play.current - in Play.  I don't think I need to explain what the advantages of this are, but to aid testing I think is the biggest.

So what we want to do now is come up with a plan for Play 3.0.  At this stage it's looking like this: every component of Play should have its dependencies declared either via a constructor, or a builder method, and that these constructors/builder methods become public API (if they aren't already).  By doing this, we open up the ability to use any form of dependency injection, both compile time and runtime.  Additionally, we will provide out of the box support for Guice - though it should be possible to replace Guice with Spring.

So what's this got to do with Play 2.4?  We want to use Play 2.4 as a release that will allow us to validate and fine tune our approach.  The starting point for the work is Greg Methvin's PR:


Though I think we want to do a little more work around designing what Play 3.0 will look like, work out where (and when) Application, Global, and NettyServer fit in to the picture, how plugins will provide dependencies (since they may want to provide more than just themselves), etc, before we merge that.

In addition we want to update our docs to assume and encourage runtime dependency injection (also providing some docs on how to use compile time dependency injection).

So, this email serves as a start to this work.  Any feedback is welcome.

Cheers,

James

--
James Roper
Software Engineer

Typesafe – Build reactive apps!
Twitter: @jroper

Pascal Voitot Dev

unread,
Jun 3, 2014, 2:41:18 AM6/3/14
to James Roper, play-fram...@googlegroups.com
Hi,

I agree that Play must stay unopinionated about DI.
I'm in favor of compile-time DI because it brings lots of better aspects than runtime DI in theory. But as you said, all compile-time solutions have pros/cons (specially cake pattern has a real cost in terms of code size & compile time).

I'm curious about your solution based on dependencies declared in constructor.
Have you prototypes of this approach to give a ground for reflexion?

Best regards
Pascal

--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Greg Methvin

unread,
Jun 3, 2014, 3:20:15 AM6/3/14
to Pascal Voitot Dev, James Roper, play-fram...@googlegroups.com
I've generally found the constructor injection approach to be the most reliable for the core pieces of my application. It works in both Java and Scala, and even with all the other options in Scala, I've found it to be the best at handling a larger number of dependencies. In Scala you can use a library like MacWire to do the wiring at compile time, and you can of course use Guice and Spring to do DI at runtime in both Java and Scala.

In Play I think we'd want to support runtime DI frameworks, so it would make sense for the interface we create (like the one in my PR) to be runtime DI. I don't think this is such a big deal, as this only means you can't catch top-level dependency issues at compile time. So if you forget to bind a controller in your module, you'll have to test at runtime to see that there's a problem. But for everything else in your app you could wire it up so you can find the error at compile time.

~Greg

Julien Richard-Foy

unread,
Jun 3, 2014, 3:39:08 AM6/3/14
to Greg Methvin, Pascal Voitot Dev, James Roper, play-fram...@googlegroups.com
As long as we have play.api.Play.current, we can not have
constructor-based DI. I don’t really see how you can expect to give a
preview of what DI will look like in Play 3.0 if we still have a
global state in 2.4.
Also, constructor-based DI is the simplest solution, probably my
favorite, but does not work anymore if you have recursive
dependencies. The cake can handle that, though it is more complex to
harness… Anyway, let’s try if we can provide an acceptable solution
with constructor-based dependencies.

James Roper

unread,
Jun 3, 2014, 4:18:04 AM6/3/14
to Julien Richard-Foy, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
On Tue, Jun 3, 2014 at 5:39 PM, Julien Richard-Foy <j...@zengularity.com> wrote:
As long as we have play.api.Play.current, we can not have
constructor-based DI. I don’t really see how you can expect to give a
preview of what DI will look like in Play 3.0 if we still have a
global state in 2.4.

Why not?  Today you use WS by doing this:

WS.url(...)

And that depends on the global state.  In Play 2.4, you will be able to:

class MyController(wsClient: WSClient) {
  wsClient.url(...)
}

And that won't use global state, so you can test MyController in isolation.  You will still be able to use WS.url(...), but we will encourage the latter.  My hope is that in Play 2.4 all plugins will be accessible both through the current static mechanism, as well as through DI.  Global state won't be gone, for example, I expect things like session configuration, body parser max length configuration etc to still depend on global state, these are things that will require major breakage to remove, as it will likely force everyone to use DI, or change Play's architecture quite fundamentally (for example, we can eliminate the session configuration reliance on global state if we don't lazily parse sessions, but instead use akka-http's caching header parsing approach, but this is quite a fundamental change to Play).

Whether we will remove play.api.Play.current altogether in Play 3.0 remains to be seen, if we can provide a smooth migration path from no DI to DI, then it may make sense to keep it there, deprecated, to facilitate that.
 
Also, constructor-based DI is the simplest solution, probably my
favorite, but does not work anymore if you have recursive
dependencies. The cake can handle that, though it is more complex to
harness… Anyway, let’s try if we can provide an acceptable solution
with constructor-based dependencies.

Circular dependencies are indeed an issue with constructor injection, but in my experience, circular dependencies are often an indication of a design problem, removing them usually results in a better design.

Note that we are only mandating constructor injection in Play - users can use any flavour of dependency injection, including property based, they want.

Julien Richard-Foy

unread,
Jun 3, 2014, 7:03:40 AM6/3/14
to James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
>> As long as we have play.api.Play.current, we can not have
>> constructor-based DI. I don’t really see how you can expect to give a
>> preview of what DI will look like in Play 3.0 if we still have a
>> global state in 2.4.
>
>
> Why not? Today you use WS by doing this:
>
> WS.url(...)
>
> And that depends on the global state. In Play 2.4, you will be able to:
>
> class MyController(wsClient: WSClient) {
> wsClient.url(...)
> }
>
> And that won't use global state, so you can test MyController in isolation.
> You will still be able to use WS.url(...), but we will encourage the latter.

You are totally right, by removing all accesses to
play.api.Play.current from the framework internals and from plugins
implementation (and by replacing it with an implicit parameter), it
makes it possible to write code that does not depend on the global
state.

However, in all the parts of your code that are called by the
framework, since you have no control on the way the framework calls
your code you can not apply constructor-based DI. The affected parts
are the Global object, plugins and, most importantly, controllers.
Today, all these parts of your application have to be static objects
and can not have injected dependencies unless you use a runtime DI
system.

Alberto SOUZA

unread,
Jun 3, 2014, 9:40:31 AM6/3/14
to play-fram...@googlegroups.com, ja...@typesafe.com, greg.m...@gmail.com, pascal.v...@gmail.com
I am not sure about Guice, but Spring and Weld work with a lot dynamic proxies, which is really bad for the auto-reload feature provided by Play. And I like the static approach in my controller. It is a completely stateless layer, why do I want dependency injection there? I know we maybe we end with a bit more coupled code but, at least to me, seems to be a nice tradeoff in order to have the productivity necessary to develop apps nowadays. Besides that, probably everyone has already had to maintain a lot of bad code, even if the application is using some DI container... I really don't think this is the happy path... 

As a plugin is the best way, if the guy wants to Spring for me ok, but I don't want to be obligated.. 

On the other hand, it would be nice have a support to replace some internal play components in a easier way. But I think that with a little extra configuration, if you want to change you are running away from convention, it is possible to create some factories which would be used in the core of the framework.

Greg Methvin

unread,
Jun 4, 2014, 3:47:03 AM6/4/14
to Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-fram...@googlegroups.com

However, in all the parts of your code that are called by the
framework, since you have no control on the way the framework calls
your code you can not apply constructor-based DI. The affected parts
are the Global object, plugins and, most importantly, controllers.
Today, all these parts of your application have to be static objects
and can not have injected dependencies unless you use a runtime DI
system.

I'm not sure I understand what you're saying here. The framework already supports constructor-based DI for controllers (with getControllerInstance). There are straightforward ways we can support constructor-based DI for plugins and the Global using a similar strategy.

You're right that you need to use a "runtime" DI system in that you need to convert a class to an instance of that class, but that's the only thing that absolutely has to be at runtime. All the dependencies of those dependencies can be defined at compile time or runtime using whatever method you want.

James Roper

unread,
Jun 11, 2014, 7:50:55 AM6/11/14
to Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
This is my current thinking about the approach we could take:

* Plugins are not components themselves that can be injected, but rather provide components that can be injected.  This allows far greater flexibility than having plugins as components themselves, as it means a single plugin can configure/provide many components, can provide named components (eg so you can have a named connection pool injected), etc.  This is also in line with many (but not all) existing plugins in the core of Play - the plugin itself just provides access to the components it provides.
* This means plugins become analogous to Guice modules (though would not actually be Guice modules as we don't want to enforce guice).  It means also that we would need to provide some sort of binding API, since JSR330 does not provide this.  Something similar to the Guice Binder, but perhaps more idiomatic for Scala.

Greg Methvin

unread,
Jun 11, 2014, 6:57:31 PM6/11/14
to James Roper, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
I think that plugins themselves should be as minimal as possible, and should basically only be concerned with integrating a particular module's behavior with the Play application, but I think they need to be injectable because the components they're providing might have their own dependencies.

I think having a binding API might be unnecessarily complex for most cases. The simplest way for a plugin to provide dependencies is exactly to how we do it with DBPlugin and CachePlugin using pure Scala: you provide methods on the plugin which return the instances. Then a user can bind those directly, for example in a Guice module, if desired. Most plugins external to your application should be fairly self-contained, and within your application you'll probably want to use your preferred DI solution.

The more generic approach I was proposing integrates a bit less nicely with runtime DI, but it's also less opinionated, and actually makes it reasonable to use compile-time DI as well. If, for example, you're using implicits or cake pattern, all you should need to do is construct a list of controllers and plugins, and the global, which is all Play needs to know about.

James Roper

unread,
Jun 17, 2014, 2:38:18 AM6/17/14
to Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
On Thu, Jun 12, 2014 at 12:57 AM, Greg Methvin <greg.m...@gmail.com> wrote:
I think that plugins themselves should be as minimal as possible, and should basically only be concerned with integrating a particular module's behavior with the Play application, but I think they need to be injectable because the components they're providing might have their own dependencies.

The plugin itself should not have dependencies, just as Guice modules don't have dependencies.  Rather, it provides components that may have dependencies, but doesn't instantiate them itself - it provides the bindings and then lets the DI container provide the dependencies to the components it has bound.  I think Guice's approach to separating modules from injectable components is a really good design pattern, which is why I think we should replicate it in Play.
 
I think having a binding API might be unnecessarily complex for most cases. The simplest way for a plugin to provide dependencies is exactly to how we do it with DBPlugin and CachePlugin using pure Scala: you provide methods on the plugin which return the instances. Then a user can bind those directly, for example in a Guice module, if desired. Most plugins external to your application should be fairly self-contained, and within your application you'll probably want to use your preferred DI solution.

Note that we want to provide first class out of the box support for runtime dependency injection.  If this were just about providing a way for a user to integrate DI into their application, then I would agree with you - since a user must know about all plugins they are including and therefore can be expected to do the more advanced bindings themselves.  But this is about Play providing an ideal runtime dependency solution out of the box, so it means we want plugins - which are not aware of what DI solution is being used - to be able to provide advanced bindings, and we want a DI solution - which is not aware of what plugins exist - to be able to allow plugins to provide as many components as they like.

By just limiting it to having plugins themselves injected, then I think we're not treating dependency injection as a first class feature, we limit ourselves, and the end solution will not be much better than what we have now.  But a goal of Play 2.4 is to treat dependency injection as a first class out of the box feature.

Also I don't like forcing plugins to have their components implement some arbitrary interface - it's taking us back to the EJB days.  We want components to be POJOs or POSOs, not things that implement Plugin.

The more generic approach I was proposing integrates a bit less nicely with runtime DI, but it's also less opinionated, and actually makes it reasonable to use compile-time DI as well. If, for example, you're using implicits or cake pattern, all you should need to do is construct a list of controllers and plugins, and the global, which is all Play needs to know about.

By making the plugin classes equivalent to guice modules, I do not believe we are restricting the use of compile time DI.  The approach we are taking internally in Play is to make constructors/factory methods public API, and have compile time dependency injection use these.  Plugins should do the same.  The Plugin trait will become just something that is used only when runtime dependency injection is being used, not when compile time dependency injection is being used.  For compile time dependency injection, users will just wire the public constructors and factory methods together.  This actually makes compile time dependency injection much nicer, it means the components you're instantiating aren't polluted by some arbitrary Plugin trait that makes no sense in the context of compile time dependency injection.

Greg Methvin

unread,
Jun 17, 2014, 4:26:24 AM6/17/14
to James Roper, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
I think you have some good points but there are a few concerns I have about your proposal that I'm not clear on:

First is that I want Play to integrate as seamlessly as possible with any DI interface. If you use Guice in your application, you should be able to use Guice modules just as easily as you would any other interface. Why would I want to use Plugins if I could use regular Guice modules? Or is this just for third-party plugins to integrate with Play?

Second is that I'd prefer not to redefine what a Plugin is. As far as I'm concerned, Plugin is an interface that lets you define what happens when the application starts and stops. I think there is also confusion with sbt plugins vs Play plugins (which are both used in Play projects), so having plugins do something different in 2.4 is likely to create more confusion.

It also happens that you can call app.plugin[PluginClass] to "inject" a plugin as a dependency. The fact that this was being used by third-party plugins was the original motivation for having plugins themselves be instantiable via DI, so you could easily create custom implementations of interfaces that the main plugin (e.g. SecureSocial) depended on. I don't think this is an ideal method of doing DI, but it does provide a way for third-party modules to have customizable dependencies. How would this work with the new system you're talking about?

James Roper

unread,
Jun 17, 2014, 5:51:40 AM6/17/14
to Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
On Tue, Jun 17, 2014 at 10:26 AM, Greg Methvin <greg.m...@gmail.com> wrote:
I think you have some good points but there are a few concerns I have about your proposal that I'm not clear on:

First is that I want Play to integrate as seamlessly as possible with any DI interface. If you use Guice in your application, you should be able to use Guice modules just as easily as you would any other interface. Why would I want to use Plugins if I could use regular Guice modules? Or is this just for third-party plugins to integrate with Play?

Yes this will definitely be possible - a runtime DI provider (eg the built in guice one or spring one) will provide some mechanism specific to itself to natively configure it to the full power that it supports - in Guice this will mean you get the opportunity to provide modules, in Spring this probably will mean you can specify an XML file.  I guess what this looks like in practice is that there will be a configuration item that let's you pass a list of guice modules.  But third party, and built in plugins, need to have a way to inject components that isn't dependent on Guice.  It should be possible to transparently switch to Spring, and have these plugins also provide components without the plugins knowing about Spring.
 
Second is that I'd prefer not to redefine what a Plugin is. As far as I'm concerned, Plugin is an interface that lets you define what happens when the application starts and stops. I think there is also confusion with sbt plugins vs Play plugins (which are both used in Play projects), so having plugins do something different in 2.4 is likely to create more confusion.

It's not just that, it also gives you a way to access shared resources - it is a provider of components.  The most ugly part of the plugin trait I think is actually the start/stop side of things - it depends on arbitrarily chosen numbers for ordering in the config file.  While this will still work in Play 2.4, it's something that we want to move away from.  I suspect in Play 2.4, none of the built in plugins will actually provide an implementation of start/stop, Play will still invoke start/stop at the appropriate times, but only for backwards compatibility.  In Play 3.0 we can completely remove them.

So, the replacement?  The thinking now is that components should do their startup in constructors - this means the ordering is implicitly defined by the dependency graph expressed by the constructors.  For cleanup, we're thinking of providing a LifecycleRegister or something, so a component can depend on that, and pass itself to the register, and then it will be shut down when the register is shut down.  The ordering here will be the reverse of the order that components were registered - and since components will register themselves in their constructors, this means it will imply the reverse order from being started.

One further thing to note here is that we will probably need a mechanism for explicitly requiring eager instantiation, to ensure that in production the app fails fast if, for example, it can't connect to the database.

There is one hole left by this, sort of - evolutions.  Nothing will depend on evolutions via a dependency, but evolutions needs to run after the database connects, but before anything else starts.  It may be that evolutions will need to use a new plugin point - the database plugin may have to expose a way to hook in evolutions.  Some more thinking is required here.

We may completely remove the term "Plugin" - perhaps "Module" would be a good name.  This certainly would help in distinguishing between sbt plugins and modules.  It's also familiar terminology for those coming from Guice.  And I also feel "Play Module" conveys what it is better than "Play Plugin".
 
It also happens that you can call app.plugin[PluginClass] to "inject" a plugin as a dependency. The fact that this was being used by third-party plugins was the original motivation for having plugins themselves be instantiable via DI, so you could easily create custom implementations of interfaces that the main plugin (e.g. SecureSocial) depended on. I don't think this is an ideal method of doing DI, but it does provide a way for third-party modules to have customizable dependencies. How would this work with the new system you're talking about?

It could be pretty similar to the way it's done now.  Let's take the Cache as an example, this might be the cache plugin:

trait CacheAPI { ... }

class EhCache(register: LifecycleRegister) extends CacheAPI { 
  val manager = new CacheManager(...)
  register.registerShutdown(manager.shutdown())
  ...
}

class EhCachePlugin(app: Application) extends Plugin {
  def bind(binder: Binder) = {
    binder.add(bind(classOf[CacheAPI]).to(classOf[EhCache]))
  }
  def enabled = app.config.getString("ehcacheplugin").forall(_ != "disabled")
}

So, now if I have a redis plugin, I can set ehcacheplugin=disabled in my config, and then it will bind RedisCache to CacheAPI in the same way that the ehcache plugin does above.

So that's one mechanism - though possibly not the nicest mechanism.  The other possibility I think is that we provide a better way to register plugins, that allows the user to explicitly deregister plugins that register themselves.  I've got no idea what this might look like, but it may be, as your current pull request allows, in the InjectionProvider, and the injection provider will provide a mechanism to add/filter out disabled plugins.  Of course that design will also mean that you can override it to automatically detect no plugins, and you are responsible for binding things (or instantiating all the play modules you want and binding them) yourself.  Some people may prefer that approach.  I'm not sure what should be provided out of the box.  We can iterate on the design here a bit.

Julien Richard-Foy

unread,
Jun 17, 2014, 7:28:21 AM6/17/14
to James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
It's not just that, it also gives you a way to access shared resources - it is a provider of components.  The most ugly part of the plugin trait I think is actually the start/stop side of things - it depends on arbitrarily chosen numbers for ordering in the config file.  While this will still work in Play 2.4, it's something that we want to move away from.  I suspect in Play 2.4, none of the built in plugins will actually provide an implementation of start/stop, Play will still invoke start/stop at the appropriate times, but only for backwards compatibility.  In Play 3.0 we can completely remove them.

I love that philosophy.

Greg Methvin

unread,
Jun 18, 2014, 2:15:15 AM6/18/14
to Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-fram...@googlegroups.com
Okay, so it seems like the idea is to provide a generic API for integrating any DI framework, in addition to a way to define "modules" for the framework which bind other dependencies. Ideally this would be a two-way integration, so a dependency bound by a Play module would be accessible in Guice/Spring/Subcut/etc., and vice versa.

How sophisticated do you guys think this binding framework needs to be? I'd prefer to keep it fairly minimal. We could also choose some existing DI implementation and go with that as the default, but depending on what we use it could be tricky to provide a convenient API for integrating with users' own DI tools.

James Roper

unread,
Jun 18, 2014, 4:44:12 AM6/18/14
to Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com


On Wed, Jun 18, 2014 at 8:14 AM, Greg Methvin <greg.m...@gmail.com> wrote:
>
> Okay, so it seems like the idea is to provide a generic API for integrating any DI framework, in addition to a way to define "modules" for the framework which bind other dependencies. Ideally this would be a two-way integration, so a dependency bound by a Play module would be accessible in Guice/Spring/Subcut/etc., and vice versa.

Yes.

 
> How sophisticated do you guys think this binding framework needs to be? I'd prefer to keep it fairly minimal. We could also choose some existing DI implementation and go with that as the default, but depending on what we use it could be tricky to provide a convenient API for integrating with users' own DI tools.

Completely agree, it should be minimal. I would say we need to provide the following feature set, and no more:

* bind implementation class to interface
* bind Provider to interface
* bind instance to interface
* named bindings
* eager singletons (this may or may not be achieved using the DI framework)

Things that I think we should specifically leave out of scope:

* scoped bindings - this doesn't really fit with Play's way doing things
* parameterised type bindings - if you want to dependency inject a list of things for example, it's really not hard to just wrap it in another type

A few other things that I've been thinking about as a result of a few discussions at ScalaDays:

* config: should we inject a config object and use that, or should we inject each config item with a named binding? I'm tending toward the first, since that means we can add new config without changing the constructor (and public api)
* Scala: I'm thinking more and more that we should provide out of the box support for either macwire or subcut. This would mean we provide traits for mixing in the default play components. With macwire, I don't think we even need to have a dependency on it, if we just provide traits with manually wired core modules as lazy vals, then it will be very easy with very minimal effort for an end user to use macwire. I need to check out subcut to see how it would fit into play.

--
James Roper
Software Engineer

Typesafe – Build reactive apps!
Twitter: @jroper

SEE YOU IN BERLIN
Scala
Days
June 16th-18th,
Berlin

Yann Simon

unread,
Jun 18, 2014, 6:59:59 AM6/18/14
to James Roper, Julien Richard-Foy, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev


On Jun 18, 2014 10:44 AM, "James Roper" <ja...@typesafe.com> wrote:
>
>
> On Wed, Jun 18, 2014 at 8:14 AM, Greg Methvin <greg.m...@gmail.com> wrote:
> >
> > Okay, so it seems like the idea is to provide a generic API for integrating any DI framework, in addition to a way to define "modules" for the framework which bind other dependencies. Ideally this would be a two-way integration, so a dependency bound by a Play module would be accessible in Guice/Spring/Subcut/etc., and vice versa.
>
> Yes.
>  
> > How sophisticated do you guys think this binding framework needs to be? I'd prefer to keep it fairly minimal. We could also choose some existing DI implementation and go with that as the default, but depending on what we use it could be tricky to provide a convenient API for integrating with users' own DI tools.
>
> Completely agree, it should be minimal. I would say we need to provide the following feature set, and no more:
>
> * bind implementation class to interface
> * bind Provider to interface
> * bind instance to interface
> * named bindings
> * eager singletons (this may or may not be achieved using the DI framework)
>
> Things that I think we should specifically leave out of scope:
>
> * scoped bindings - this doesn't really fit with Play's way doing things
> * parameterised type bindings - if you want to dependency inject a list of things for example, it's really not hard to just wrap it in another type
>
> A few other things that I've been thinking about as a result of a few discussions at ScalaDays:
>
> * config: should we inject a config object and use that, or should we inject each config item with a named binding? I'm tending toward the first, since that means we can add new config without changing the constructor (and public api)
> * Scala: I'm thinking more and more that we should provide out of the box support for either macwire or subcut. This would mean we provide traits for mixing in the default play components. With macwire, I don't think we even need to have a dependency on it, if we just provide traits with manually wired core modules as lazy vals, then it will be very easy with very minimal effort for an end user to use macwire. I need to check out subcut to see how it would fit into play.

I can recommend you to have a look at scaldi as well. It already integrates with play and has a good implementation of modules IMO.

http://scaldi.org


>
> --
> James Roper
> Software Engineer
>
> Typesafe – Build reactive apps!
> Twitter: @jroper
>
> SEE YOU IN BERLIN
> Scala
> Days
> June 16th-18th,
> Berlin
>
> On 18 Jun 2014 08:15, "Greg Methvin" <greg.m...@gmail.com> wrote:
>>
>> Okay, so it seems like the idea is to provide a generic API for integrating any DI framework, in addition to a way to define "modules" for the framework which bind other dependencies. Ideally this would be a two-way integration, so a dependency bound by a Play module would be accessible in Guice/Spring/Subcut/etc., and vice versa.
>>
>> How sophisticated do you guys think this binding framework needs to be? I'd prefer to keep it fairly minimal. We could also choose some existing DI implementation and go with that as the default, but depending on what we use it could be tricky to provide a convenient API for integrating with users' own DI tools.
>

Martin Grotzke

unread,
Jun 18, 2014, 7:22:53 AM6/18/14
to James Roper, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev, Julien Richard-Foy

Am 18.06.2014 12:59 schrieb "Yann Simon" <yann.s...@gmail.com>:
>
> I can recommend you to have a look at scaldi as well. It already integrates with play and has a good implementation of modules IMO.
>
> http://scaldi.org

Here's a (biased) comparison of subcut and scaldi: http://stackoverflow.com/a/16660055/130167

If play wouldn't come with scaldi support out of the box it would be great if we could contribute this so that it will be shipped with play then.

Cheers,
Martin

James Roper

unread,
Jun 18, 2014, 8:01:55 AM6/18/14
to Martin Grotzke, Julien Richard-Foy, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev

My hope is that whatever approach we take will allow third party libraries to provide support for other DI frameworks seamlessly and idiomatically. The plan for developing this is that we will release Play 2.4-M1 very early, as soon as we have exposed public constructors to internal components and have basic guice support, and at that time it would be awesome if people could start trying to integrate that with other DI frameworks, so that we can validate or modify the approach if necessary.

>
> Cheers,
> Martin

Martin Grotzke

unread,
Jun 18, 2014, 9:42:16 AM6/18/14
to James Roper, Greg Methvin, Julien Richard-Foy, play-fram...@googlegroups.com, Pascal Voitot Dev

Sounds good!

Cheers,
Martin

Rich Dougherty

unread,
Jun 18, 2014, 1:05:48 PM6/18/14
to James Roper, Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
On Wed, Jun 18, 2014 at 10:44 AM, James Roper <ja...@typesafe.com> wrote:

Completely agree, it should be minimal. I would say we need to provide the following feature set, and no more:

* bind implementation class to interface
* bind Provider to interface
* bind instance to interface
* named bindings
* eager singletons (this may or may not be achieved using the DI framework)

Things that I think we should specifically leave out of scope:

* scoped bindings - this doesn't really fit with Play's way doing things
* parameterised type bindings - if you want to dependency inject a list of things for example, it's really not hard to just wrap it in another type

I agree with all that.

In 2.4 we'll want to have a way to get different setups for Prod, Dev and Testing mode, but hopefully using the DI system. One option for distinguishing config for different modes might be to use a JSR330 qualifier annotation. But we could probably get the same effect without using that feature, just by loading slightly different binding modules depending which mode we're running in.

I'd like to remove the idea of an explicit "mode" value in 3.0 and just rely on DI to inject different configuration when we start the application in prod, dev and testing.

A few other things that I've been thinking about as a result of a few discussions at ScalaDays:

* config: should we inject a config object and use that, or should we inject each config item with a named binding? I'm tending toward the first, since that means we can add new config without changing the constructor (and public api)

Are you talking about these two approaches to config?

1. class MyClass(config: com.typesafe.config.Config)
2. class MyClass(setting1: @Named("Setting1") String)

There's also this approach:

3. class MyClass(config: MyConfig)

In option 3 if we need a new setting then we would change MyConfig. This would be a public API change, but users of MyConfig wouldn't have to change their constructor args.

* Scala: I'm thinking more and more that we should provide out of the box support for either macwire or subcut. This would mean we provide traits for mixing in the default play components. With macwire, I don't think we even need to have a dependency on it, if we just provide traits with manually wired core modules as lazy vals, then it will be very easy with very minimal effort for an end user to use macwire. I need to check out subcut to see how it would fit into play.

That's a good idea. Depending on how we do our bindings, if we can make bindings statically known somehow, then it might be possible to use a macro to generate application initialisation code.

Cheers
Rich

--
Rich Dougherty - @richdougherty
Engineer - Typesafe, Inc

Greg Methvin

unread,
Jun 18, 2014, 6:32:00 PM6/18/14
to Rich Dougherty, James Roper, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com

* bind implementation class to interface
* bind Provider to interface
* bind instance to interface
* named bindings
* eager singletons (this may or may not be achieved using the DI framework)

We might be able to get away without having named bindings by always injecting custom types. I've never found named bindings that useful, but that could be because it's easier to create wrapper classes or "config" case classes in Scala.
 
I'd like to remove the idea of an explicit "mode" value in 3.0 and just rely on DI to inject different configuration when we start the application in prod, dev and testing.

Agreed. Any internal logic that depends on the mode, or any global parameter from the application, is a bad idea, and will just make your components less testable.

Are you talking about these two approaches to config?

1. class MyClass(config: com.typesafe.config.Config)
2. class MyClass(setting1: @Named("Setting1") String)

There's also this approach:

3. class MyClass(config: MyConfig)

I tend to use option 3 a lot in my own code, especially when I have configuration mixed with other dependencies. Another thing that works is to define a Provider which constructs it, like this:

@Provides def myClass(conf: Configuration): MyClass =
  new MyClass(setting1 = conf.getString("setting1"), setting2 = conf.getString("setting2"))

For the compile-time frameworks, the easiest thing would be for Play to provide a trait with lazy vals or defs for all the dependencies the framework can provide (e.g. configuration, WSClient, etc.), then you can just directly access those methods.

James Roper

unread,
Jun 19, 2014, 5:21:33 AM6/19/14
to Greg Methvin, Rich Dougherty, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
On Thu, Jun 19, 2014 at 12:31 AM, Greg Methvin <greg.m...@gmail.com> wrote:

* bind implementation class to interface
* bind Provider to interface
* bind instance to interface
* named bindings
* eager singletons (this may or may not be achieved using the DI framework)

We might be able to get away without having named bindings by always injecting custom types. I've never found named bindings that useful, but that could be because it's easier to create wrapper classes or "config" case classes in Scala.

I'm just thinking about the use case where you have multiple datasources, configured by name - the DB plugin can't use a different type for each since they are dynamically configured.  Of course we could (and definitely will) provide an interface to lookup a datasource, but it feels wrong to inject a dependency that you look dependencies up out of, you should just inject the dependency directly instead of having the indirection, and from a testing perspective, this means you have to double mock, first mocking the provider, to the return a mocked datasource.
  
I'd like to remove the idea of an explicit "mode" value in 3.0 and just rely on DI to inject different configuration when we start the application in prod, dev and testing.

Agreed. Any internal logic that depends on the mode, or any global parameter from the application, is a bad idea, and will just make your components less testable.

I don't see a clear distinction here.  At some point there has to be some logic looking at the mode and making a different decision based on it.  Consider error page rendering, we could create a default error page abstraction, with one implementation that renders detailed exceptions/source code in dev mode, and one implementation that renders a minimal error message - but I just don't see what we're gaining there over a switch, all I see is additional complexity - there is now a new abstraction (and therefore public API) for default error reporting, and there's more complex setup wiring code to ensure the right things happen.
 
Are you talking about these two approaches to config?

1. class MyClass(config: com.typesafe.config.Config)
2. class MyClass(setting1: @Named("Setting1") String)

There's also this approach:

3. class MyClass(config: MyConfig)

I tend to use option 3 a lot in my own code, especially when I have configuration mixed with other dependencies.

That makes sense.
 
Another thing that works is to define a Provider which constructs it, like this:

@Provides def myClass(conf: Configuration): MyClass =
  new MyClass(setting1 = conf.getString("setting1"), setting2 = conf.getString("setting2"))

For the compile-time frameworks, the easiest thing would be for Play to provide a trait with lazy vals or defs for all the dependencies the framework can provide (e.g. configuration, WSClient, etc.), then you can just directly access those methods.

Greg Methvin

unread,
Jun 19, 2014, 6:18:20 AM6/19/14
to James Roper, Rich Dougherty, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com

I don't see a clear distinction here.  At some point there has to be some logic looking at the mode and making a different decision based on it.  Consider error page rendering, we could create a default error page abstraction, with one implementation that renders detailed exceptions/source code in dev mode, and one implementation that renders a minimal error message - but I just don't see what we're gaining there over a switch, all I see is additional complexity - there is now a new abstraction (and therefore public API) for default error reporting, and there's more complex setup wiring code to ensure the right things happen.

What I meant was that you should avoid directly referencing properties of the application outside of your top-level modules. In the Global (e.g. onError) I think it's fine. Generally, though, if you want your code to be testable without an application (which currently requires global state) it's better to inject a configuration parameter or have different implementations.

Greg Methvin

unread,
Jun 19, 2014, 10:18:39 PM6/19/14
to James Roper, Rich Dougherty, Julien Richard-Foy, Pascal Voitot Dev, play-fram...@googlegroups.com
Also, we should decide on what the mechanism of injection is for the built-in modules. I think explicitly declaring the dependencies in the constructor is the best way to do it. I've taken a look at subcut and scaldi, and they seem to have nice binding DSLs, but I don't understand the advantage of passing the injector itself to the constructor rather than the dependencies themselves. I'd love to get thoughts from people who've used those frameworks in a large application, though.

Adam Warski

unread,
Jun 24, 2014, 5:52:33 AM6/24/14
to play-fram...@googlegroups.com
Hello,

jumping a bit late to the discussion, but I just found out about the thread on ScalaDays (thx James).
I'll note in the beginning that I'm probably biased, as I wrote Macwire (https://github.com/adamw/macwire), but I used quite a lot of CDI and Guice some time ago as well.

I think my main point would be to make sure that it's possible to wire up a complete Play application "by hand", just by writing down the "new ..." invocations. It's a very simple method of doing DI, but also very effective for small-medium applications. It also gives a lot of freedom, without the constraints that each framework imposes.

Secondly, I'm not quite sure how the reloading in Play works, so maybe that's not relevant; but it's important to keep in mind that each framework, especially a DI one, adds an additional peace of application-wide state to maintain. That is, after each code change, it is not enough to update the classes (using hotswap or whatever the mechanism is), it is also needed to update the DI container - which usually means recreating it. If the container relies on reflection and classpath scanning, especially in larger applications, the time needed to actually re-scan and re-read the metadata is noticeable and probably above what's a reasonable refresh timing. Here no-framework (pure-language) solutions win easily as the "DI" is simply using language constructs.

Finally, as for plugins - not a lot of opinions here, but it would certainly be nice if plugins provided a default way to wire the object graph it provides. It should be modifiable, of course (to replace a plugin's component with a custom one), but I guess by default not much work should be needed. Plus a way of expressing dependencies on existing (Play) components is needed as well, I suppose. A guice module, or a trait with the default wiring (thin cake pattern) should work fine here.

Adam

Oleg Ilyenko

unread,
Jun 24, 2014, 5:55:11 PM6/24/14
to play-fram...@googlegroups.com
Hi,

> My hope is that whatever approach we take will allow third party libraries to provide support for other DI frameworks seamlessly and idiomatically. The plan for developing this is that we will release Play 2.4-M1 very early, as soon as we have exposed public constructors to internal components and have basic guice support, and at that time it would be awesome if people could start trying to integrate that with other DI frameworks, so that we can validate or modify the approach if necessary.

Sounds great! As soon as M1 would be available I'll try to integrate it with scaldi and will give you my feedback.

Best regards,
Oleg

Greg Methvin

unread,
Jun 26, 2014, 9:36:56 PM6/26/14
to Oleg Ilyenko, play-fram...@googlegroups.com
I pretty much agree with Adam here. It would be great to be able to use thin cake pattern with all the Play core components. What I think I would do is have a PlayModule trait which defines all the dependencies the application should export:

trait PlayModule {
  def application: Application

  def wsClient: WSClient = application.inject[WSClient]
  def dbApi: DBApi = application.inject[DBApi]
  // ...
}

This way, I can mix in this trait to have compile time binding for my own application components, but other Play modules can add bindings at runtime.

Greg

--

Julien Richard-Foy

unread,
Jul 3, 2014, 1:56:08 PM7/3/14
to James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
Hi,

Just to be sure we understand each other:

On Tue, Jun 3, 2014 at 10:17 AM, James Roper <ja...@typesafe.com> wrote:
On Tue, Jun 3, 2014 at 5:39 PM, Julien Richard-Foy <j...@zengularity.com> wrote:
As long as we have play.api.Play.current, we can not have
constructor-based DI. I don’t really see how you can expect to give a
preview of what DI will look like in Play 3.0 if we still have a
global state in 2.4.

Why not?  Today you use WS by doing this:

WS.url(...)

And that depends on the global state.  In Play 2.4, you will be able to:

class MyController(wsClient: WSClient) {
  wsClient.url(...)
}

And that won't use global state, so you can test MyController in isolation.  You will still be able to use WS.url(...), but we will encourage the latter.  My hope is that in Play 2.4 all plugins will be accessible both through the current static mechanism, as well as through DI.

​Actually, if we complete the example we see that we *must* ​use runtime DI even though our controller class takes its dependencies in its constructor.

Indeed, if you want to use compile-time DI for your controller, it has to be defined as a static value, at some point (this is true only with the current design of the router). Maybe one could believe that he can define an object MyController like this:

// Easy to test!
class MyController(wsClient: WSClient) {
  …
}

// Finally, for the router
object MyController extends MyController(WS.client(play.api.Play.current))

​But the above simply does not work because play.api.Play.current is *not* a stable reference​ due to the hot reloading mechanism. It means that if your application is reloaded, the MyController object still refers to the old application.

So we can use compile-time DI for testing the controller in isolation but we have to pay a runtime DI overhead in prod.

Also, I’m not sure it is yet a good idea to encourage developers to use classes for their controllers because some parts of Play internally refer to Play.current (cf my comment on issue 3122), making it impossible to run the code that uses them without starting an application.

James Roper

unread,
Jul 4, 2014, 4:31:08 AM7/4/14
to Julien Richard-Foy, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev

We will be making an injectable router... Generating a router that declares its dependencies in a constructor. So a fully compile time injected application will be possible. And we hope to get rid of all dependence on Play.current internally, if not get rid of it altogether, in 3.0.

Julien Richard-Foy

unread,
Jul 4, 2014, 4:39:59 AM7/4/14
to James Roper, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev

We will be making an injectable router...

​I thought you wanted to do this for 3.0 only. So you mean that you plan to do it for 2.4? That’s a great news!​ ​We also need the ApplicationProvider thing that you described ​in the other thread, in order to achieve compile-time DI.

Julien Richard-Foy

unread,
Jul 4, 2014, 4:42:48 AM7/4/14
to James Roper, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev
 ​We also need the ApplicationProvider thing that you described ​in the other thread

​I mean “ApplicationLoader”, obviously.​

James Roper

unread,
Jul 4, 2014, 4:45:37 AM7/4/14
to Julien Richard-Foy, Greg Methvin, play-fram...@googlegroups.com, Pascal Voitot Dev

ApplicationLoader/Provider/Begetter/Whatever will definitely be in 2.4. A new router... Depends whether we have time or not. I think we could make it configurable (ie you choose which router implementation), so both can be generated.

Yann Simon

unread,
Jul 4, 2014, 4:56:28 AM7/4/14
to Julien Richard-Foy, James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
2014-07-03 19:56 GMT+02:00 Julien Richard-Foy <j...@zengularity.com>:

​Actually, if we complete the example we see that we *must* ​use runtime DI even though our controller class takes its dependencies in its constructor.

Indeed, if you want to use compile-time DI for your controller, it has to be defined as a static value, at some point (this is true only with the current design of the router). Maybe one could believe that he can define an object MyController like this:

// Easy to test!
class MyController(wsClient: WSClient) {
  …
}

// Finally, for the router
object MyController extends MyController(WS.client(play.api.Play.current))

​But the above simply does not work because play.api.Play.current is *not* a stable reference​ due to the hot reloading mechanism. It means that if your application is reloaded, the MyController object still refers to the old application.

Actually, this is a constellation I am using, and it works.
As far as I understand, the application classloader is renew for each application restart in dev mode.

Julien Richard-Foy

unread,
Jul 4, 2014, 5:23:52 AM7/4/14
to Yann Simon, James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
Actually, this is a constellation I am using, and it works.

​Is a new controller object created each time you perform a request? How does your DI mechanism know that a controller is dirty (due to an application reload) and must be recreated?​

Yann Simon

unread,
Jul 4, 2014, 6:05:12 AM7/4/14
to Julien Richard-Foy, James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
2014-07-04 11:23 GMT+02:00 Julien Richard-Foy <j...@zengularity.com>:
Actually, this is a constellation I am using, and it works.

​Is a new controller object created each time you perform a request? How does your DI mechanism know that a controller is dirty (due to an application reload) and must be recreated?​

The new controller object should be created after each application reload.
I think that, as the class loader with the old instances is removed, the new class loader does not know this controller yet and instantiates a new one.
I'll check that.

Jean Helou

unread,
Jul 4, 2014, 6:19:17 AM7/4/14
to play-fram...@googlegroups.com


Damn phone my answer went to julien alone.

> I am pretty sure all application code is loaded in a specific classloader.
>
> When a file is changed leading to an app restart in Dev mode, the whole class loader gets discarded including any object instances it might have held.
> This in turn forces a reinit of everything and thus the the references are correct
>
> When testing however one doesn't use the object, but instanciates the class directly instead, giving a mock/stub/dummy for the dependency or even a concrete implem referencing the fake application in scope.
>
> I use a variation of this with traits having abstract members which are actually implemented in the object or in a class for tests. The constructor solution is cleaner but we lacked time to refactor.
>
> Jean


>
> Le 4 juil. 2014 11:23, "Julien Richard-Foy" <j...@zengularity.com> a écrit :
>
>>> Actually, this is a constellation I am using, and it works.
>>
>>
>> ​Is a new controller object created each time you perform a request? How does your DI mechanism know that a controller is dirty (due to an application reload) and must be recreated?​
>>

Julien Richard-Foy

unread,
Jul 4, 2014, 6:55:53 AM7/4/14
to Yann Simon, James Roper, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
Said otherwise, my question is: how does the DI system know that it can reuse the same previous instance instead of re-creating one, when we call its getInstance method?
--
  Z E N G U L A R I T Y
––––––––––––––––––––––
Julien RICHARD-FOY - Programmer

56 rue Saint Lazare 75009 Paris
625 Market Street - San Francisco

James Roper

unread,
Jul 7, 2014, 6:59:38 PM7/7/14
to Julien Richard-Foy, Yann Simon, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
On Fri, Jul 4, 2014 at 10:55 PM, Julien Richard-Foy <j...@zengularity.com> wrote:
Said otherwise, my question is: how does the DI system know that it can reuse the same previous instance instead of re-creating one, when we call its getInstance method?

The DI system will have its lifecycle bound to the Application - when a new Application is created, a new DI container will be created.
 


On Fri, Jul 4, 2014 at 12:05 PM, Yann Simon <yann.s...@gmail.com> wrote:



2014-07-04 11:23 GMT+02:00 Julien Richard-Foy <j...@zengularity.com>:

Actually, this is a constellation I am using, and it works.

​Is a new controller object created each time you perform a request? How does your DI mechanism know that a controller is dirty (due to an application reload) and must be recreated?​

The new controller object should be created after each application reload.
I think that, as the class loader with the old instances is removed, the new class loader does not know this controller yet and instantiates a new one.
I'll check that.




--
  Z E N G U L A R I T Y
––––––––––––––––––––––
Julien RICHARD-FOY - Programmer

56 rue Saint Lazare 75009 Paris
625 Market Street - San Francisco

--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James Roper

unread,
Jul 16, 2014, 3:52:18 AM7/16/14
to Adam Warski, play-fram...@googlegroups.com
Adam,

Thanks for your thoughts here.

For the reloading, we have a single entry point, ApplicationLoader.  A compile time DI user will implement this themselves, this is loaded reflectively, and it is expected to return an "Application", which knows how to handle requests, etc.

We're now in the thick of starting to implement this stuff, and I'm interested in what you think the best way to express dependencies on existing Play components or components from other modules is.

A very lightweight way would be to simply declare an abstract method:

trait PlayModule {
  lazy val somePlayComponent: SomePlayComponent = new SomePlayComponentImpl

trait MyModule {
  def somePlayComponent: SomePlayComponent
  lazy val myComponent: MyComponent = new MyComponentImpl(somePlayComponent)
}

object MyApp extends PlayModule with MyModule

These methods would be named by convention.  It would be very easy to substitute in different implementations, very easy to mock somePlayComponent, etc.

Another possibility is to use a very thin cake pattern:

trait PlayModule {
  lazy val somePlayComponent: SomePlayComponent = new SomePlayComponentImpl
}

trait MyModule {
  self: PlayModule =>
  lazy val myComponent: MyComponent = new MyComponentImpl(somePlayComponent)
}

This makes the dependencies strongly typed, not just mixed in by convention.  You can still override somePlayComponent here as the end user, but if I have another module that depends on MyModule, and I want to mock myComponent, so I no longer need PlayModule, it's still going to bring in that PlayModule dependency.

The final option of course is to go the full cake pattern:

trait PlayModule {
  def somePlayComponent: SomePlayComponent
}

trait PlayModuleImpl extends PlayModule {
  lazy val somePlayComponent = new SomePlayComponentImpl
}

trait MyModule {
  def myComponent: MyComponent
}

trait MyModuleImpl extends MyModule {
  self: PlayModule =>
  lazy val myComponent = new MyComponentImpl(somePlayComponent)
}

Now I've got the full power of being able to do anything, but of course it also means I have the full verbosity of the Cake pattern.

In your experience (and anyone elses) what would be the best approach here?  I'm tending towards the first approach, it is very lightweight, and completely optional - if the trait didn't quite do what you need to do, you can always fallback to just using plain constructors, which a framework like macwire would make a lot easier for you too.

Thoughts?


--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Fehmi Can Saglam

unread,
Jul 16, 2014, 6:04:32 AM7/16/14
to Adam Warski, James Roper, play-fram...@googlegroups.com
James,

Just a quick question. I can understand how I can define multiple applications wired using different dependencies. But how am I going to specify which application to be loaded? For example one for development, one for production and one for test…

Thanks,
Fehmi Can Saglam
> >> *James Roper*
> >> *Software Engineer*
> >>
> >> Typesafe – Build reactive apps!
> >> Twitter: @jroper
> >>
> >> SEE YOU IN BERLIN
> >> Scala
> >> Days
> >> June 16th-18th,
> >> Berlin
> >>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Play framework dev" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to play-framework-...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
> >
>
>
>
> --
> *James Roper*
> *Software Engineer*
>
> Typesafe – Build reactive apps!
> Twitter: @jroper
>

James Roper

unread,
Jul 16, 2014, 6:17:49 AM7/16/14
to Fehmi Can Saglam, Adam Warski, play-fram...@googlegroups.com
On Wed, Jul 16, 2014 at 10:04 PM, Fehmi Can Saglam <fehmica...@gmail.com> wrote:
James,

Just a quick question. I can understand how I can define multiple applications wired using different dependencies. But how am I going to specify which application to be loaded? For example one for development, one for production and one for test…

With compile time dependency injection, in tests, the test you write is in complete control.  We haven't nailed down how these interfaces will look, but presumably it will look something like this:

"my app" should {
  "do something" in new WithServer(MyTestApp.application) {
    ...
  }
}

So you're in complete control because it's you that creates and wires together test app, and you just pass it to the server. 

Now in prod mode, I think you'll have two options, either implement the main method yourself, and wire together the server with the application yourself, or use the ApplicationLoader mechanism to implement an ApplicationLoader, and just wire the application, letting server take care of itself.  In dev mode, it will be using the ApplicationLoader.  If you used the ApplicationLoader for prod as well, and you want different wirings for dev and prod, you have two options - implement a different ApplicationLoader for dev to the one for prod, or, the application loader trait looks like this:

trait ApplicationLoader {
  def load(env: Environment, initialConfiguration: Configuration): Application
}

Environment contains the mode (dev, test or prod), so you can there look at the mode and wire things differently based on dev or prod.



--
James Roper
Software Engineer

Jean Helou

unread,
Jul 16, 2014, 6:38:13 AM7/16/14
to James Roper, Julien Richard-Foy, Yann Simon, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
On Tue, Jul 8, 2014 at 12:59 AM, James Roper <ja...@typesafe.com> wrote:
The DI system will have its lifecycle bound to the Application - when a new Application is created, a new DI container will be created.


Some applications can take a "long time" to start (for various reasons). Dropping and reloading the whole app/container state is the easy way to do reload but it can make the autoreload feature very slow. 
Will there be a way to disable autoreload for dev mode so that at least when using a "classic" DI system (read spring/guice), one can use JRebel to handle reloading. IIRC Jrebel more or less creates a classloader instance/hierarchy for every class and only restarts the parts of the object graph which depend on the reloaded component.


Jean

James Roper

unread,
Jul 16, 2014, 8:31:05 AM7/16/14
to Jean Helou, Julien Richard-Foy, Yann Simon, Greg Methvin, Pascal Voitot Dev, play-fram...@googlegroups.com
There are people in the community that already use Play with JRebel - I don't think anything is going to change around that.

Adam Warski

unread,
Jul 16, 2014, 10:40:59 AM7/16/14
to James Roper, Adam Warski, play-fram...@googlegroups.com
Hello,

In your experience (and anyone elses) what would be the best approach here?  I'm tending towards the first approach, it is very lightweight, and completely optional - if the trait didn't quite do what you need to do, you can always fallback to just using plain constructors, which a framework like macwire would make a lot easier for you too.

Thoughts?

I tried using both the cake pattern and the “lightweight” approach, and I would definitely recommend the “lightweight” one. It works great in a couple of projects we are working on. It’s easy to understand and easy to use; the naming convention is also quite straightforward, and it hasn’t been a problem for us.

In fact, the first approach you describe is what I call the “Thin Cake Pattern” (without the self-types, which as you noted, force to bring in the more traits when testing): http://www.warski.org/blog/2014/02/using-scala-traits-as-modules-or-the-thin-cake-pattern/ 

Adam


Julien Richard-Foy

unread,
Jan 4, 2015, 9:55:33 AM1/4/15
to Adam Warski, James Roper, Adam Warski, play-fram...@googlegroups.com
Hi,

Here is some feedback of my experience with Play 2.4 and dependency injection. I started with the Scala application taken from my book Play Framework Essentials, which was based on Play 2.3 and was using runtime dependency injection with Guice, and I upgraded it to Play 2.4, still with Guice, and then moved to compile-time dependency injection (just follow the links to see the code).

The main features exercised by my project are the following:
 — Use different databases for test and run ;
 — Populate the database differently for test and run ;
 — Isolate the service layer from the whole application ;
 — Use the CSRF filter ;
 — Use Akka ;
 — Use i18n ;
 — Use evolutions ;
 — Use cache ;
 — Use WSClient.

I was globally satisfied but some rough edges still exist, here is a summary of them. First, when I upgraded to 2.4 while still using runtime DI:

 — I needed to add a resolver to get sbt correctly resolve a scalaz dependency ;

 — In application.conf, while you can write:
    play.modules.enabled += "some.Module"
or:
but you can not write:
    play.modules.enabled += ["some.Module", "some.OtherModule"]
(this is more a HOCON concern than a Play concern) ;

 — The supported configuration is still inconsistent between some components. For instance the jdbc component still uses the “db” key prefix and the application’s secret key still uses the “application.secret” key while the evolutions component uses the “play.modules.evolutions” key prefix. I think we should always use keys under the “play” prefix (so, in the examples above we should use “play.modules.jdbc” instead of “db”, and “play.application.secret” instead of “application.secret”). I’m not sure we should keep the “modules” subkey: why not use “play.evolutions” and “play.i18n” instead of “play.modules.evolutions” and “play.modules.i18n”, respectively?

 — The conversion to the new way of achieving DI was straightforward (I just had to define injectable constructors for my modules and, if needed, define their bindings) and internal Play things worked well. However, I got some troubles when I wanted to customize the wiring in tests. For instance, I couldn’t find a way to add a binding to a mock that is still in the scope of my test code (so that I can control the behavior of this mock). Here is what I did with 2.3 (where GuiceInjector is a GlobalSetting subclass that sets up a Guice injector). The 2.4 version I wrote does not work: I get a NullPointerException here. This is definitely a use case we should straightforwardly support ;

 — More generally, the WithApplicationLoader scope (that I wrote) is of very little help because we can not pass it custom configuration settings. It is very common to load some common modules in both test and run modes but to customize the behaviour of some module via the configuration (typically, the database URL for the jdbc module). WithApplicationLoader allows us to set which ApplicationLoader to use and eventually to define custom bindings, but it does not help to define custom configuration settings. To workaround this limitation I used WithApplication instead of WithApplicationLoader everywhere I could, and used its additionalConfiguration parameter to define my custom configuration.

 — Then I upgraded the code base to use compile-time dependency injection. Contrary to runtime DI, the experience with compile-time DI was tougher because there is almost no documentation (for each module we should document how it is intended to be used with a compile-time DI approach, e.g. for the evolutions module we should tell users that at some point they have to explicitly evaluate the applicationEvolutions lazy val) and, above all, because Play internals still rely on runtime DI at some places:
     — The HTML helpers internally use the i18n API based on runtime DI (in that case I think we could fix this by passing them an implicit Messages instead of an implicit Lang) ;
     — The “request2Lang” member of Controller does the same ;
     — The “route” member of the test helpers delegates to the application’s “global” member to retrieve the handler for a given request, and this “global” member is itself initialized using the runtime dependency injector. I think the first problem could be solved by using the application’s “requestHandler” member instead of “global”, like I did here. The second problem (the initialization of the “global” member of Application) seems harder to solve.

 — More generally, it was difficult, for a given module, to know if it relies on a runtime injector or not. For instance, the jdbc module provides a “DB” object whose methods all have an implicit parameter of type Application so that the actual DBApi to use can be retrieved using the application’s injector. The same applies to the i18n module and its “Messages” object. Maybe this kind of APIs should be deprecated so that users always retrieve the DBApi or the MessagesApi in their module dependencies instead of using this level of indirection via the application’s injector, but, more importantly, I think that code using these APIs should not compile when you don’t use a runtime injector. In the same vein, I think that Application should not have an “injector” member.

 — It was not straightforward to use the i18n module. First, I had to define an implicit conversion from RequestHeader to Messages in my controllers, and then at usage site I had to write this inconvenient syntax. I think that a solution to this problem could be to make the Messages object take an implicit Messages parameter instead of Lang (so we could use the same syntax as in 2.3 to get i18n, provided we have such an implicit conversion from RequestHeader to Messages).

 — It looks weird that we set which ApplicationLoader to use in the application.conf file. This is especially a non-sense when we use a FakeApplication, which is definitely not leaded via our custom ApplicationLoader but still uses it to load some modules (excepted the FakeApplication itself, obviously).

 — This point is maybe related to the previous one, it may happen that one wants to reuse a component of Play without having to rely on the whole ApplicationLoader machinery. For instance, to reuse the evolutions component in my tests I can write a trait defining how to wire the components of my service and then use it to create my service in my tests. It turns out that in that case I don’t need an application (nor a router), I just need an Environment or a Configuration. That’s why I created a WithContext specs2 scope that creates a Context (which contains an environment and a configuration) and that supports the definition of custom configuration settings, unlike WithApplicationLoader.
     — BTW I think that the member “initialConfiguration” of Context should be named just “configuration”.

 — I was happy to use WithApplicationLoader to run my tests using my custom application loader, but only after I wrote a method to modify the configuration settings.

 — It was not possible to directly use WithBrowser because it takes a FakeApplication as parameter, though I was only able to produce an Application with my ApplicationLoader. I copy-pasted it and just changed its signature so that it takes an Application instead of a FakeApplication and it worked well. I hope we can apply the same change in Play.

 — Note that I was still unable to wire a dependency to a mock while keeping a reference to it in the scope of my tests. Here, my workaround was to write my tests using just my controller instead of a running application but I think we should also support testing using a running application.

 — I had troubles using the injected router because by default routers are generated in the empty package which you can not refer to unless you are in the empty package too. My workaround was to make my routers always use subpackages.

 — I had to add this line to get the evolutions component working. I think the dynamicEvolution member should not be abstract in the EvolutionsComponents, am I correct?

That’s all for today!
Cheers,
Julien

James Roper

unread,
Jan 4, 2015, 8:08:35 PM1/4/15
to Julien Richard-Foy, Adam Warski, Adam Warski, play-fram...@googlegroups.com
Hey Julien,

Wow!  This feedback is so valuable, and good timing too.  Some responses inline:

On Mon, Jan 5, 2015 at 1:55 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
 — I needed to add a resolver to get sbt correctly resolve a scalaz dependency ;

This is already fixed on master.
 
 — In application.conf, while you can write:
    play.modules.enabled += "some.Module"
or:
but you can not write:
    play.modules.enabled += ["some.Module", "some.OtherModule"]
(this is more a HOCON concern than a Play concern) ;

So I just raised a feature request for ++= here:


 — The supported configuration is still inconsistent between some components. For instance the jdbc component still uses the “db” key prefix and the application’s secret key still uses the “application.secret” key while the evolutions component uses the “play.modules.evolutions” key prefix. I think we should always use keys under the “play” prefix (so, in the examples above we should use “play.modules.jdbc” instead of “db”, and “play.application.secret” instead of “application.secret”). I’m not sure we should keep the “modules” subkey: why not use “play.evolutions” and “play.i18n” instead of “play.modules.evolutions” and “play.modules.i18n”, respectively?

Yes, this is an ongoing thing.  One difficulty with changing the configuration is it's hard to deprecate.  We've got some helpers at the moment that will look up the old key, and output a deprecation warning at runtime if it's found, this works well in some cases.  I'm not sure if we'll get through moving all configuration to the new format by Play 2.4, but pull requests are certainly welcome - just try and do it in such a way that users get notification that it's changed - eg for jdbc, it may make sense to check both the db key and the new key, and output a warning for each datasource found under the db key.

With regards to the modules prefix, it's a good point - perhaps it's not needed.  Anyone else have any preference here?

 — The conversion to the new way of achieving DI was straightforward (I just had to define injectable constructors for my modules and, if needed, define their bindings) and internal Play things worked well. However, I got some troubles when I wanted to customize the wiring in tests. For instance, I couldn’t find a way to add a binding to a mock that is still in the scope of my test code (so that I can control the behavior of this mock). Here is what I did with 2.3 (where GuiceInjector is a GlobalSetting subclass that sets up a Guice injector). The 2.4 version I wrote does not work: I get a NullPointerException here. This is definitely a use case we should straightforwardly support ;

I'm doing work in this area right now.  I'm not sure if I've said this elsewhere, but I think we could have a guice application builder, that allows providing guice override modules and/or bindings.  This probably wouldn't be used in combination with the With* helpers.
 
 — More generally, the WithApplicationLoader scope (that I wrote) is of very little help because we can not pass it custom configuration settings. It is very common to load some common modules in both test and run modes but to customize the behaviour of some module via the configuration (typically, the database URL for the jdbc module). WithApplicationLoader allows us to set which ApplicationLoader to use and eventually to define custom bindings, but it does not help to define custom configuration settings. To workaround this limitation I used WithApplication instead of WithApplicationLoader everywhere I could, and used its additionalConfiguration parameter to define my custom configuration.

I've started writing tests (and helpers to aid this) that build on the Scala compile time DI components.  In many cases, this means custom configuration isn't even needed, because you simply instantiate the components you need for the test configured the way you need them to be for the test.  But this also makes it quite straight forward to inject configuration.
 
 — Then I upgraded the code base to use compile-time dependency injection. Contrary to runtime DI, the experience with compile-time DI was tougher because there is almost no documentation (for each module we should document how it is intended to be used with a compile-time DI approach, e.g. for the evolutions module we should tell users that at some point they have to explicitly evaluate the applicationEvolutions lazy val)

Agree that more documentation is needed here.  I'm a little cautious about cluttering the main documentation on each module - perhaps a compile time di modules page with notes on how to use each module would be useful?
 
and, above all, because Play internals still rely on runtime DI at some places:

Yeah, this is very hard to get away from until we've completely eradicated the global state - the current solution we have for this is to provide a simple injector that provides the compile time injected components that are currently needed - it seems like there may be a few extra components that we need to make available via this mechanism.
 
     — The HTML helpers internally use the i18n API based on runtime DI (in that case I think we could fix this by passing them an implicit Messages instead of an implicit Lang) ;

You're right about the fix, but I was trying to hold off doing that until Play 3.  I think we can solve this by putting the MessagesApi in the compile time injector.
 
     — The “request2Lang” member of Controller does the same ;
     — The “route” member of the test helpers delegates to the application’s “global” member to retrieve the handler for a given request, and this “global” member is itself initialized using the runtime dependency injector. I think the first problem could be solved by using the application’s “requestHandler” member instead of “global”, like I did here. The second problem (the initialization of the “global” member of Application) seems harder to solve.

Yes, the fix for the first problem is quite straight forward.  The second problem I don't think needs to be solved - it should be possible to write a Play application that never touches or instantiates any GlobalSettings object.  Any places in the core of Play that depend on global with no alternative should be fixed.
 
 — More generally, it was difficult, for a given module, to know if it relies on a runtime injector or not. For instance, the jdbc module provides a “DB” object whose methods all have an implicit parameter of type Application so that the actual DBApi to use can be retrieved using the application’s injector. The same applies to the i18n module and its “Messages” object. Maybe this kind of APIs should be deprecated so that users always retrieve the DBApi or the MessagesApi in their module dependencies instead of using this level of indirection via the application’s injector, but, more importantly, I think that code using these APIs should not compile when you don’t use a runtime injector. In the same vein, I think that Application should not have an “injector” member.

In some ways this problem already exists - it's difficult to know, for any API in Play today, whether it depends on Global state (and therefore needs WithApplication etc when testing).  So we've kind of inherited this problem.  The DB and Messages objects should be deprecated, yes, but the question is when - what I'm not sure about is, if we deprecate it in 2.4, how will users react to upgrading to 2.4 and finding that every single API call they make in Play is deprecated?  We want to make the transition to 2.4 as smooth as possible, and this means supporting both the old and new APIs concurrently.  Our current plan is that we'll release Play 2.5 at some point, which will be Play 2.4 + deprecation warnings, and will give users a chance to see what they need to change for Play 3, and then we'll release Play 3.0, and all these APIs will be removed.

You're right, Application should not have an injector, Play 3 will not have it, this is just a transitional thing while we still support the old APIs that depend on global state for a smooth transition to Play 2.4.
 
 — It was not straightforward to use the i18n module. First, I had to define an implicit conversion from RequestHeader to Messages in my controllers, and then at usage site I had to write this inconvenient syntax. I think that a solution to this problem could be to make the Messages object take an implicit Messages parameter instead of Lang (so we could use the same syntax as in 2.3 to get i18n, provided we have such an implicit conversion from RequestHeader to Messages).

This is good to know, we'll have to come up with a way to generically solve this.
 
 — It looks weird that we set which ApplicationLoader to use in the application.conf file. This is especially a non-sense when we use a FakeApplication, which is definitely not leaded via our custom ApplicationLoader but still uses it to load some modules (excepted the FakeApplication itself, obviously).

I'm hoping that by the time we release Play 2.4, we'll have comprehensive alternatives to FakeApplication for all types of testing, that are better and easier to use.  With that, FakeApplication will just be something that exists so that you don't have to rewrite all your existing tests when you upgrade from Play 2.3 to 2.4.
 
 — This point is maybe related to the previous one, it may happen that one wants to reuse a component of Play without having to rely on the whole ApplicationLoader machinery. For instance, to reuse the evolutions component in my tests I can write a trait defining how to wire the components of my service and then use it to create my service in my tests. It turns out that in that case I don’t need an application (nor a router), I just need an Environment or a Configuration. That’s why I created a WithContext specs2 scope that creates a Context (which contains an environment and a configuration) and that supports the definition of custom configuration settings, unlike WithApplicationLoader.

Here's an example of what I've done to implement testing using evolutions/database without instantiating a whole application:


At the bottom of that spec is number of helpers, these I've already started generalising and pulling into Play.
 
     — BTW I think that the member “initialConfiguration” of Context should be named just “configuration”. 

My thinking behind initialConfiguration is that this configuration is used to pass config from sbt to Play, and then the application loader loads the configuration files and merges initial configuration in with that.
 
 — I was happy to use WithApplicationLoader to run my tests using my custom application loader, but only after I wrote a method to modify the configuration settings.

 — It was not possible to directly use WithBrowser because it takes a FakeApplication as parameter, though I was only able to produce an Application with my ApplicationLoader. I copy-pasted it and just changed its signature so that it takes an Application instead of a FakeApplication and it worked well. I hope we can apply the same change in Play.

Definitely.
 
 — Note that I was still unable to wire a dependency to a mock while keeping a reference to it in the scope of my tests. Here, my workaround was to write my tests using just my controller instead of a running application but I think we should also support testing using a running application.

Yes, I think in this case we need to look at not using Specs around scopes, but functions that take functions, this I think is more flexible because it means you can easily set up some scope before everything is started, such as the mocks.  I also think we should encourage people to use this pattern liberally in their own tests, of creating helpers specific to their own use case.
 
 — I had troubles using the injected router because by default routers are generated in the empty package which you can not refer to unless you are in the empty package too. My workaround was to make my routers always use subpackages.

_root_ doesn't work?
 
 — I had to add this line to get the evolutions component working. I think the dynamicEvolution member should not be abstract in the EvolutionsComponents, am I correct?

I'm not sure - dynamic evolutions exist to allow generating evolutions using schema generation tools.
 
That’s all for today!

Cool thanks!  Keep the feedback coming!
 
Cheers,
Julien

Julien Richard-Foy

unread,
Jan 5, 2015, 2:49:10 AM1/5/15
to James Roper, Adam Warski, Adam Warski, play-fram...@googlegroups.com
Yeah, this is very hard to get away from until we've completely eradicated the global state - the current solution we have for this is to provide a simple injector that provides the compile time injected components that are currently needed - it seems like there may be a few extra components that we need to make available via this mechanism.

​I’m not sure to see what you mean by this “inject that provides compile time injected components”.​ Can you point me to the code?

     — The “request2Lang” member of Controller does the same ;
     — The “route” member of the test helpers delegates to the application’s “global” member to retrieve the handler for a given request, and this “global” member is itself initialized using the runtime dependency injector. I think the first problem could be solved by using the application’s “requestHandler” member instead of “global”, like I did here. The second problem (the initialization of the “global” member of Application) seems harder to solve.

Yes, the fix for the first problem is quite straight forward.


 — It was not straightforward to use the i18n module. First, I had to define an implicit conversion from RequestHeader to Messages in my controllers, and then at usage site I had to write this inconvenient syntax. I think that a solution to this problem could be to make the Messages object take an implicit Messages parameter instead of Lang (so we could use the same syntax as in 2.3 to get i18n, provided we have such an implicit conversion from RequestHeader to Messages).

This is good to know, we'll have to come up with a way to generically solve this.

We could provide the following trait:

trait MessagesSupport {

  def messagesApi: MessagesApi

  implicit def request2Messages(implicit rh: RequestHeader): Messages = messagesApi.preferred(rh)

}​

So that users just have to mix it in their controllers. In my example I would just have to write the following:

class Authentication(users: Users, val messagesApi: MessagesApi) extends Controller with MessagesSupport {
  
}

This would work for runtime DI users as well (they just need to make their class injectable).

We could also provide a way to get an easy update solution for users that are still using the static API by defining an implicit conversion that also takes an implicit Application as parameter:

implicit def request2Messages(implicit rh: RequestHeader, app: Application): Messages =
  app.injector.instanceOf[MessagesApi].preferred(rh)

I’m not sure whether the Controller trait should by default have these conversions or if they should explicitly be mixed in by users.

 — This point is maybe related to the previous one, it may happen that one wants to reuse a component of Play without having to rely on the whole ApplicationLoader machinery. For instance, to reuse the evolutions component in my tests I can write a trait defining how to wire the components of my service and then use it to create my service in my tests. It turns out that in that case I don’t need an application (nor a router), I just need an Environment or a Configuration. That’s why I created a WithContext specs2 scope that creates a Context (which contains an environment and a configuration) and that supports the definition of custom configuration settings, unlike WithApplicationLoader.

Here's an example of what I've done to implement testing using evolutions/database without instantiating a whole application:


At the bottom of that spec is number of helpers, these I've already started generalising and pulling into Play.

​Interesting, thanks for the link.​

 — It was not possible to directly use WithBrowser because it takes a FakeApplication as parameter, though I was only able to produce an Application with my ApplicationLoader. I copy-pasted it and just changed its signature so that it takes an Application instead of a FakeApplication and it worked well. I hope we can apply the same change in Play.

Definitely.


 — I had troubles using the injected router because by default routers are generated in the empty package which you can not refer to unless you are in the empty package too. My workaround was to make my routers always use subpackages.

_root_ doesn't work?

​No, the empty package can not be accessed using _root_. See http://stackoverflow.com/a/9822212/561721

​Julien​

James Roper

unread,
Jan 5, 2015, 5:53:54 PM1/5/15
to Julien Richard-Foy, Adam Warski, Adam Warski, play-fram...@googlegroups.com
On Mon, Jan 5, 2015 at 6:49 PM, Julien Richard-Foy <j...@zengularity.com> wrote:
Yeah, this is very hard to get away from until we've completely eradicated the global state - the current solution we have for this is to provide a simple injector that provides the compile time injected components that are currently needed - it seems like there may be a few extra components that we need to make available via this mechanism.

​I’m not sure to see what you mean by this “inject that provides compile time injected components”.​ Can you point me to the code?

It's called a SimpleInjector:


and it's used by BuiltInComponents here:


So you can see, the crypto API (accessed through global state by the session signing stuff), http configuration (accessed in many places through global state) and the routes are all made available in that mini injector.  We can add more to this.  Obviously this isn't intended as a long term solution, it's just a temporary solution for those aspects of global state that we can't/don't want to address yet in Play 2.4.  We could also make them fields on Application, but I think we want to keep Application as small as possible.
 

     — The “request2Lang” member of Controller does the same ;
     — The “route” member of the test helpers delegates to the application’s “global” member to retrieve the handler for a given request, and this “global” member is itself initialized using the runtime dependency injector. I think the first problem could be solved by using the application’s “requestHandler” member instead of “global”, like I did here. The second problem (the initialization of the “global” member of Application) seems harder to solve.

Yes, the fix for the first problem is quite straight forward.


 — It was not straightforward to use the i18n module. First, I had to define an implicit conversion from RequestHeader to Messages in my controllers, and then at usage site I had to write this inconvenient syntax. I think that a solution to this problem could be to make the Messages object take an implicit Messages parameter instead of Lang (so we could use the same syntax as in 2.3 to get i18n, provided we have such an implicit conversion from RequestHeader to Messages).

This is good to know, we'll have to come up with a way to generically solve this.

We could provide the following trait:

trait MessagesSupport {

  def messagesApi: MessagesApi

  implicit def request2Messages(implicit rh: RequestHeader): Messages = messagesApi.preferred(rh)

}​

So that users just have to mix it in their controllers. In my example I would just have to write the following:

class Authentication(users: Users, val messagesApi: MessagesApi) extends Controller with MessagesSupport {
  
}

This would work for runtime DI users as well (they just need to make their class injectable).

We could also provide a way to get an easy update solution for users that are still using the static API by defining an implicit conversion that also takes an implicit Application as parameter:

implicit def request2Messages(implicit rh: RequestHeader, app: Application): Messages =
  app.injector.instanceOf[MessagesApi].preferred(rh)

I’m not sure whether the Controller trait should by default have these conversions or if they should explicitly be mixed in by users.

I like the MessagesSupport trait, I think we should go with that.
 
 — This point is maybe related to the previous one, it may happen that one wants to reuse a component of Play without having to rely on the whole ApplicationLoader machinery. For instance, to reuse the evolutions component in my tests I can write a trait defining how to wire the components of my service and then use it to create my service in my tests. It turns out that in that case I don’t need an application (nor a router), I just need an Environment or a Configuration. That’s why I created a WithContext specs2 scope that creates a Context (which contains an environment and a configuration) and that supports the definition of custom configuration settings, unlike WithApplicationLoader.

Here's an example of what I've done to implement testing using evolutions/database without instantiating a whole application:


At the bottom of that spec is number of helpers, these I've already started generalising and pulling into Play.

​Interesting, thanks for the link.​

 — It was not possible to directly use WithBrowser because it takes a FakeApplication as parameter, though I was only able to produce an Application with my ApplicationLoader. I copy-pasted it and just changed its signature so that it takes an Application instead of a FakeApplication and it worked well. I hope we can apply the same change in Play.

Definitely.


 — I had troubles using the injected router because by default routers are generated in the empty package which you can not refer to unless you are in the empty package too. My workaround was to make my routers always use subpackages.

_root_ doesn't work?

​No, the empty package can not be accessed using _root_. See http://stackoverflow.com/a/9822212/561721

Ok.  Sounds like we should change the default router to be in a package then.  Any idea on what package?  controllers might be a good package, but I wonder if that would cause any namespacing conflicts.  Maybe routes.Routes?  main.Routes?
 

​Julien​

--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Julien Richard-Foy

unread,
Jan 6, 2015, 1:14:05 PM1/6/15
to James Roper, Adam Warski, Adam Warski, play-fram...@googlegroups.com
 — It was not straightforward to use the i18n module. First, I had to define an implicit conversion from RequestHeader to Messages in my controllers, and then at usage site I had to write this inconvenient syntax. I think that a solution to this problem could be to make the Messages object take an implicit Messages parameter instead of Lang (so we could use the same syntax as in 2.3 to get i18n, provided we have such an implicit conversion from RequestHeader to Messages).

This is good to know, we'll have to come up with a way to generically solve this.

We could provide the following trait:

trait MessagesSupport {

  def messagesApi: MessagesApi

  implicit def request2Messages(implicit rh: RequestHeader): Messages = messagesApi.preferred(rh)

}​

So that users just have to mix it in their controllers. In my example I would just have to write the following:

class Authentication(users: Users, val messagesApi: MessagesApi) extends Controller with MessagesSupport {
  
}

This would work for runtime DI users as well (they just need to make their class injectable).

We could also provide a way to get an easy update solution for users that are still using the static API by defining an implicit conversion that also takes an implicit Application as parameter:

implicit def request2Messages(implicit rh: RequestHeader, app: Application): Messages =
  app.injector.instanceOf[MessagesApi].preferred(rh)

I’m not sure whether the Controller trait should by default have these conversions or if they should explicitly be mixed in by users.

I like the MessagesSupport trait, I think we should go with that.

​It solves only half of the problem: once you have an implicit Messages value you can not use it straightforwardly with the i18n API.​ Maybe we can just add the following member to the MessagesSupport trait:

    object Messages {
      def apply(key: String)(implicit messages: Messages): String = …
      // …
    }

 — I had troubles using the injected router because by default routers are generated in the empty package which you can not refer to unless you are in the empty package too. My workaround was to make my routers always use subpackages.

_root_ doesn't work?

​No, the empty package can not be accessed using _root_. See http://stackoverflow.com/a/9822212/561721

Ok.  Sounds like we should change the default router to be in a package then.  Any idea on what package?  controllers might be a good package, but I wonder if that would cause any namespacing conflicts.  Maybe routes.Routes?  main.Routes?

​What about “router”?​

Julien Richard-Foy

unread,
Jan 21, 2015, 3:18:11 AM1/21/15
to play-fram...@googlegroups.com, ja...@typesafe.com, ad...@warski.org, ada...@gmail.com, j...@zengularity.com
Hi,

Here is some more feedback. I upgraded play-jsmessages to Play 2.4.0 (BTW is there a way to point to the snapshots in my build?). The Scala sample wires everything at compile-time.

The README gives you an idea of the new developer experience with Play 2.4.0. For my tests, I didn’t use specs2’s Around because they do not compose well. Instead I wrote a higher-order function that sets up a context and apply a function that is passed to it. I’m quite happy with it. I didn’t use an ApplicationLoader in my tests because you can not get anything else than a Application from such a type, though I wanted to also retrieve, for instance, the WSClient for some of my tests. So I ended up with this pattern: I define a trait that extends BuiltInComponents and provides the components of my application. Then I use it in my ApplicationLoader as well as in my tests. In the latter case, I even mix in another components trait. I think Play should provide a way to get an ApplicationLoader.Context without too much boilerplate.

James Roper

unread,
Jan 21, 2015, 5:35:00 PM1/21/15
to Julien Richard-Foy, play-fram...@googlegroups.com, Adam Warski, Adam Warski, Julien Richard-Foy
Hey Julien,

Thanks, this is great.

On Wed, Jan 21, 2015 at 7:18 PM, Julien Richard-Foy <jul...@richard-foy.fr> wrote:
Hi,

Here is some more feedback. I upgraded play-jsmessages to Play 2.4.0 (BTW is there a way to point to the snapshots in my build?). The Scala sample wires everything at compile-time.

The README gives you an idea of the new developer experience with Play 2.4.0. For my tests, I didn’t use specs2’s Around because they do not compose well. Instead I wrote a higher-order function that sets up a context and apply a function that is passed to it. I’m quite happy with it.

I agree with this approach as a best practice going forward.  The reason I originally introduce the around scope is that it meant an implicit application could automatically be provided. But now that we're not passing implicit applications everywhere, this no longer makes sense.
 
I didn’t use an ApplicationLoader in my tests because you can not get anything else than a Application from such a type, though I wanted to also retrieve, for instance, the WSClient for some of my tests. So I ended up with this pattern: I define a trait that extends BuiltInComponents and provides the components of my application. Then I use it in my ApplicationLoader as well as in my tests. In the latter case, I even mix in another components trait.

Yes, this is the approach I was thinking of too.
 
I think Play should provide a way to get an ApplicationLoader.Context without too much boilerplate.

Currently you can do this:

ApplicationLoader.createContext(Environment.simple())

Perhaps we could provide a default parameter for the environment too?
Reply all
Reply to author
Forward
0 new messages