-
Clarification
-
Resolution: Won't Do
-
Major
-
None
-
None
-
None
-
None
Chapter 4.2 of the (1.0) spec misses a bullet point about inheritance of observer methods.
Either
- If X declares a non-static observer method x() then Y does inherit this method.
or - If X declares a non-static observer method x() then Y does not inherit this method.
(This behavior is different to what is defined in the Common Annotations for the Java Platform specification.)
should be added.
Don't know, what's right through...
[CDI-277] Clarify inheritance behavior of observer methods
I think this is already covered "When an enabled bean, as defined in Section 5.1.2, “Enabled and disabled beans”, specializes a second bean, we can be certain that the second bean is never instantiated or called by the container. Even if the second bean defines a producer or observer method, the method will never be called."
I'm going to reject this issue.
I think, we now agree.
But we should add an explicite sentence to the inheritance section about what specializing beans NOT inherit (in opposition to normal subclassing)
See my comment above.
I'll take a look into the TCK to see if it needs to be improved or if the 1.1 version is just fine in this area.
Well, in CDI TCK 1.1 we have a lot of new tests covering all the obvious assertions from chapter "4. Inheritance and specialization" (1.0 covers 69.66%, 1.1 covers 100%). Though it's sometimes quite difficult to reveal and test all hidden corners of the spec. Anyways feel free to file a TCK issue to add some missing tests
After discussing all that I think we have pretty much a common agreement. Arne, wdyt?
This area is definitely missing some more TCK tests though
Yes, it does not disable other beans completely. That's what specialization is for. Though, I understand the tricky part with a specialized private method you raised.
X is just a placeholder for some random interface.
The point is that an @Alternative never disables another bean completely. What if e.g. class A implements X, Y ? Then @Alternative class B implements X would only be used for @Inject X x; but not for @Inject Y y; injection points.
~jharting ok, let me rephrase: A non-activated @Alternative is never target of a CDI event. The @Alternative must be enabled to get a CDI event.
What I meant is that just having another
@Alternative class B implements X
for
class A implements X
will NOT disable any observer method in class A!
Ok Martin. This means that you can just override any observer method with an empty method to disable it. Of course this only works for non-private methods, but that is a problem of the programmer I guess
1.) This bullet clearly disables veto() beans from receiving Observers, right?
A vetoed bean is definitely not an enabled bean so this is clear IMHO.
2.) @Alternative has no influence on Observers at all! They do not disable beans but only affect the resolution process.
A bean is said to be enabled if: it is not an alternative, or it is a selected alternative of at least one bean archive.
An event is delivered to an observer method if: The observer method belongs to an enabled bean.
So from there I would say that @Alternatives do have influence on observers.
Arne,
I don't get what's missing (WRT the issue description) - the spec states in "4.2. Inheritance of member-level metadata":
- If X declares an initializer, non-static observer, @PostConstruct or @PreDestroy method x() then Y inherits x() if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the method x().
(This behavior is defined by the Common Annotations for the Java Platform specification.)
Yes, in addition to the bullet point I suggest in the description above, there should be a bullet point that clarifies inheritance for specializing beans.
So either
- If Y specializes X (as defined in Section 3.1.4, "Specializing a managed bean" and Section 3.2.4, "Specializing a session bean") and X declares a non-static observer method x() then Y does inherit this method.
or - If Y specializes X (as defined in Section 3.1.4, "Specializing a managed bean" and Section 3.2.4, "Specializing a session bean") and X declares a non-static observer method x() then Y does not inherit this method. (This behavior is different to what is defined in the Common Annotations for the Java Platform specification.)
should be added.
If the first is taken, then the last sentence of 4.3 has to be changed to "Even if the second bean defines a producer or observer method, the method will never be called on a contextual instance of the second bean."
In addition similar bullet points must be added for producer methods.
Y extends X
X will be scanned and a Bean<X> will be created for it
Y will be scanned and a Bean<Y> will be created for it
If Y @Specializes extends X then Bean<X> is disabled.
But Y still inherits all the methods of X.
Assume X has a method doSomething(@Observes SomeEvent e) {..
Then this method is also part of any instance of type Y.
We are perfectly d' accord that there will be no contextual instance created for Bean<X> ever. But imo it's not clear what should happen with the methods which get inherited by any contextual instance for Bean<Y>. At least it's not clear to me right now
That leads to the inheritance issues. So which methods should be called in this scenario:
public class BeanA { private void observer1(@Observes Event1 event1) { } public void observer2(@Observes Event2 event2) { } private static void observer3(@Observes Event3 event3) { } public static void observer4(@Observes Event4 event4) { } } public class BeanB extends BeanA { private void observer1(@Observes Event1 event1) { } public void observer2(@Observes Event2 event2) { } private static void observer3(@Observes Event3 event3) { } public static void observer4(@Observes Event4 event4) { } }
On event1 I would expect to be called:
observer1 of BeanA on an instance of BeanA
observer1 of BeanA on an instance of BeanB
observer1 of BeanB on an instance of BeanB
On event2 I would expect to be called:
observer2 of BeanA on an instance of BeanA
observer2 of BeanB on an instance of BeanB
On event3 I would expect to be called:
observer3 of BeanA
observer3 of BeanB
On event4 I would expect to be called:
observer4 of BeanA
observer4 of BeanB
right?
OK, learned something
From the wording of the 1.0 spec, especially the last paragraph of 4.3: "When an enabled bean [...] specializes a second bean, we can be
certain that the second bean is never instantiated or called by the container. Even if the second bean defines a producer or
observer method, the method will never be called."
So in fact in the scenario I described a method of BeanA would never be called because it is specialized by BeanC. I think this is pretty clear from the spec, but the sentence should be moved to some location earlier in that chapter, because auf it's importance. Anyway the specialization rules are quite clear with that sentence and @Mark: With this you get the possibility to disable a private observer by specialization.
On event1 I would expect to be called:
observer1 of BeanA on an instance of BeanB
observer1 of BeanA on an instance of BeanC
observer1 of BeanB on an instance of BeanB
observer1 of BeanC on an instance of BeanC
observer1 of BeanA is NOT called on an instance of BeanA because it is specialized
On event2 I would expect to be called:
observer2 of BeanB on an instance of BeanB
observer2 of BeanC on an instance of BeanC
observer2 of BeanA is NOT called because BeanB and BeanC override it and no instance of BeanA exists, because BeanC specializes it.
On event3 I would expect to be called:
observer3 of BeanB
observer3 of BeanC
observer3 of BeanA is NOT called because BeanA is specialized
On event4 I would expect to be called:
observer4 of BeanB
observer4 of BeanC
observer4 of BeanA is NOT called because BeanA is specialized
wdyt?
There are some more cases to be clarified:
public class BeanA { private void observer1(@Observes Event1 event1) { } public void observer2(@Observes Event2 event2) { } private static void observer3(@Observes Event3 event3) { } public static void observer4(@Observes Event4 event4) { } } public class BeanB extends BeanA { private void observer1(@Observes Event1 event1) { } public void observer2(@Observes Event2 event2) { } private static void observer3(@Observes Event3 event3) { } public static void observer4(@Observes Event4 event4) { } } @Specializes public class BeanC extends BeanA { private void observer1(@Observes Event1 event1) { } public void observer2(@Observes Event2 event2) { } private static void observer3(@Observes Event3 event3) { } public static void observer4(@Observes Event4 event4) { } }
We need to clarify which methods on which instance get called on event1, event2, event3 and event4!
There is another paragraph in the spec where this gets covered:
10.2. Observer resolution
An event is delivered to an observer method if:
• The observer method belongs to an enabled bean.
In my opinion the following must get clarified:
1.) This bullet clearly disables veto() beans from receiving Observers, right?
2.) @Alternative has no influence on Observers at all! They do not disable beans but only affect the resolution process.
3.) A @Specializes class Y must be a subclass of another class X. If X defines an observer method then this is also part of class Y and thus will get called.
4.) Any Reception.ALWAYS Observer method in X will NOT create a contextual instance of X but only of type Y (as X is not an enabled bean)
What I'm asking me is how one can disable a private observer method in it's superclass or a static observer method at all ^^ Probably only via Extensions.
What if there are 2 Observer methods, both private and with the exact same name and signature, but in different levels in the class hierarchy? Guess both will get triggered, right?
Please reopen if you disagree and want changes