-
1. Re: Does javax.inject.Provider.get() always return a new instance?
pgmjsd Jul 12, 2011 2:32 PM (in response to yangju.richard.yang.pearson.com)Short answer: Yes. It returns a new instance every time.
Note that these are going to be managed instances, so they will be tracked by Weld until the context is destroyed. This can lead to some unexpected behavior when injecting an Instance into an ApplicationScoped bean, as Weld may keep every instance around forever.
-
2. Re: Does javax.inject.Provider.get() always return a new instance?
yangju.richard.yang.pearson.com Jul 12, 2011 2:41 PM (in response to yangju.richard.yang.pearson.com)Thanks for confirming this.
I am glad you mention this. I am injecting those beans into an applicationscoped bean right now. I have to use Application scope in my case.
@ApplicationScoped
Class MyClass {
@Inject
@Any
Instance<MyType> source;
MyType myBeans= (MyType) source.select(new AnnotationLiteral<MyAnnotation>() { }).get();
...
}
So you are saying that there could be many instances of myBeans injected into the application scoped Myclass and managed by weld.
And these instances will stay as long as the jvm is up.
Then is there a way for me to pro grammatically decommission/remove the beans?
-
3. Re: Does javax.inject.Provider.get() always return a new instance?
pgmjsd Jul 12, 2011 3:49 PM (in response to yangju.richard.yang.pearson.com)
richard yang wrote on Jul 12, 2011 14:41:
So you are saying that there could be many instances of myBeans injected into the application scoped Myclass and managed by weld.Yes. Instance provides 'managed beans'.
And these instances will stay as long as the jvm is up.Yes.
Then is there a way for me to pro grammatically decommission/remove the beans?CDI 1.0 currently produces managed instances only. See https://issues.jboss.org/browse/CDI-139
-
4. Re: Does javax.inject.Provider.get() always return a new instance?
haye Jul 12, 2011 11:17 PM (in response to yangju.richard.yang.pearson.com)
I haven't tried this myself, but couldn't you add @New to the injection point (not sure if it's even allowed)?
e.g.
@Any @New Instance<MyType> source;
...
MyType myBeans= source.select(new AnnotationLiteral<MyAnnotation>() { }).get();
...
As long as there is only one bean that is of type MyType and is annotated with @MyAnnotation (context doesn't matter), you should receive a new dependent instance of the bean. -
5. Re: Does javax.inject.Provider.get() always return a new instance?
haye Jul 12, 2011 11:24 PM (in response to yangju.richard.yang.pearson.com)
.. or if CDI wont allow you to add @New at the injection point, you could always do it when you're retrieving the instance
MyType myBeans= source.select(new AnnotationLiteral<MyAnnotation>() { }, new AnnotationLiteral<New>() { }).get(); -
6. Re: Does javax.inject.Provider.get() always return a new instance?
yangju.richard.yang.pearson.com Jul 13, 2011 10:26 AM (in response to yangju.richard.yang.pearson.com)I have verified that weld does generate a new instance everytime the MyType myBeans= (MyType) source.select(new AnnotationLiteral<MyAnnotation>() { }).get(); gets called.
But I don't understand that why Weld does not remove the old instances when a new instance is created. As you can see from the declaration:
@Inject
@Any
Instance<MyType> source;
There is only one source declared. Why does weld have to keep all the instances in the scope, when a new one is created.
BTW, the @Any @New Instance<MyType> source is not allowed.
-
7. Re: Does javax.inject.Provider.get() always return a new instance?
yangju.richard.yang.pearson.com Jul 13, 2011 10:33 AM (in response to yangju.richard.yang.pearson.com)If I inject @Inject
@Any
Instance<MyType> source;
into an applicationscoped bean and run the get() over and over, eventually I would get OutOfMemory error. This seems a Weld's design defect to me. -
8. Re: Does javax.inject.Provider.get() always return a new instance?
haye Jul 13, 2011 1:25 PM (in response to yangju.richard.yang.pearson.com)Since every time you call Instance.get() a new bean with @Dependent scope is created, the object will linger as long as the @ApplicationScoped bean it is dependent on (MyClass) is still in existence (for the lifetime of your application).
I believe you need to re-think how you're doing things. If the method that calls Instance.get() is invoked as part of a request, then you need to make MyType a request-scoped bean. That way, the instance created when you call Instance.get() will be destroyed at the end of the request. You can do this by either annotating MyType with @RequestScoped or you can create a request-scoped producer method that returns the object.
-
9. Re: Does javax.inject.Provider.get() always return a new instance?
haye Jul 13, 2011 1:41 PM (in response to yangju.richard.yang.pearson.com)Also have a look at this thread http://seamframework.org/Community/DependentBeansDoubts
They seem to be dealing with your exact use case.
-
10. Re: Does javax.inject.Provider.get() always return a new instance?
yangju.richard.yang.pearson.com Jul 13, 2011 2:41 PM (in response to yangju.richard.yang.pearson.com)Thanks, Zak.
In my case, I could make the bean non-applicationscoped, but this bean eventually gets injected to a service bean (such as jboss mbean) which is an application scoped singleton. My understanding is (I also verified) that the application scoped service bean promotes all its dependent beans into the same application scope. This is exactly CDI supposed to do. So, mark this bean as RequestScoped or psedo scopes won't help me.
This link you provides is exactly what my problem is. I wonder why I did not see this thread before. The other difference is that the reason I use Instance<> is because the instance that I am injecting is unknown at compiler time. Basically it is based on user's input (a name of class) and then the application will create an instance based on this class name string. I think this is what the CDI programmatically lookup is designed for. I could create a object out of the class name that the user selects by doing Class.newInstance(). Then the new instance is not managed by Weld and I cannot inject anything into it. That is essentially why I use get().
I wish CDI did not create a new instance everytime get() is called. I also wish that CDI would find a way to release the previous instance it creates. But those are just my wish.
As the discussions in the thread you mentioned, using get() has serious memory problem (potentially), and the Weld documentation should have pointed it out.
If you have other ideas for my problem, please let me know.
I really appreciate your help, especially the link that you found for me.
Richard -
11. Re: Does javax.inject.Provider.get() always return a new instance?
pgmjsd Jul 13, 2011 6:20 PM (in response to yangju.richard.yang.pearson.com)
richard yang wrote on Jul 13, 2011 14:41:
I wish CDI did not create a new instance everytime get() is called.Then don't use Instance, just inject the bean.
I also wish that CDI would find a way to release the previous instance it creates. But those are just my wish.You want
unmanaged instances
. CDI 1.0 currently supportsmanaged instances
only, where the CDI container is guaranteed to call lifecycle methods when the context/bean goes out of scope, etc. What you want is a Guice / PicoContainer behavior where the container creates the object and then hands it to you:your problem now, buddy
.See https://issues.jboss.org/browse/CDI-139
Please vote for this issue, maybe it will be included in CDI 1.1.
As the discussions in the thread you mentioned, using get() has serious memory problem (potentially), and the Weld documentation should have pointed it out.Yes! It's very easy to misunderstand CDI's Instance.get() behavior, especially if you have used other DI frameworks. It goes something like this:
- Developer: I want Weld to return me a new instance every time. How do I do that.
- CDI Guru: Inject Instance and use the Instance.get().
- Developer: Okay thanks! (goes off and tries it...)
- Developer: Hey, Java isn't cleaning up the objects created by Instance.get() because the CDI implementation is pointing at them! WTF?
- CDI Guru: That is because they are managed instances.
- Developer: $%#&!#$*(%!