users@hk2.java.net

Re: InstanceLifeCycleListener examples?

From: buko <buko_at_chiubarobot.com>
Date: Thu, 8 Aug 2013 08:15:34 -0400

Perhaps this is a bug. If I have a custom injection annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface FxmlResource {

    public String path();
}


and a custom injection resolver that processes that annotation:

public class FxmlResourceInjectionResolver implements
InjectionResolver<FxmlResource>{

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> root) {
        AnnotatedElement target = injectee.getParent();
        FxmlResource controller = target.getAnnotation(FxmlResource.class);
        String path = controller.path();

        try {
            URL fxmlResource =
injectee.getInjecteeClass().getResource(path);

            if (fxmlResource == null)
                throw new RuntimeException("Could not find resource path="
+ path + " searching from class=" + injectee.getInjecteeClass());

            return FXMLLoader.load(fxmlResource);
        } catch (IOException ioe) {
            throw new RuntimeException(this + " failed to resolve " +
injectee, ioe);
        }
    }

    @Override
    public boolean isConstructorParameterIndicator() {
        return true;
    }

    @Override
    public boolean isMethodParameterIndicator() {
        return false;
    }

}


Will this Injectee show up in the knownInjectees map later when the
InstanceLifeCycleListeners are notified? Or are InstanceLifeCycleListeners
only told about the built-in/system injection points?


On Thu, Aug 8, 2013 at 8:10 AM, buko <buko_at_chiubarobot.com> wrote:

>
> Have a bit of a bigger problem: seems like the knownInjectees map is
> always empty. Javadoc says this will happen for the case of objects created
> by factories or pre-reified descriptors. If my object is not created by a
> factory and is bound using AbstractBinder#addActiveDescriptor() does that
> not meet the criteria? And why would the knownInjectees map be empty rather
> than null?.
>
>
> On Thu, Aug 8, 2013 at 7:42 AM, buko <buko_at_chiubarobot.com> wrote:
>
>> It looks like for a given object @PostConstruct methods will be invoked
>> before the InstanceLifeCycleListener is given the chance to post-process
>> the object by handling the POST_PRODUCTION event. So if I have an
>> InstanceLifeCycleListener and its goal is to post-process an object, it
>> gets a LifeCycleEvent with lifeCycleObject=null (the PRE_PRODUCTION) case,
>> then @PostConstruct gets invoked but of course everything is still null
>> because the listener was never given a chance to do its post-processing.
>>
>> Is there a way around this? Can I post-process an object to get in there
>> to set some variables before its @PostConstruct methods get invoked?
>>
>>
>> On Wed, Aug 7, 2013 at 10:18 AM, buko <buko_at_chiubarobot.com> wrote:
>>
>>> Thanks John. The qualifier thing makes sense, I'll give it a shot.
>>> On Aug 7, 2013 9:07 AM, "John Wells" <john.wells_at_oracle.com> wrote:
>>>
>>>> Answers in-line.
>>>>
>>>> The fact that you are asking these questions implies that we do not
>>>> have enough documentation for the feature. I will try to find somewhere to
>>>> add an example or find some other way to upgrade the documentation.
>>>>
>>>> On 8/7/2013 8:43 AM, buko wrote:
>>>>
>>>>>
>>>>> Are there any examples of custom InstanceLifeCycleListeners out there?
>>>>>
>>>> We have no example of the InstanceLifeCycleListener in our
>>>> documentation. However, the config subsystem of HK2 uses it in order to
>>>> have a backwards reference from the injectee to the injector. I think some
>>>> kind of example should be added to the hk2 documentation.
>>>>
>>>>>
>>>>> I'm looking to do some basic post-processing of managed objects. In
>>>>> the normal injection phase a resource is passed to the ctor. In the next
>>>>> phase I'd like to go back and use the injected resource to further
>>>>> customize the object.
>>>>>
>>>>> I've taken a look at ConfigInstanceListener and don't quite get it.
>>>>>
>>>>> Does the lifecycle object (post-processing target?) need to implement
>>>>> a specific interface in order for the Filter to match? Ideally I'd like to
>>>>> just slap an annotation on them. But it's not clear how to construct a
>>>>> Filter that matches an annotation.
>>>>>
>>>> If you just want to put an annotation on the classes you want to
>>>> operate on the best thing to do would be to make your annotation a
>>>> qualifier (i.e., put @Qualifier on your annotation). That way your
>>>> annotation would show up in the list of qualifiers in the Descriptor. And
>>>> thus the Filter could easily match just those services that have that
>>>> qualifier.
>>>>
>>>>>
>>>>> If I need to actually initialize/wrap/set fields on the lifecycle
>>>>> object does hk2 offer any facilities for that? Should normal java
>>>>> reflection be used? I'm worried this won't work if the post-processing
>>>>> object is proxied by hk2. Do InstanceLifeCycleListeners get called for the
>>>>> creation of proxies if the underlying object hasn't been created yet?
>>>>>
>>>> You would need to do your own reflection. The object returned here is
>>>> NOT the proxy, but the real underlying object, which means you can call any
>>>> methods you want on the object and not worry about causing the proxy to
>>>> create the underlying object (thus invalidating the point of the proxy!).
>>>> This fact should be documented in the javadoc though!
>>>>
>>>>>
>>>>> What does InstanceLifeCycleEvent#**knownInjectees return? Are these
>>>>> the same injectees that are passed to a custom InjectionResolver?
>>>>>
>>>> For this the javadoc is pretty clear. The descriptor has a set of
>>>> injectees. This is a map from that set of injectees to the real objects
>>>> that were created for this object. This is useful in the usecase described
>>>> above, where the user wants to have a backwards pointer from the injectee
>>>> to the injector.
>>>>
>>>>>
>>>>> Thanks for any help.
>>>>>
>>>>
>>>>
>>
>