Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdi-dev] Minimal CDI implementation questions


On Wed, Apr 6, 2022 at 10:10 PM John Hendrikx <john.hendrikx@xxxxxxxxx> wrote:


1) How does an InjectionPoint handle an implicit dependency on an owner
class (container class)? For example, when you have a non-static
Producer method, it can only be called after its owner class is
instantiated. The Producer's parameters are injection points, but my
framework also lists the owner class as an injection point, representing
the "this" parameter that is implicitely needed for calling a non-static
Producer method. For such an injection point, my implementation returns
`null` for `getMember()` to indicate the injection point represents the
owner class. How is this handled in CDI?

In CDI, a producer method/field has to be declared in a CDI Bean.
And in order to invoke the non-static producer (i.e. create the bean from it), CDI will need to first instantiate the bean that it is declared in (the "owner class").
I don't fully follow the scenario you are trying to describe, are you talking about self injection?
All I can tell is that `getMember()` isn't returning `null` in any case - it should be either Field,Method or Constructor (according to javadoc).

What I mean is, when the Producer method is called (I'm calling Producers using Reflection) the framework supplies this method with all necessary information to execute the call.  In the case of a non-static Producer method this would necessarily need to include the instance of the owner class + any parameters. 

Perhaps some code helps; this class calls the Producer when its #create method is called, and the list of injections it receives contains the instance of the owner class if it is a non-static producer.  The amount of parameters the Producer needs is therefore the number of injections - 1.

    public class MethodObjectFactory<T> implements Constructable<T> {
      private final Method method;
      private final boolean isStatic;
    
      public MethodObjectFactory(Method method) {
        this.method = method;
        this.isStatic = Modifier.isStatic(method.getModifiers());
    
        method.setAccessible(true);
      }
    
      @Override
      public T create(List<Injection> injections) {
        Object[] values = new Object[injections.size() - (isStatic ? 0 : 1)];  // Parameters for method
        Object instance = null;  // remains null if the Producer is static
        int parameterIndex = 0;
    
        for(Injection injection : injections) {
          if(injection.getTarget() instanceof Method) {
            values[parameterIndex++] = injection.getValue();
          }
          else {
            instance = injection.getValue();  // injection without a target, must be the instance for a non-static producer
          }
        }
   
        return (T)method.invoke(instance, values);
      }
    }

I was just curious how CDI handles this dependency between a Producer and its owner CDI Bean -- it doesn't seem to be visible as an InjectionPoint, whereas in my implementation I saw no reason to handle it differently -- as far as the framework is concerned, the owner instance is just another dependency which can be expressed as an InjectionPoint.

I think however I see that it is not necessary to expose this in the specification as it is really more of an implementation detail on how information about the owner instance is passed along when calling a Producer. I can probably do it in a similar fashion and align this part with how CDI exposes its InjectionPoints.


Alright, I see what you mean.
You are correct that CDI doesn't exactly define this explicitly although it does define InjectionPoint to be Field/Method/Constructor which you violate here.
Furthermore, CDI extensions have events such as ProcessInjectionPoint[1] which also doesn't align with your approach because you couldn't fire the event for it.
I understand that every producer has to keep track f its declaring bean, but I don't perceive the declaring bean as an injection point.
I cannot tell you what Weld does from the top of my head, but in case you want to explore it a bit, I'd start by looking at an abstract representation of the producer bean[2]. Be warned though, it is not going to be an easy read :)
 

2) The BeanAttributes class has a `getQualifiers` method.  Does this
include qualifiers detected in any stereotypes it might be annotated
with? What's the reasoning behind listing stereotypes separately?
Similar question for `getScope` although I'm assuming there that it must
be getting the scope from the stereotype (if present and not overriden).

Yes, it includes those as well. And if I am not mistaken, you'd even see any programmatically added annotations there (i.e. added via extensions).

Yes, that would make sense, thanks for clarifying.

Think of BeanAttributes as a complete view of bean's metadata.
The reason stereotypes are there is because they are also a kind of metadata related to a bean and because they can carry information about its bindings, qualifiers or scope.
And some of its information cannot be found elsewhere due to inheritance rules - for instance a stereotype can declare a scope such as @RequestScoped but the bean itself then declares @ApplicationScoped.
The resulting scope (stored in BeanAttributes) is @ApplicationScoped and you'd need to introspect the stereotype to learn that there was some other scope.

Alright, so could you say that the StereoTypes themselves won't influence decisions made by the injector itself (after the full set of qualifiers and scope has been determined) -- it can just look at the types, qualifers and scope for determining valid candidates and for doing validation/consistency checks of all detected beans.


Pretty much yes. Stereotypes influence the decisions in that they are bean defining annotations[3] and from CDI 4 they can contain `@Priority` as well.
However, most of this information is likely parsed out of them and into bean attributes themselves.
 

The others answers were clear and not entirely unexpected, just wanted to make sure. Thanks a lot :)

--John

_______________________________________________
cdi-dev mailing list
cdi-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/cdi-dev

Back to the top