Reputation: 473
In CDI, I am able to inject a bean with a particular scope, the scope with which the bean class was defined. But what if I create the bean class without any scope and I give scope to that bean at the point of injection. My requirement is to make injection-time-scoping possible in the latter case. Problem is that injection is happening with dependent scope
instead of the desired annotated scope unless I use a producer
.
For Example:
CASE 1:
When I declare scope of a bean in its class declaration like this:
@ApplicationScoped
class UserDetails {
...
}
And injected like this:
@ViewScoped
class UserView {
@Inject
UserDetails userDetails;
.
.
}
It works as expected. The bean injected in application scope is available throughout the application in all other beans.
CASE 2:
But when I give no scope in class declaration:
class UserDetails {
...
}
And injected like this (giving scope at the point of injection):
@ViewScoped
class UserView {
@Inject @ApplicationScoped
UserDetails userDetails;
.
.
}
This failed!.. The injected bean did not inject in application scope
but got dependent scope
instead (View Scope
in my case).
I had to create a Producer
& a Qualifier
where @Produces
method is providing the bean in desired application scope
. I feel this producer/qualifier extension turns out to be an overhead if I have to inject bean class UserDetails in application scope
in this case.
Thing is, UserDetails class is part of a third party jar. This class does not have any scope declared and is a POJO. I can not change its source code.
Based on the above discussion, I have two questions:
Why someone would create bean classes defined with no scope when they know that the beans are to be injected under a particular scope? Would this practice do any good in terms of design?
As I do not have control over the source code of the bean classes and as they are not associated with any scope, Is producer/qualifier extension the only good way to inject such beans in the desired scope?
Upvotes: 3
Views: 2819
Reputation: 9655
1. Object without scope defined - @Dependent used
CDI will treat Object wihout scope as @Dependent scope.
An instance of a dependent bean is never shared between different clients or different injection points. It is strictly a dependent object of some other object. It is instantiated when the object it belongs to is created, and destroyed when the object it belongs to is destroyed.
Beans with scope @Dependent don’t need a proxy object. The client holds a direct reference to its instance.
Spring IoC dev: CDI @Dependent scope is similar to Spring IoC Prototype scope.
2. No @Produces & just use @Inject
CDI will create new instance of UserDetails for each injection (@Dependent scope). No sharing data here! You can't define scope as you did (when inject).
3. Use @Produces & use @Inject
You can control the scope of UserDetails object (ApplicationScoped, SessionScoped, or RequestScoped)
public class Producers {
@Produces @ApplicationScoped
public UserDetails createUserDetails() {
// Initialize UserDetails
}
public void release(@Disposes UserDetails userDetails) {
// Release userDetails if you have to
}
}
4. Another way: Extend UserDetails if possible
@ApplicationScoped // Or @SessionScoped, @RequestScoped
public class UserDetailsImpl extends UserDetails {
//
}
If you want ApplicationScoped for UserDetails. Way 3 or way 4 can be used.
Upvotes: 6
Reputation: 1
I think you can inject an @ApplicationScoped
bean as a @Dependent
bean by specifying the @New
annotation near the injection point, but you can't do the opposite.
Upvotes: 0
Reputation: 12865
The scope is always defined on the bean, not on the injection point.
An injection point cannot change the scope of the injected bean.
Upvotes: 2