Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In CDI, how to give scope to a bean at the point of injection?

Tags:

java

cdi

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:

  1. 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?

  2. 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?

like image 251
user2918640 Avatar asked Oct 31 '25 15:10

user2918640


2 Answers

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.

like image 128
Loc Avatar answered Nov 02 '25 05:11

Loc


The scope is always defined on the bean, not on the injection point.

An injection point cannot change the scope of the injected bean.

like image 31
Harald Wellmann Avatar answered Nov 02 '25 06:11

Harald Wellmann