-
1. Re: Beans with a dependent scope and an observer method - weird behavior
mkouba Nov 21, 2016 3:09 AM (in response to steappe)Hi Stéphane,
this is expected behavior. When the container calls an observer method it must obtain a contextual instance first. For dependent beans this means to create a new instance (and also destroy this instance properly when the invocation completes). Note that dependent bean instances do not live in a context, they're bound to the lifecycle of the bean they depend on. See also Invocation of observer methods and Destruction of objects with scope @Dependent.
-
2. Re: Beans with a dependent scope and an observer method - weird behavior
steappe Nov 21, 2016 5:14 AM (in response to mkouba)Hi Martin,
Thanks for the clarification.
I wonder if the CDI specifications should be clarified then, because:
http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#observer_notificationhttp://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#observer_notification
"If there is no context active for the scope to which the bean declaring the observer method belongs, then the observer method should not be called."
And
http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#dependent_context
"Any instance of the bean injected into an object that is being created by the container is bound to the lifecycle of the newly created object."
"Any instance of the bean that receives a producer method, producer field, disposer method or observer method invocation exists to service that invocation only."
Can you see the confusion?
I have then another question:
Is it possible to implement a portable CDI extension in Weld-SE defining a custom scope that would behave exactly as I want, i.e. where only Son and Daughter would be notified in my example above?
Or said it differently, where only the beans declaring an observer method and that are placed in the scope of an active context would be notified.
If yes, a few hints about the implementation would be helpful. Thanks
-
3. Re: Beans with a dependent scope and an observer method - weird behavior
mkouba Nov 21, 2016 5:29 AM (in response to steappe)Can you see the confusion?
Not really . The @Dependent scope is always active. These sentences simply mean that if you have a @Dependent bean with an observer method, a new bean instance is always created when the observer is about to be called, then the observer method is called upon the instance and finally, the instance is destroyed afterwards.
I have then another question:
Is it possible to implement a portable CDI extension in Weld-SE defining a custom scope that would behave exactly as I want, i.e. where only Son and Daughter would be notified in my example above?
Or said it differently, where only the beans declaring an observer method and that are placed in the scope of an active context would be notified.
If yes, a few hints about the implementation would be helpful. Thanks
Well, this will work for any normal scope but not for @Dependent - for @Dependent the container does not hold a reference to the bean instance.
-
4. Re: Beans with a dependent scope and an observer method - weird behavior
steappe Nov 21, 2016 11:11 AM (in response to mkouba)Ok got it for the @Dependent scope now. Since it's always active, then it makes perfectly sense. It's a bit counter-intuitive in a first place, but I can understand.
I've started the implementation of a custom scope @MyScoped, which would have the behavior I want, and an associated MyContext. So I have this:
@MyScoped
class Parent {
@Inject Child son;
@Inject Child daughter;
public Child getSon() {return son;}
public Child getDaughter() {return daughter;}
}
@MyScoped
class Child {
public void foo() {}
private void onEvent(@Observes SomeEvent event) {
}
}
For such a construct to work, I need two different instances of Child: one for son and one for daughter.
So I implemented MyContext this way:
MyContext implements Context {
@Override
public <T> T get(Contextual<T> contextual) {
return null; // always return null so a new instance of the bean is created.
}
}
But of course this is not working:
Child son = parent.getSon(); // a new instance of parent is created
Child daughter = parent.getDaughter(); // once again, a new instance of parent is created
son.foo(); // a new instance of son is created
son.foo(); // once again, a new instance of son is created
How can I implement the get method of MyContext, so I can have 1 instance of parent, and two instances of Child?
I feel like I would need to have an access to the injection point of the bean, more or less the same way it's done in the DependentContext. But how can it be done in a portable way?
-
5. Re: Beans with a dependent scope and an observer method - weird behavior
mkouba Nov 22, 2016 2:24 AM (in response to steappe)How can I implement the get method of MyContext, so I can have 1 instance of parent, and two instances of Child?
I think this is not possible as long as MyScoped is a normal scope (for normal scope there's always one instance per bean per thread). So in other words, you could either have distinguish @Dependent children without observers or shared normal scoped child with observers. You may also consider invoking the observer logic manually. E.g. define the observer on Parent and delegate to all Children instances. Also I'd recommend to look at Object tree" scope prototype and Command context example to get some more info about how contexts work in CDI.