Uploaded image for project: 'CDI Specification Issues'
  1. CDI Specification Issues
  2. CDI-277

Clarify inheritance behavior of observer methods

    • Icon: Clarification Clarification
    • Resolution: Won't Do
    • Icon: Major 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

            Please reopen if you disagree and want changes

            Pete Muir (Inactive) added a comment - Please reopen if you disagree and want changes

            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.

            Pete Muir (Inactive) added a comment - 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.

            Arne Limburg (Inactive) added a comment - 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

            Martin Kouba added a comment - 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

            Mark Struberg (Inactive) added a comment - 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.

            Jozef Hartinger added a comment - 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.

            Mark Struberg (Inactive) added a comment - - edited

            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.

            Mark Struberg (Inactive) added a comment - - edited 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.

            What's X?

            Jozef Hartinger added a comment - What's X?

            ~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!

            Mark Struberg (Inactive) added a comment - ~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

            Mark Struberg (Inactive) added a comment - 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.

            Jozef Hartinger added a comment - 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.)

            Martin Kouba added a comment - 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.

            Arne Limburg (Inactive) added a comment - 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

            Mark Struberg (Inactive) added a comment - 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?

            Arne Limburg (Inactive) added a comment - 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.

            Arne Limburg (Inactive) added a comment - 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?

            Arne Limburg (Inactive) added a comment - 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!

            Arne Limburg (Inactive) added a comment - 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?

            Mark Struberg (Inactive) added a comment - 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?

              pmuiratbleepbleep Pete Muir (Inactive)
              arnelim Arne Limburg (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: