I am struggling to understand the effective lifecycle of a @Dependent
scoped bean in both CDI 1.0 and CDI 1.1. My experiments so far have lead me to the following conclusions:
- A
@Dependent
scoped bean is not proxied. - No
@PreDestroy
method is invoked when a@Dependent
bean is destroyed. Provider.get()
always creates a new instance of a@Dependent
bean.- With JBoss 6/CDI 1.0, a
@Dependent
bean that is created by an@ApplicationScoped
bean'sProvider<>
field is "leaked", because it still "belongs" to theProvider
. - I have seen no evidence (yet!) of
@Dependent
beans being leaked by similarProvider
s when using WELD 2.1.2.Final/CDI 1.1. (Although this might be because these particular@Dependent
beans are created by@Produces
methods...!)
I see that CDI 1.1 has added a destroy()
method to Instance<>
, presumably to address the memory leak in CDI 1.0. But what about Provider<>
- does that still leak in CDI 1.1? (And if it does, then how are you supposed to use Provider.get()
?)
Basically, I have several @ApplicationScoped
beans / @Singleton
EJBs that I @Inject
Provider
fields into, and I am trying to use Provider.get()
as factories for both @Dependent
and @RequestScoped
"helper" beans. I definitely do not want these beans to "belong" to their Provider
fields, as I need the beans to be garbage collected afterwards:
public void updateStuff() {
Helper helper = helperProvider.get();
// use helper...
}
For my CDI 1.0 application, I was thinking of fixing the memory leak by "faking" my Provider
s with code like this:
provider = new Provider<MyBean>() {
@Override
public MyBean get() {
return getReferenceFor(MyBean.class);
}
};
private <T> T getReferenceFor(Class<T> type) {
Bean<?> bean = beanManager.resolve(beanManager.getBeans(type));
CreationalContext<?> context = beanManager.createCreationalContext(bean);
try {
return (T) beanManager.getReference(bean, bean.getBeanClass(), context);
} finally {
// Destroy this context - which I don't want to exist anyway.
// I only need a strong reference to a fully @Inject-ed bean!
context.release();
}
}
MyBean
is a @Dependent
scoped bean with no @PreDestroy
method that only needs to be garbage collected when I've finished with it. However, I can't find a lot of information about Provider
s, and so can't tell if I'm arming some kind of time-bomb by doing this.
Some of my @Dependent
scoped beans (which I still obtain via Provider.get()
, btw) are created by @Produces
methods. Are they still in danger of being leaked?
Can anyone advise me, please?
Thanks,
Chris