What are the Dagger 2 compatibility prospects for future Play releases?

260 views
Skip to first unread message

joe.ha...@inavero.com

unread,
May 8, 2017, 2:43:33 PM5/8/17
to Play Framework, Jarett Creason
Hi,

I am actively working on moving our Play 2.5 apps to using Dagger 2 for DI. I figured it would be good to get a read on the future of Dagger 2 with Play...

 Are there any plans to switch from Guice? 

If not, are there any plans to maintain relative compatibility for upgrades - i.e. can I count on a hypothetical 2.6 -> 2.7 upgrade not massively breaking my DI implementation (assuming I stick closely to the example)? 

What does the landscape look like for Play 3? 

Are there any plans to get an example of how to test with a fake application using Dagger 2? (I'll contribute if I solve this one.) 


Thanks for all your time and efforts. 

-Joe 

Will Sargent

unread,
May 8, 2017, 4:09:13 PM5/8/17
to play-fr...@googlegroups.com, Jarett Creason
There's no plans to switch away from Guice, but Play 2.6 does not include Guice in the root library.  See https://app.updateimpact.com/treeof/com.typesafe.play/play_2.12/2.6.0-M5 for the core library dependencies.

Refactorings in DI implementation has been limited to removing global state (i.e. Play.current) access under the hood, but in your case there were no compile time DI components for Play 2.5.x, so it depends on if you're using the https://github.com/playframework/play-java-dagger2-example example -- we added a whole bunch of components in 2.6.x to make building easier.  So you want to compare against the https://github.com/playframework/play-java-dagger2-example/tree/2.6.x branch and possibly backport some code from https://github.com/playframework/playframework/tree/master/framework/src/play/src/main/java/play/components

The roadmap for Play 3.0 is here:


Testing with a fake application is all about being able to pass it to running():


so if you can create an Application you're already 90% of the way there -- see


So start from the application loader:


and that should be it.  

Will.






--
Will Sargent
Engineer, Lightbend, Inc.


--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/4f82d360-6709-4c9c-bde5-afcc5970353e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

joe.ha...@inavero.com

unread,
May 8, 2017, 5:39:01 PM5/8/17
to Play Framework, jarett....@inavero.com
Will,

Thanks for the quick response and the info. 

Funny... I got a simple Application-dependent test working while waiting for the reply and it ended up being basically what you prescribed. Glad to know I was doing something sensible! Should I go ahead and PR that test for the Dagger example app? If so, what branch? 

As for the new 2.6 components, were you referring to 'backporting' within our app (e.g. copy them to a local package), or should I create a a backport PR for Play 2.5?

Thanks! 

-Joe  
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Greg Methvin

unread,
May 8, 2017, 9:38:34 PM5/8/17
to play-framework, jarett....@inavero.com
Of course, PRs are welcome. Ideally we'd want the test on both branches, though in 2.6.x it's more important since we're actually saying this is a supported feature. But we can back- or forward-port as needed.

You could "backport" the Java components into your app by copying the code and modifying it to match the 2.5 APIs. It should be relatively straightforward. If it's easy enough you can submit a PR to the 2.5 branch, but support for the Java components API on 2.5 isn't really a goal for us.

The idea is that 2.7 and future 2.x releases will be more minor changes, and we will use 3.0 to create new, possibly breaking APIs. Effectively we're changing the versioning scheme from epoch.major.minor to major.minor.patch, just as Akka did recently.

For the Java API we still need runtime reflection for some things, like the Action annotations and body parsers, so we can't do perfect reflection-free compile-time DI, but you basically just need an "injector" that has instances of those things for it to work (https://github.com/playframework/play-java-dagger2-example/blob/461249/app/dagger/MyComponentsFromContext.java#L46). In the future we'd like to implement a new action API (based on EssentialAction) that uses function composition instead of annotations, but would indefinitely support the current Java API on 2.x

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/70c32ed2-1ebe-4033-915a-9958d5ef5f88%40googlegroups.com.

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



--
Greg Methvin
Tech Lead - Play Framework

joe.ha...@inavero.com

unread,
May 9, 2017, 3:47:50 PM5/9/17
to Play Framework, jarett....@inavero.com

Greg, 

Thanks for the info! I did make an attempt to 'backport' some of the 2.6 components structure but the dependencies on 2.6 interfaces (new or modified) ran deeper than was justified for our immediate needs - definitely nontrivial. 

I'll try to get a PR for tests in by end of the week. 

Thanks again. 

-Joe 

joe.ha...@inavero.com

unread,
May 9, 2017, 6:40:51 PM5/9/17
to Play Framework, jarett....@inavero.com
I'm trying to get Ebean working and I have a few more questions.... 

My issue is that it appears the Ebean servers aren't getting initialized. I'm getting this as soon as Ebean.getDefaultServer() is called:

io.ebean.Ebean - Error trying to create the default EbeanServer

java.lang.RuntimeException: DataSource user is null?

... Is this correct? 

It appears that the PlayEbean plugin includes a play.inject.Module, EbeanModule: https://github.com/playframework/play-ebean/blob/master/play-ebean/src/main/java/play/db/ebean/EbeanModule.java
... How do these 'modules' get initialized? (I know they get specified in configs but what actually instantiates them?) 
... What is the relationship (if any) between play.api.inject.Injector and play.api.inject.Module ? 

Is there any way to get debug information/logs on modules being instantiated? 

Is there a simple way to get Ebean configured/setup with compile-time DI? 

Thanks. 

-Joe 

On Monday, May 8, 2017 at 6:38:34 PM UTC-7, Greg Methvin wrote:

joe.ha...@inavero.com

unread,
May 10, 2017, 1:08:50 AM5/10/17
to Play Framework, jarett....@inavero.com
OK, scratch my prior questions... after doing some digging here's what I've got - please correct me where wrong:
  • The play.api.inject package include the Module and Injector interfaces that make up part of Play's internal DI mechanism (framework)
    • These are in place to provide the 'DI framework agnostic' mechanism that 3rd party modules can be written against 
    • Modules are discovered by way of Modules.locate()
    • Modules implements the bindings() method that provides informs the Play DI system which implementations should be used for injected interface dependencies 
    • Implementations of the Injector interface use the bindings to provide instantiated implementations upon request (explicitly or by other modules) 
  • The GuiceApplicationBuilder (and other supporting classes) handle discovery of Play modules, collection of bindings, and creation of an Injector implementation 
    • Play modules can have dependencies specified through Guice annotations/modules?
  • Play 2.5 Compile-Time DI
    • No GuiceApplicationBuilder - everything written from scratch 
    • ... therefore... No built in module loading (i.e. Ebean and Deadbolt modules don't start up) 
    • Play Injector implementation must be manually setup; i.e. Dagger 2 injection won't be automatically used to provide dependencies for objects instantiated with the Play DI mechanism
I general, what I'm gathering is that:
  • In order to avoid having 3rd party modules be written for every supported DI framework (e.g. Guice, Dagger), Play his it's own internal DI system that is partially aware of Guice but not any other Java DI framework. 
  • Unless I'm missing something, module loading and internal DI runtime setup doesn't exist outside GuiceApplicationBuilder for Java and Play 2.5. 
  • This effectively results in Java developers using Play having to learn two DI frameworks - Play and Guice (or some alternative). 
So my big questions are: what do I have wrong? ... and what has changed for 2.6? (The components seem to streamline the compile-time DI setup, but I still can't find how modules are loaded and hooked up to the Injector implementation.) 

Thanks again for your time. 

-Joe 

Will Sargent

unread,
May 20, 2017, 2:02:35 PM5/20/17
to play-fr...@googlegroups.com, Jarett Creason
play.api.inject is Play's internal DI mechanism, yes.  Play modules should be written against it, application / user level modules don't have to be.

The GuiceApplicationBuilder is useful for testing as an out of the box strategy, but Play can and does create application through compile time DI for testing purposes internally.  Play modules should be DI-framework agnostic, so having a guice dependency isn't cool.  So for the sake of example, take the JSR 107 / JCache binding -- Play can use play.api.inject.bind and javax.inject.Provider to do 

bind[CacheManager].toProvider[DefaultCacheManagerProvider]

but adding cache-annotations-ri-guice isn't okay there.  See https://github.com/playframework/playframework/pull/7371 for details.

So Ebean provides a module for runtime DI:


and there is also an SBT plugin that gets pulled in when you specify "addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "4.0.0-M3")"


and as part of the SBT autoplugin, it adds play-enhancer and then runs through models:


So that the classes are available.

The problem here is that there's an EBeansModule for runtime DI, but there is no EbeanComponents for compile time DI.  For example, compare with the Slick module, which has both SlickModule and SlickComponents:


What we did in 2.6 was add a whole bunch of Java components:


So to load the module, you need to create that trait and then extend play.api.BuiltInComponentsFromContext with it.


Does that help?

--
Will Sargent
Engineer, Lightbend, Inc.


To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/139c6f12-1a42-4c7b-abd7-438df103b13d%40googlegroups.com.

joe.ha...@inavero.com

unread,
May 23, 2017, 3:14:55 PM5/23/17
to Play Framework, jarett....@inavero.com
Will,

Thanks for the breakdown. It will be useful for anyone else looking into this and for us if we dive back into this. For now, we've had to abandon the effort due to the amount of new code that would have to be written just to get all the 3rd party modules working again, not just for instantiation, but getting configuration working as well (in both normal and test environments).

-Joe 

Will Sargent

unread,
May 23, 2017, 3:45:39 PM5/23/17
to play-fr...@googlegroups.com, Jarett Creason
No problem.  I've added ebean components in this PR:


--
Will Sargent
Engineer, Lightbend, Inc.


To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/20258817-d601-4594-9825-6c055dcdfdac%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages