You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
guava 14.0.1 cannot be deployed in a JEE7 Container #1433
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?
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.
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.
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().
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..
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.
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.. ?
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)…
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.
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
Activity
gissuebot commentedon Nov 1, 2014
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-DevCC: cgruber@google.com
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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..
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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.. ?
gissuebot commentedon Nov 1, 2014
Original comment posted by AaronJWhiteside on 2013-05-29 at 02:26 AM
*or at least until you explicitly configure it...?
gissuebot commentedon Nov 1, 2014
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
gissuebot commentedon Nov 1, 2014
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
gissuebot commentedon Nov 1, 2014
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..
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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.
gissuebot commentedon Nov 1, 2014
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
gissuebot commentedon Nov 1, 2014
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.
36 remaining items
gissuebot commentedon Nov 1, 2014
Original comment posted by pjpires on 2014-02-14 at 07:38 AM
Glassfish bundles its own Guava.
gissuebot commentedon Nov 1, 2014
Original comment posted by hsaqallah on 2014-02-14 at 07:39 AM
Any idea how to remove it?
Thanks.
gissuebot commentedon Nov 1, 2014
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?
gissuebot commentedon Nov 1, 2014
Original comment posted by hsaqallah on 2014-02-14 at 07:48 AM
Done: #1668
bcmedeiros commentedon Aug 6, 2015
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.
lukesandberg commentedon Aug 18, 2015
@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