Skip to content

guava 14.0.1 cannot be deployed in a JEE7 Container #1433

Closed

Description

@gissuebot

Original issue created by AaronJWhiteside on 2013-05-28 at 09:34 PM


In JEE7 CDI (CDI 2.0) is enabled by default (without a beans.xml needing to be present), with no standardized way of disable it.

com.google.common.util.concurrent.ServiceManager is annotated with @Singleton and has a constructor...

  @Inject ServiceManager(Set<Service> services) {
    this((Iterable<Service>) services);
  }

So any war or ear that contains a guava 14.0.1 jar suffers from CDI seeing this and trying to create the bean but failing and thus failing the entire war from loading.

This error is from Glassfish 4.0

[2013-05-23T15:08:35.664-0700] [glassfish 4.0] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=34 _ThreadName=admin-listener(2)] [timeMillis: 1369346915664] [levelValue: 1000] [[
  Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)]

The same WAR also fails to deploy on Firefly 8.0 with a similar error.

Can guava be modified to not use the @Singleton and @Inject annotations?

Activity

  1. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by kurt.kluever on 2013-05-28 at 09:36 PM


    (No comment entered for this change.)


    Owner: lukes@google.com
    Labels: Type-Dev
    CC: cgruber@google.com

  2. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by cgruber@google.com on 2013-05-28 at 09:56 PM


    Oi. The problem here is that (as I understood it) @Inject was added to make it an injectable class in both Guice and Dagger, to avoid having to manually create them in a module. In both systems, this would not be created early (with some notable exceptions). But certainly not just because it is in the classpath and annotated.

    I don't know that much about CDI except from very ancient memory, but it seems to me that CDI is interpreting JSR-330 in a particular way that is not consistent with the intentions of the reference implementation that spawned it - guice. It's making the (unwarranted) assumption that if it's annotated and on the classpath you want to create it up-front.

    That is unfortunate, but I'm not sure we should un-annotate ServiceManager to cater to that assumption. Doing so requires additional boilerplate modules for Dagger or Guice users in preference to the CDI users.

    A simple workaround is to simply configure an empty Set<Service>. I don't know if there is a way to configure glassfish or others to exclude classes/packages from this assumption. It's a bit of a mind-blowing assumption to make. :/

    Another possibility is to proguard the ServiceManager away entirely.

    Argh.

  3. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by cgruber@google.com on 2013-05-28 at 10:10 PM


    Another workaround, have a relevant class implement

    @Produces Set<Service> dummyServices() {
        throw new AssertionError();
    }

    This should pass validation (structurally satisfies the dependency), but if it's ever actually called, it will throw, so should ensure that you're not actually creating any ServiceManagers in production. If you are, and this approach doesn't work, just return an empty Set<Service> per above.

  4. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-28 at 11:49 PM


    CDI 1.1 (not 2.0 my mistake) will scan all classes in the war and try and instantiate them at deployment time. So the dummyServices() method will be invoked and throw the AssertionError().

    JSR-346 governs the behavior of CDI 1.1: http://www.jcp.org/en/jsr/detail?id=346

    Perhaps you have more clout than a lot of other poeple/at least myself and could pursue someone on the expert group for JSR-346 with this matter?

    I understand your frustration but if you include classes with any JSR-330 annotations they will be treated differently in JEE7 containers, currently Firefly 8 and Glassfish4, soon to follow Tomcat.. and various others..

    On the other note what does it matter if it requires a little more boilerplate code to make it compatible with the next generation of application server containers? Right now the preference is with Guide and Dagger users to the exclusion of users of JEE7 containers (not specifically CDI - I don't use it myself). Shouldn't a library such as guava try to be compatible with the majority of technology it will be used in (hint hint JEE)?

    BTW I do love Guice, and we have a few products here that use it extensively. But they are still deployed as WARs in JEE containers..

  5. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by lukes@google.com on 2013-05-29 at 01:59 AM


    What would be the 'little more boilerplate' that we could add to support CDI 1.1?

    another solution would be to add a beans.xml that simply excludes this class from auto discovery, though as you have mentioned this will still be a stumbling block for anyone trying to use the class in a JEE 7 container.

  6. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-29 at 02:21 AM


    A pre-made Guice Module? But I expect that will put a dependency directly on Guice which you probably don't want. I was thinking more alone the lines of a wiki page for users explaining how to bind what to where... shrug?

    beans.xml does not officially support a method to exclude classes from auto discovery. Although WELD does support this via an extension it does not seem to work in Glassfish, only JBoss.. and is non-portable between CDI implementations, not that there are many.

  7. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-29 at 02:25 AM


    Not sure if this applies, but you could annotate specific classes with @Alternative, this would make CDI treat the bean as "disabled" by default.

    http://relation.to/Bloggers/WhyIsBeansxmlRequiredInCDI

    But I suspect you'll then have a dependency on:

    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>1.1</version>
    </dependency>

    But then you could always mark that dependency as optional, so you would need it for compile time but no one else will pick it up as a transitive dependency. And would still behave nicely in CDI.. or at least make it explicitly configure it.. ?

  8. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-29 at 02:26 AM


    *or at least until you explicitly configure it...?

  9. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by lukes@google.com on 2013-05-29 at 03:02 PM


    wouldn't this do it

    <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee">
    <scan>
    <exclude name="com.google.common.util.concurrent.ServiceManager" />
    </scan>
    </beans>

    this is based on reading section 12.4 of the CDI 1.1 spec

  10. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by gak@google.com on 2013-05-29 at 04:09 PM


    So, I poked around in the spec a bit and there's a interesting part of the spec for managed beans: "It is not annotated @Vetoed or in a package annotated @Vetoed." If JEE7 is really going to be a concern, it might not be a bad idea to toss that annotation on all of our packages because we'll never want Guava classes to be managed beans. Since annotations aren't runtime deps, it'll make no difference for most people.

    That said, we lukes@ has created a ServiceModule for Guice that is often easier to use and has more configuration options than the @Inject constructor, so it might be worth just removing that annotation and open-sourcing the module (someplace else)…


    CC: gak@google.com

  11. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-29 at 04:24 PM


    I tried that it doesn't work.

    I think you're right this isn't an issue with Guava, looks like an issue with CDI. Or the broken implementations that are currently bundled with the non-production ready releases of Glassfish 4 and Firefly 8..

  12. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by AaronJWhiteside on 2013-05-29 at 04:46 PM


    Gak,

    If you would be willing to do that, that would be wonderful. And would help until the various JEE7 implementations have sorted their bugs out..

    Would it make sense for guava to have a guava-guice artifact/module (maven) too, that people could include for Guice support? Having it part of the Guava project would ensure it is maintained in line with the other changes to Guava.

  13. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by gak@google.com on 2013-05-29 at 05:21 PM


    Mind pulling down Guava, adding the annotation and seeing whether or not it works? It'd be an interesting data point.

  14. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by reuben.pasquini512 on 2013-06-14 at 05:29 PM


    I filed this ticket with the JIRA instance linked to by the CDI spec:
        https://issues.jboss.org/browse/CDI-377

  15. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by paul.brickell on 2013-06-23 at 03:54 PM


    OK I'm using a guava cache in my JEE web application and am currently upgrading my deployments to GF 4.0.

    I'm hosed by this one. Is there a workaround I can implement in my module that can get me over the hump?

    TIA.

  16. 36 remaining items

  17. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by pjpires on 2014-02-14 at 07:38 AM


    Glassfish bundles its own Guava.

  18. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by hsaqallah on 2014-02-14 at 07:39 AM


    Any idea how to remove it?
    Thanks.

  19. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by lukes@google.com on 2014-02-14 at 07:40 AM


    This appears to be a different issue. Can you open a new bug?

  20. gissuebot commented on Nov 1, 2014

    @gissuebot
    Author

    Original comment posted by hsaqallah on 2014-02-14 at 07:48 AM


    Done: #1668

  21. modified the milestone: 15.0 on Nov 1, 2014
  22. bcmedeiros commented on Aug 6, 2015

    @bcmedeiros

    Why not remove just the @singleton annotation, which causes the problem, and leaves the @Inject? At least Guice users will have to only set the scope to this class if they need that.

  23. lukesandberg commented on Aug 18, 2015

    @lukesandberg
    Contributor

    @brunojcm That would probably have been more dangerous since then contains like Guice would create a new ServiceManager for each injection point and then some of them will fail because you can't construct a ServiceManager with started services.

    in any case the annotations were removed and adding custom bindings for ServiceManager et.al. in your container should be straightforward

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    ⌂ 换网址