-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
guava 14.0.1 cannot be deployed in a JEE7 Container #1433
Comments
Original comment posted by kurt.kluever on 2013-05-28 at 09:36 PM (No comment entered for this change.) Owner: lukes@google.com |
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. |
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() { 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. |
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.. |
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. |
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. |
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> 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.. ? |
Original comment posted by AaronJWhiteside on 2013-05-29 at 02:26 AM *or at least until you explicitly configure it...? |
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"> this is based on reading section 12.4 of the CDI 1.1 spec |
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 |
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.. |
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. |
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. |
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: |
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. |
Original comment posted by reuben.pasquini512 on 2013-06-23 at 06:08 PM I rolled back to guava 13.0.1 as a quick workaround ... |
Original comment posted by reuben.pasquini512 on 2013-06-27 at 10:15 PM It turns out that CDI 1.1 supports a new "bean-discovery-mode" attribute in META-INF/beans.xml that can be set to "all", "none", or "annotated", so adding a META-INF/beans.xml file to the jar with "none" discovery mode prevents CDI from scanning the jar. http://java.dzone.com/articles/java-ee-7-deployment I ran a test adding META-INF/beans.xml to guava's jar in a webapp on glassfish 4.0, and it worked fine:
Can you add an empty beans.xml CDI config file to the guava jar ? |
Original comment posted by reuben.pasquini512 on 2013-06-27 at 10:47 PM BTW - I pulled the test app in glassfish 3 just to verify that adding the beans.xml file to guava's jar didn't break things there, and it worked fine there too ... |
Original comment posted by mr.peter.somogyvari on 2013-07-01 at 10:36 AM I'm in the process of upgrading to GF4.0 too. Anybody has some -not so fishy workaroundish- suggestions if I have a lib which declares guava 14.0 as a dependency? |
Original comment posted by cgdecker@google.com on 2013-07-01 at 02:59 PM As a workaround, can you just do a variation of what comment #3 suggested? Have a relevant class implement: @Produces Set<Service> dummyServices() { You might get a warning logged, but I'd think it should work. |
Original comment posted by reuben.pasquini512 on 2013-07-01 at 03:31 PM Try overriding the dependency to use guava-13.1 in the I wound up wiring up my webapp build process to add a beans.xml file
where src/java just contains META-INF/beans.xml with Good luck! |
Original comment posted by cgdecker@google.com on 2013-07-01 at 10:00 PM It looks like the specific issue here may not be that ServiceManager has @Inject on a constructor, but that the class is annotated with a scope (@Singleton). See this section of the CDI 1.1 spec: http://docs.jboss.org/cdi/spec/1.1/cdi-spec.html#bean_defining_annotations Any scope annotation is a bean defining annotation, and any class with a bean defining annotation is treated as a bean. Section 12.1 (http://docs.jboss.org/cdi/spec/1.1/cdi-spec.html#bean_archive) goes on to define an "implicit bean archive" as one containing any class annotated with a bean definining annotation. So Guava is an implicit bean archive whether it likes it or not. On the other hand, another part of the spec (http://docs.jboss.org/cdi/spec/1.1/cdi-spec.html#what_classes_are_beans) states that anything with @Inject on a constructor that meets a variety of other requirements is a "managed bean", so I don't know. Doesn't much matter either way. One thing I can't tell from what I've read of the spec is whether a beans.xml file at the war level (in WEB-INF/ or WEB-INF/classes/META-INF/) can exclude packages from jars included in the war. It really seems like it should be able to, but from what AaronJWhiteside said in #11 it sounds like that doesn't work. Can anyone confirm? Or confirm if adding a method that @Produces an empty Set<Service> works? In any case, while this is clearly an issue with CDI, if there's no good workaround that doesn't involve modifying the Guava jar in some way, we'll ensure this isn't an issue in 15.0. Status: |
Original comment posted by cgdecker@google.com on 2013-07-11 at 02:58 PM I've added a beans.xml with bean-discovery-mode="none" to the guava jar's META-INF/ (de8f4e8 If someone having this issue could build the jar and verify that it fixes the issue for them, that would be great. Status: |
Original comment posted by reuben.pasquini512 on 2013-07-11 at 09:18 PM I just built and deployed the guava-15.0-SNAPSHOT.jar that now includes META-INF/beans.xml, and it works fine for me in glassfish 4.0. Thanks! |
Original comment posted by sb.leszek on 2013-09-01 at 10:27 AM I'm using Glassfish 4.0 and discovered that weld-osgi-bundle.jar contains Guava. So my application (using Guice also) is working without having it's own copy of Guava but I'm using a limited subset of Guava API. |
Original comment posted by cody.lerum on 2013-09-10 at 02:43 PM Unfortunately in CDI 1.0 the inclusion of a beans.xml in the guava archive triggers scanning of it for CDI thus (potentially) breaking applications using CDI 1.0 |
Original comment posted by sebastian.davids on 2013-09-12 at 08:59 AM GlassFish: cannot deploy war with google guava lib |
Original comment posted by k...@appendium.com on 2013-09-12 at 10:24 AM We are getting similar error with Guava 15 and JBoss 7 Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[parameter 1] of [constructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)] It works fine with Guava 14.0.1. Anyone faced the same issue? |
Original comment posted by s...@imsand.li on 2013-09-12 at 11:04 AM We also facing issues with guava 15.0 deploying an application to an embedded tomee 1.5.1 Here the stacktrace. Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Api type [java.util.Set] is not found with the qualifiers Removing beans.xml would solve the problem. |
Original comment posted by k...@appendium.com on 2013-09-12 at 11:27 AM Removing beans.xml from the guava-15.0.jar works. Is there however a solution that does not involve editing the jar file? Any help/pointers would be great. |
Original comment posted by xaerxess on 2013-10-04 at 07:51 AM @cgdecker: You've mentioned in comment 33 you'll release Guava 15.0.1 (or even 15.1) without beans.xml - is that still a plan? It would fix issue #1527 problem. |
Original comment posted by hazendaz on 2013-10-06 at 04:27 AM My two cents. I'm not convinced this beans.xml is doing what it advertises. Scanning still seems to occur. We have successfully used guava 14.0.1 for quite some time without issue running essentially java EE7 inside of tomcat 7.0.x as well as weblogic 10.3.6. We use weld 2.1.CR1 at the moment. I'll spare the details but we have nearly the entire EE7 spec running in those environments aside with exception of jars requiring java 7. In those cases, we are still back on EE6 (EL, ejb, servlet) - all reasons beyond my control and silly I know. When we try to upgrade to guava 15, we run into two issues. First, the issue noted here with WELD-001408. The second is with richfaces. The later of which is a show stopper and something richfaces team needs to resolve. However, provided they solve their issue, we still cannot upgrade so long as this beans.xml is inside of guava. However, I personally have no issue simply removing it to make it work and keeping a patched copy in our nexus repository for internal use. That matter is trivial at best. I prefer not to do so, so a better solution is much wanted. My guess is that our specific setup is somehow causing some regression here. So along with others, it does sound like removing it is better and/or simply releasing two copies to the repositories until this is properly resolved. |
Original comment posted by dhumeniuk on 2013-10-29 at 07:35 PM I'm using an OSGi web bundle which uses other OSGi services from other bundles. This means I need to use CDI in my web bundle and need my classes in the bundle (JAR file) to be scanned. Basically this means I can't use Guava as it doesn't work with CDI currently. Whether the bean.xml is in the JAR doesn't really matter as I'm including the Guava code in my bundle so I don't have an extra dependency on Guava in case some other bundle is using a different version. If the annotations are not really important for these classes, can they be removed? I can manually remove these classes in my case. However, I will not be able to access them in my web bundle (JAR) and seems a bit of a hack. That is the only work around that I can think of right now. |
Original comment posted by cgdecker@google.com on 2013-10-30 at 10:09 PM JSR-330 annotations have been removed for Guava 16.0, so hopefully there will be no further issues with CDI. Now we'll just have issues when code that was taking advantage of the annotations stops working. |
Original comment posted by xaerxess on 2013-10-30 at 10:50 PM So I hope Guava 16.0 will be out soon, because right now we're stuck on ancient (1,5 years old) version 13... |
Original comment posted by cgdecker on 2013-10-31 at 12:40 AM @xaerxess: How are you stuck? Have you tried guava-15.0-cdi1.0.jar (with no beans.xml)? |
Original comment posted by xaerxess on 2013-10-31 at 06:23 AM Correct me if I'm wrong, but if we use both Java EE 6 and 7 application servers, there's no way having project depending on Guava 14 or 15 deployed without POM juggling (i.e. change classifier and rebuild whole project), right? It's quite troubling because Guava should remain CDI agnostic and it will be true for version 16. |
Original comment posted by cgdecker@google.com on 2013-10-31 at 04:14 PM @xaerxess: Yes, that's probably correct (though using Maven profiles might help). You could also build Guava from source with the annotations removed.
So, both guava-14.0.1 and (strangely enough) guava-15.0-cdi1.0 are CDI agnostic. They only use JSR-330 annotations. To be clear: CDI itself is the problem here, because its specification prevents the use of libraries that annotate classes with certain JSR-330 annotations. We're removing the annotations in Guava 16.0 because we feel that A) it seems unlikely that CDI will fix its spec anytime soon, and B) the problems this causes for users in CDI environments (where there apparently isn't any good workaround) probably outweighs the benefits of the annotations to users who are taking advantage of them in other environments (because at least with other JSR-330 frameworks like Guice and Dagger, binding the ServiceManager yourself isn't hard). It's not because we believe it's wrong for Guava to use the annotations; quite the opposite. |
Original comment posted by xaerxess on 2013-10-31 at 06:16 PM @cgdecker: Thanks for detailed explanation, my wording was a bit unfortunate (regarding Guava and CDI). So to sum up, in perfect world (with better CDI specification and implementation) there would be no problem with JSR-330 annotated classes in Guava. |
Original comment posted by cgdecker@google.com on 2013-10-31 at 06:29 PM @xaerxess: Right. One of the big advantages (in my opinion) of a standard set of annotations for dependency injection like JSR-330 was that it would make it possible for libraries to make their classes easy to use with DI frameworks. It's really unfortunate that another Java standard simultaneously interprets those annotations in a way that makes that impossible. |
Original comment posted by antoine.sabotdurand on 2013-12-27 at 01:53 PM CDI 1.2 will address this problem. At least at implementation level : https://issues.jboss.org/browse/CDI-377 |
Original comment posted by hsaqallah on 2014-02-14 at 07:00 AM Guava 16 and 16.0.1 still have the same problem with glassfish 4.0. What am I missing? |
Original comment posted by lukes@google.com on 2014-02-14 at 07:22 AM What error are you getting? Both the @Inject and @Singleton annotations were removed from Is it possible you have more than one copy of guava on your class path? in a JEE7 Container am I missing? |
Original comment posted by hsaqallah on 2014-02-14 at 07:36 AM The error message is: java.lang.NoSuchMethodError: com.google.common.base.Splitter.splitToList(Ljava/lang/CharSequence;)Ljava/util/List; My mvn dependency:tree is showing exactly one guava 16.0 and I don't have google collections. This is the tree (minus our own packages): [INFO] - org.ocpsoft.prettytime:prettytime:jar:3.2.4.Final:compileThe same error is happening with guava 15.0.x and 16.0.1 |
Original comment posted by pjpires on 2014-02-14 at 07:38 AM Glassfish bundles its own Guava. |
Original comment posted by hsaqallah on 2014-02-14 at 07:39 AM Any idea how to remove it? |
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? |
Original comment posted by hsaqallah on 2014-02-14 at 07:48 AM Done: #1668 |
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. |
@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 |
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?
The text was updated successfully, but these errors were encountered: