OpenWebBeans
  1. OpenWebBeans
  2. OWB-667

Bean queries have strange behavior (difference between Open Web Beans and the Reference Implementation)

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.1.4
    • Fix Version/s: 1.1.5
    • Component/s: Core
    • Labels:
      None
    • Environment:
      All

      Description

      We use the BeanManager#getBeans(java.lang.reflect.Type, java.lang.annotation.Annotation...) to find all beans of a certain type (to implement something like a service locator).
      As soon as one of the beans is an activated Alternative, the list of matching beans is reduced to this activated Alternative.

      The expected behavior is present in the Reference Implementation.
      Please refer to the attached test cases.

      1. cdi-boot.zip
        52 kB
        Phil Oser

        Activity

        Hide
        Phil Oser added a comment -

        This test case allows to run tests for open web beans or weld. The tests are implemented in the maven project "cdi-test".

        It uses Maven 3 and works with an empty settings.xml file.

        Show
        Phil Oser added a comment - This test case allows to run tests for open web beans or weld. The tests are implemented in the maven project "cdi-test". It uses Maven 3 and works with an empty settings.xml file.
        Hide
        Mark Struberg added a comment -

        Hi Phil!

        Thanks for the report! I guess this is a duplicate of OWB-658 ?
        Can you please check the explanation there?

        The core part is that getBeans is not defined to return all Beans of the given class, but to return all beans which are subject to be injected into an InjectionPoint of the given type! And if you have an @Alternative involved for that type, all other beans are disabled for this injection.

        I fear it's just not a good idea to use getBeans as replacement for the java.util.ServiceLoader. We maybe need to think about portable ways to do such stuff in CDI.

        In my big app I just fire a CDI Event 'registerMyServices' which has a #addService(YourService s) method to pick up all implementations.

        Show
        Mark Struberg added a comment - Hi Phil! Thanks for the report! I guess this is a duplicate of OWB-658 ? Can you please check the explanation there? The core part is that getBeans is not defined to return all Beans of the given class, but to return all beans which are subject to be injected into an InjectionPoint of the given type! And if you have an @Alternative involved for that type, all other beans are disabled for this injection. I fear it's just not a good idea to use getBeans as replacement for the java.util.ServiceLoader. We maybe need to think about portable ways to do such stuff in CDI. In my big app I just fire a CDI Event 'registerMyServices' which has a #addService(YourService s) method to pick up all implementations.
        Hide
        Phil Oser added a comment -

        Hello Mark

        Yes, it is the same problem as owb 658. The RI has the behavior we expect. We figured that we did not get our argument taken into account, so we tried again.

        Given the javadoc (without the behavior of Weld), I could imagine a different behavior, namely that all the beans that match the query (including alternatives) are returned.
        But the open web beans implementation throws away all results if just ONE alternative is encountered (even if the query includes much more beans than just the one matching the alternative).

        I understand your pattern with the event. But I think it is a nuisance if a framework that manages bean does not allow to query for beans?!

        BTW: IMHO it would be great if open web beans could run CDI extensions such as solder. I think it shows some advanced usages (we already filed another bug due to it).

        Thanks and cheers,
        P

        Show
        Phil Oser added a comment - Hello Mark Yes, it is the same problem as owb 658. The RI has the behavior we expect. We figured that we did not get our argument taken into account, so we tried again. Given the javadoc (without the behavior of Weld), I could imagine a different behavior, namely that all the beans that match the query (including alternatives) are returned. But the open web beans implementation throws away all results if just ONE alternative is encountered (even if the query includes much more beans than just the one matching the alternative). I understand your pattern with the event. But I think it is a nuisance if a framework that manages bean does not allow to query for beans?! BTW: IMHO it would be great if open web beans could run CDI extensions such as solder. I think it shows some advanced usages (we already filed another bug due to it). Thanks and cheers, P
        Hide
        Romain Manni-Bucau added a comment -

        Hi Phil,

        i don't understand your answer, reading the 2nd paragrah you say you want the behavior describe by the javadoc but what you explain is not the one described in the spec (cf Mark answer).

        Regarding solder, openwebbeans can run a lot of them, i had issues regarding some of seam 3 extensions (on openejb jira) because seam was hard linked to weld but generally it works well.

        Show
        Romain Manni-Bucau added a comment - Hi Phil, i don't understand your answer, reading the 2nd paragrah you say you want the behavior describe by the javadoc but what you explain is not the one described in the spec (cf Mark answer). Regarding solder, openwebbeans can run a lot of them, i had issues regarding some of seam 3 extensions (on openejb jira) because seam was hard linked to weld but generally it works well.
        Hide
        Mark Struberg added a comment -

        Hi!

        Yes, that was one of the reasons which did lead to the creation of Apache DeltaSpike (consisting mostly of members of the MyFaces CODI and the JBoss Seam community). Please file a CDI spec issue that the getBeans() needs further clarification. Imo I do not care much whether we do the filtering of @Alternatives in BeanManager#getBeans or in BeanManager#resolve(). The only important thing is that the container is still able to do injection resolving and we remain portable (and backward compatible).

        PS: The stuff you have as StartMain exists in OWB since more than 2 years in our cditest module We also moved it over to DeltaSpike now. See CdiCtrl. We are happy about every helping hand though ...

        Show
        Mark Struberg added a comment - Hi! Yes, that was one of the reasons which did lead to the creation of Apache DeltaSpike (consisting mostly of members of the MyFaces CODI and the JBoss Seam community). Please file a CDI spec issue that the getBeans() needs further clarification. Imo I do not care much whether we do the filtering of @Alternatives in BeanManager#getBeans or in BeanManager#resolve(). The only important thing is that the container is still able to do injection resolving and we remain portable (and backward compatible). PS: The stuff you have as StartMain exists in OWB since more than 2 years in our cditest module We also moved it over to DeltaSpike now. See CdiCtrl. We are happy about every helping hand though ...
        Hide
        Phil Oser added a comment -

        @Romain:

        I try to clarify my point:
        I understand the point of Mark that the javadoc of getBeans says "only injectable references" shall be returned. But nevertheless, I think that the implementation of OWB is wrong in this respect:
        It starts by evaluating the bean query. As soon as it finds just ONE alternative, it throws away all the found query-results.

        Show
        Phil Oser added a comment - @Romain: I try to clarify my point: I understand the point of Mark that the javadoc of getBeans says "only injectable references" shall be returned. But nevertheless, I think that the implementation of OWB is wrong in this respect: It starts by evaluating the bean query. As soon as it finds just ONE alternative, it throws away all the found query-results.
        Hide
        Romain Manni-Bucau added a comment -

        But if an alternative is activated it is the only available result regarding this condition so it seems fine

        Show
        Romain Manni-Bucau added a comment - But if an alternative is activated it is the only available result regarding this condition so it seems fine
        Hide
        Mark Struberg added a comment -

        I can explain this point: the candidate type of a bean is it's type plus all it's interfaces and superclasses. The same is true for an @Alternative. Having a class

        @Alternative
        public class MyBean extends X, implements Y {..

        gives you the following Type[]:

        {MyBean, X, Y, Object}

        .

        @Alternative is (way too shortly) defined (chapter 2.6.3, 4.3) and use the matching algorithm defined in 5.2.1:

        >When an ambiguous dependency exists, the container attempts to resolve the ambiguity.
        > The container eliminates all eligible beans that are not alternatives, except for
        > producer methods and fields of beans that are alternatives. If there is ex- actly one bean
        > remaining, the container will select this bean, and the ambiguous dependency is called resolvable.

        What neither the spec nor the javadoc say is whether this should happen in getBeans() or in resolve().
        I'll try to again clarify this with the EG.

        Show
        Mark Struberg added a comment - I can explain this point: the candidate type of a bean is it's type plus all it's interfaces and superclasses. The same is true for an @Alternative. Having a class @Alternative public class MyBean extends X, implements Y {.. gives you the following Type[]: {MyBean, X, Y, Object} . @Alternative is (way too shortly) defined (chapter 2.6.3, 4.3) and use the matching algorithm defined in 5.2.1: >When an ambiguous dependency exists, the container attempts to resolve the ambiguity. > The container eliminates all eligible beans that are not alternatives, except for > producer methods and fields of beans that are alternatives. If there is ex- actly one bean > remaining, the container will select this bean, and the ambiguous dependency is called resolvable. What neither the spec nor the javadoc say is whether this should happen in getBeans() or in resolve(). I'll try to again clarify this with the EG.
        Hide
        Mark Struberg added a comment -

        I've now talked with a few EG community members and created https://issues.jboss.org/browse/CDI-231

        What Weld does atm is that it partially filters in getBeans() (dropping non-enabled beans) and partially in resolve().

        I'll wait for a reply from Pete to finally clarify the exact behaviour and then might change this in OWB (should not be a problem, just move the logic).

        Show
        Mark Struberg added a comment - I've now talked with a few EG community members and created https://issues.jboss.org/browse/CDI-231 What Weld does atm is that it partially filters in getBeans() (dropping non-enabled beans) and partially in resolve(). I'll wait for a reply from Pete to finally clarify the exact behaviour and then might change this in OWB (should not be a problem, just move the logic).
        Hide
        Mark Struberg added a comment -

        I've now aligned the behaviour with Weld. We will also clarify this in CDI-1.1

        Show
        Mark Struberg added a comment - I've now aligned the behaviour with Weld. We will also clarify this in CDI-1.1

          People

          • Assignee:
            Mark Struberg
            Reporter:
            Phil Oser
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development