This content has been marked as final.
Show 3 replies
-
1. Re: Method @Produces with varying implementations at runtime
nickarls Mar 22, 2010 8:50 AM (in response to wujek)Yes, they are created each time (they're dependents).
You could always inject a manager object that has stuff cached or use Instance etc if you don't want stuff created too often.
I must say I didn't understand the last paragraph ;-)
-
2. Re: Method @Produces with varying implementations at runtime
wujek Mar 22, 2010 10:24 AM (in response to wujek)What I meant is this: the Bean that stands for a producer method is container managed, and this method is called by the container when a bean that this method produces (with the type and qualifiers) is required, it is not normally called by the user. So it would be fairly simple for the container to call this method, then intercept the result, perform injection on it and return this injected instance. This would enable the producer method to instantiate the object with the 'new' keyword, and still have such instances injected.
You wrote: Yes, they are created each time (they're dependents).
Weld docs say (section 8.3 from http://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html#d0e3306):
"Then a new dependent instance of CreditCardPaymentStrategy will be created, passed to the producer method, returned by the producer method and finally bound to the session context. The dependent object won't be destroyed until the Preferences object is destroyed, at the end of the session."
The above would imply that the created @New beans are dependent on the bean that defines the producer method, not on the bean on whose behalf the method was called.
Suppose the Preferences is @ApplicationScoped. This means, that for 100 invocations of the producer method, there will exist 300 dependent objects, 200 of which were never used, and the remaining 100 were used but are not needed any more (they are dependent, and the bean that used this method is potentially out of scope - dependent itself, but the Preferences instance is @ApplicationScoped and it holds on to the objects). If the application runs for a long time, this might result in OutOfMemoryException, as the instances cannot be GC-ed. The option to allow 'new' creation and injecting afterwards would decrease the number of object by 3. And I still don't understand why the produced @New dependent objects are preserved for the whole lifetime of the Preferences object - shouldn't they be destroyed when the bean instance that needed them and on whose behalf the producer was called is destroyed? I see creating a manager (as suggested above) as a workaround - CDI has it's own contexts and scope management, so it is the manager for me, and should take care of removing unneeded instances, why would I want to create my own?
(I base the above on my understanding of the quoted excerpt and your last post. If what I say is rubbish, feel free to bash me, I will be very happy to learn otherwise ;d).
What I meant that it is simple to inject in to an instance is (I am sure you know this code):
Object instance = ...
Class<?> clazz = instance.getClass();
Annotation[] qualifiers = getQualifiers(instance.getClass().getAnnotations()); // helper that uses BeanManager.isQualifier()
AnnotatedType<?> annotatedType = beanManager.createAnnotatedType(instance.getClass());
InjectionTarget<?> injectionTarget = beanManager.createInjectionTarget(annotatedType);
Set<Bean<?>> beans = beanManager.getBeans(instance.getClass(), qualifiers);
if (beans.size() == 0) {
throw new IllegalStateException("class '" + clazz.getName()
+ "' seems not to be a CDI managed bean; make sure it complies with "
+ "the CDI specification requirements and the class is in a bean "
+ "archive - there must be a 'beans.xml' file in appropriate location");
}
Bean<?> bean = beans.iterator().next();
CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean);
InjectionTarget rawInjectionTarget = injectionTarget;
rawInjectionTarget.inject(instance, creationalContext);
I do it in our TestNG tests, where instance is the test class instance - this enables us to declare object in test classes using CDI typesafe injection, and have them injected for us. Works a charm.
Wujek -
3. Re: Method @Produces with varying implementations at runtime
nickarls Mar 22, 2010 12:01 PM (in response to wujek)I glanced at the code and I think I'll stand corrected.
Producers have CreationalContexts (sort of
bubbles
around them that picks up what they produce so they can be destroyed as dependents when the producer-defining bean goes down), I get the picture that these contexts are searched first to see if they already exist from a previous invocation which keeps the number of instances to go out of control with @New (they're beans, too).