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



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.

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.

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

--John


Back to the top