Guice, Java 8 and cyclic dependencies

430 views
Skip to first unread message

James Roper

unread,
Feb 5, 2015, 12:37:44 AM2/5/15
to play-fram...@googlegroups.com
Hi all,

You may have seen this issue with Play 2.4 and Java 8:


A few people have run into the problem, but from what I've seen, it has a very specific set of requirements in order to trigger it:

* You must be using a provider that contains a lambda in it
* The provider must not be able to resolve dependencies, either due to missing dependency or circular dependency
* I think the provider has to provide a concrete class, not an interface - for me, the problem wasn't triggered when the provider was providing an interface.

A few things about the bug:

* The bug is in Guice's error handling code, it occurs when Guice tries to look into the method implementation, this triggers a but in ASM that can't handle the lambda.  It does not affect a working application, it just masks the true cause of the error.
* The bug is only triggered once per classloader.  On the second time, it seems Guice caches the fact that there was an error, and doesn't try again to look into the method, so you get a meaningful exception.  So, when you get this in dev mode, simply hit refresh again, and the problem goes away on the second attempt to instantiate the injector.

The issue is fixed in Guice 4, but that's still in beta, and there's been very little activity on it, so I'm not sure that there will be a release before Play 2.4 is released, and I really don't want to be depending on a beta release of Guice - not because I'm worried about stability, but because I'm worried about API changes.

Now there is a very simple work around, that is, simply disable guice's use of ASM.  They actually have a no_aop classified artifact with ASM disabled.  So I'm wondering, should we depend on the no_aop one in Play by default?  The disadvantage of doing so is that Guice won't be able to resolve circular dependencies by extending concrete classes - but personally, I think that's a good thing, I'd rather my code completely fail if there's a circular dependency, and resolve it using Providers.

So, we've got an issue that has impacted a few users, but doesn't seem to be a major issue, and has simple work arounds (eg, hit refresh twice in dev mode).  We've got a solution that means turning off functionality that is probably best turned off anyway.  Should we switch to the no_aop version by default?  Users can always switch back manually in their build if they want.

Cheers,

James

--
James Roper
Software Engineer

Typesafe – Build reactive apps!
Twitter: @jroper

Rich Dougherty

unread,
Feb 5, 2015, 12:56:22 AM2/5/15
to James Roper, play-fram...@googlegroups.com
Thanks for the writeup. To me it sounds like it would be OK to disable Guice's ASM support—and users who really want it could turn it on through sbt's usual dependency support.

Rich

--
Rich Dougherty
Engineer, Typesafe, Inc

Jean Helou

unread,
Feb 5, 2015, 2:56:55 AM2/5/15
to Rich Dougherty, James Roper, play-fram...@googlegroups.com

+1 and having circular deps is bad anyways might as well fail early


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

Ben McCann

unread,
Feb 5, 2015, 8:03:50 PM2/5/15
to Jean Helou, Rich Dougherty, James Roper, play-fram...@googlegroups.com
I just swapped our app to the no_aop version to see if we'd run into any trouble. It worked just fine for us

-Ben

Peter Vlugter

unread,
Feb 8, 2015, 4:12:20 PM2/8/15
to play-framework-dev
I agree, switching to no_aop by default seems like a good idea.

Peter

AliSoleimani

unread,
Apr 23, 2015, 9:31:03 AM4/23/15
to play-fram...@googlegroups.com


On Thursday, February 5, 2015 at 9:07:44 AM UTC+3:30, james...@typesafe.com wrote:
So, we've got an issue that has impacted a few users, but doesn't seem to be a major issue, and has simple work arounds (eg, hit refresh twice in dev mode).  We've got a solution that means turning off functionality that is probably best turned off anyway.  Should we switch to the no_aop version by default?  Users can always switch back manually in their build if they want.


How is it possible to use default guice,
libraryDependencies ++= Seq("com.google.inject.extensions" % "guice-multibindings" % "3.0")
does not work

Best Regards

Rich Dougherty

unread,
Apr 23, 2015, 12:21:54 PM4/23/15
to AliSoleimani, play-fram...@googlegroups.com

Can you explain more about what you're doing and what problem you see?

— Rich

--

James Roper

unread,
Apr 23, 2015, 7:15:09 PM4/23/15
to Rich Dougherty, AliSoleimani, play-fram...@googlegroups.com
Hi Ali,

I noticed this recently - it's a problem with using classifiers, not sure if it's ivy specific or if it also happens in maven.  We depend on guice no_aop, and we exclude cglib and aop_alliance from it's transitive dependencies, because classifiers don't change dependencies, and they aren't needed:

"com.google.inject" % "guice" % "3.0" classifier "no_aop"
  exclude("org.sonatype.sisu.inject", "cglib") exclude("aopalliance", "aopalliance")

The problem comes, when you depend on something that depends on unclassified guice, this causes the unclassified guice to override and be used in preference to the no_aop guice that Play provides, however the exclusions still apply, so you end up with NoClassDefFoundError's because it's using a version of guice that requires the dependencies we've excluded.  The work around is simple, when you depend on something that transitively depends on guice, exclude guice from it, eg, this is how I added a dependency to assistedinject:

"com.google.inject.extensions" % "guice-assistedinject" % "3.0"
  exclude("com.google.inject", "guice")

Anyway, we might be able to solve this by simply upgrading to Guice 4, it looks like Google might be cutting a release soon:


Cheers,

James

AliSoleimani

unread,
Apr 25, 2015, 11:33:11 AM4/25/15
to play-fram...@googlegroups.com, ri...@rd.gen.nz, alis...@gmail.com
Hi James

Thank You
I couldn't find any way to disable classified jar, when creating dist package both classified and unclassified exists in zip file

James Roper

unread,
Apr 26, 2015, 7:50:19 PM4/26/15
to AliSoleimani, play-fram...@googlegroups.com, Rich Dougherty
Hi Ali,

Checkout the ivy report, that will show you which dependencies are pulling guice in.  Any that are not Play will potentially override the classifier.  You should exclude it from all dependencies other than Play using the exclude call shown above.  For information on how to checkout the ivy report see:


Cheers,

James

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

AliSoleimani

unread,
Apr 27, 2015, 9:49:02 AM4/27/15
to play-fram...@googlegroups.com, alis...@gmail.com, ri...@rd.gen.nz
Hi James
your hint was helpful and solved my problem

Thank You

libraryDependencies ++= Seq(
  "com.google.inject" % "guice" % "3.0",
  "com.google.inject.extensions" % "guice-assistedinject" % "3.0" exclude("com.google.inject", "guice"),
  "com.typesafe.play" %% "play" % "2.4.0-RC1" exclude("com.google.inject", "guice"),
  "com.typesafe.play" %% "play-netty-server" % "2.4.0-RC1" exclude("com.google.inject", "guice"),
  "com.typesafe.play" %% "play-server" % "2.4.0-RC1" exclude("com.google.inject", "guice"),
  jdbc exclude("com.google.inject", "guice"),
  cache exclude("com.google.inject", "guice"),
  ws exclude("com.google.inject", "guice")
)

Ben McCann

unread,
Apr 28, 2015, 7:02:35 PM4/28/15
to AliSoleimani, play-fram...@googlegroups.com, Rich Dougherty

--
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.
Reply all
Reply to author
Forward
0 new messages