[cdi-dev] Producer#dispose(T instance) and similar

Pete Muir pmuir at redhat.com
Mon Dec 10 07:37:43 EST 2012


On 10 Dec 2012, at 09:33, Mark Struberg wrote:

> 
>> My understanding of the spec is that an InjectionTarget is completely 
>> responsible for building and invoking interceptors and decorators. 
> 
> That only got added in CDI-1.0. In CDI-1.0 it was _not_ defined.

Agreed, it was very ambiguous in CDI 1.0. I asked Gavin, this was the way he intended it.

> 
> My point is that this is technically not possible for a _portable_ Producer and InjectionTarget to get it right!
> 
> It would need to know exactly:
> * how the proxies work, ASF, Javassist, BCEL, etc
> * how to store the Interceptors and Decorators in the CreationalContext
> * how to _retrieve_ the Interceptors and Decorators our of the CreationalContext again!
> 
> I don't think this can be done in a portable way. At least I found no solution so far...
> An easy example: The produce(CC) method only has a CreationalContext parameter but not a BeanManager! So how would you e.g. resolve an @ApplicationScoped bean which contains the producer method? 
> 
> 
> The only solution I can think about is to define that setProducer and setInjectionTarget must only be used to _wrap_ the existing ones.
> 
> 
> LieGrue,
> strub
> 
> 
> 
> 
> ----- Original Message -----
>> From: Jozef Hartinger <jharting at redhat.com>
>> To: Mark Struberg <struberg at yahoo.de>
>> Cc: Pete Muir <pmuir at redhat.com>; cdi-dev <cdi-dev at lists.jboss.org>
>> Sent: Monday, December 10, 2012 10:23 AM
>> Subject: Re: [cdi-dev] Producer#dispose(T instance) and similar
>> 
>> My understanding of the spec is that an InjectionTarget is completely 
>> responsible for building and invoking interceptors and decorators. The 
>> produce() method can either return the target object (assuming there are 
>> no interceptors or decorators) or a proxy that handles interception. 
>> This is completely transparent to the container.
>> 
>> The instance that the container retrieves from the produce() method is 
>> then passed to postConstruct(), preDestroy() and dispose() methods. Note 
>> that if the instance is a proxy it is a client proxy (creating client 
>> proxies is the container's job, not InjectionTarget's) but rather an 
>> interceptor/decorator enabling proxy which carries interceptor/decorator 
>> instances. Therefore, the CreationalContext is not necessary in those 
>> methods as the instance itself knows how to invoke interceptors/decorators.
>> 
>> HTH,
>> 
>> JH
>> 
>> On 12/07/2012 10:56 PM, Mark Struberg wrote:
>>>> I think the critical part of the spec to understand this is 11.2. 
>> I'm
>>>> quoting here from the CDI 1.1 spec, into which we have add the 
>> clarification
>>>> that "The instance returned by produce() may be a proxy.". 
>> The part
>>>> about building interceptors and decorators is there in CDI 1.0.
>>> I think that would end up being highly non-portable and we must revert this 
>> 'clarification' as it breaks a lot of stuff!
>>> 
>>> Proxies are the core business of the cdi container! If we allow/force a 
>> pluggable Producer<T> to handle the interception proxying then this would 
>> not be possible without knowing implementation details of the respective 
>> container. This starts with the fact that we need to store the implicitly 
>> @Dependent scoped Interceptors and Decorators in our CreationalContexts but we 
>> do _not_ define an API to portably extract Interceptors and Decorators from them 
>> later.
>>> 
>>> 
>>> Also this contradicts the need that some functionality like e.g. CDI events 
>> might be private methods. There is just no way to invoke a private method on a 
>> proxy whose internal structure you don't know. And doing the interceptors 
>> via subclassing instead of proxies would break both the EJB and the interceptors 
>> spec which define that only 'external' calls must get intercepted.
>>> 
>>> LieGrue,
>>> strub
>>> 
>>> 
>>> 
>>> ----- Original Message -----
>>>> From: Pete Muir <pmuir at redhat.com>
>>>> To: Mark Struberg <struberg at yahoo.de>
>>>> Cc: cdi-dev <cdi-dev at lists.jboss.org>
>>>> Sent: Tuesday, December 4, 2012 5:46 PM
>>>> Subject: Re: [cdi-dev] Producer#dispose(T instance) and similar
>>>> 
>>>> Hi Mark, I'll try to answer inline, but I'm missing a bit of 
>> background
>>>> about what you are doing...
>>>> 
>>>> On 4 Dec 2012, at 14:20, Mark Struberg wrote:
>>>> 
>>>>>    Another problem probably being an interceptor on the @Disposes 
>> method
>>>> itself.
>>>>>    Where does the Proucer#dispose(T instance) get the interceptor 
>> from?
>>>>> 
>>>>>    LieGrue,
>>>>>    strub
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>>    ----- Original Message -----
>>>>>>    From: Mark Struberg <struberg at yahoo.de>
>>>>>>    To: cdi-dev <cdi-dev at lists.jboss.org>
>>>>>>    Cc:
>>>>>>    Sent: Tuesday, December 4, 2012 3:16 PM
>>>>>>    Subject: [cdi-dev] Producer#dispose(T instance) and similar
>>>>>> 
>>>>>>    Hi!
>>>>>> 
>>>>>>    I'm currently stumbling over implementing
>>>>>> 
>>>>>>    Producer#dispose(T instance) properly
>>>>>> 
>>>>>>    The Producer#produce(CreationalContext)
>>>>>> 
>>>>>>    has the CreationalContext parameter but the dispose
>>>> Right, it would have been good to have included it here. I'm not 
>> sure why it
>>>> wasn't, however I don't believe that it causes a problem with 
>> the CDI
>>>> 1.0 spec, but just limits us going forward.
>>>> 
>>>>>>    and others do not have it.
>>>> Yes.
>>>> 
>>>>>>    Problem here is that a Producer could probably get exchanged 
>> via a
>>>> portable
>>>>>>    extension via ProcessProducer#setProducer(Producer)
>>>> Yes, this is definitely supported
>>>> 
>>>>>>    so it could be from a
>>>>>>    foreign source which must not know anything about container
>>>> implementation
>>>>>>    details.
>>>> Yes.
>>>> 
>>>> I think the critical part of the spec to understand this is 11.2. 
>> I'm
>>>> quoting here from the CDI 1.1 spec, into which we have add the 
>> clarification
>>>> that "The instance returned by produce() may be a proxy.". 
>> The part
>>>> about building interceptors and decorators is there in CDI 1.0.
>>>> 
>>>>>    For a Producer that represents a class:
>>>>> 
>>>>>        • produce() calls the constructor annotated @Inject if it 
>> exists, or
>>>> the constructor with no parameters otherwise, as defined in 
>> [instantiation], and
>>>> returns the resulting instance. If the class has interceptors,produce() 
>> is
>>>> responsible for building the interceptors and decorators of the 
>> instance. The
>>>> instance returned by produce() may be a proxy.
>>>>>        • dispose() does nothing.
>>>> and
>>>> 
>>>>>    For a Producer that represents a producer method or field:
>>>>> 
>>>>>        • produce() calls the producer method on, or accesses the 
>> producer
>>>> field of, a contextual instance of the bean that declares the producer 
>> method,
>>>> as defined in [methods].
>>>>>        • dispose() calls the disposer method, if any, on a 
>> contextual instance
>>>> of the bean that declares the disposer method, as defined in [methods], 
>> or
>>>> performs any additional required cleanup, if any, to destroy state 
>> associated
>>>> with a resource.
>>>> 
>>>> Now, let me start to break down your sentence :-)
>>>> 
>>>>>>    What now about having an interceptor on @PreDestroy?
>>>> For a start, it's worth remembering interceptors can only be 
>> associated with
>>>> beans defined by a class. If the bean is a producer, then you can't
>>>> intercept the instance produced (only the invocation of the producer).
>>>> 
>>>>>>    This is what you get if
>>>>>>    your interceptor has a at PreDestroy method himself as per the
>>>> interceptors and EJB
>>>>>>    specs. That would mean that the instance passed to dispose() 
>> whould be
>>>> the
>>>>>>    proxy? That purely sounds wrong to me.
>>>> Based on my comment from above, I think it's clear that dispose() 
>> should
>>>> never try to invoke predestroy methods. That is the job of
>>>> InjectionTarget.preDestroy(). I would expect a proxy to be passed to
>>>> preDestroy().
>>>> 
>>>>> 
>>>>>>    Another issue being InjectionTarget#postConstruct() only 
>> having the
>>>> instance T
>>>>>>    as well. Now what about @PostConstruct interceptors as 
>> defined in the
>>>>>>    interceptors spec?
>>>> Again, I would expect a proxy to be passed to postConstruct(). Anyway, 
>> I'm
>>>> not sure why you need access to the creational context in the 
>> postConstruct()?
>>>> Here you should just invoke the postConstruct callback, which should 
>> create any
>>>> new dependent objects.
>>>> 
>>>>>>    Currently we have a dirty hack in OWB to pass over the
>>>> CreationalContext which
>>>>>>    contains the dependent scoped interceptors for our own 
>> Producers and
>>>>>>    InjectionTargets. But I have no clue yet how that should get
>>>> implemented if one
>>>>>>    plugs in a portable Producer via an Extension ^^
>>>>>> 
>>>>>>    Who is responsible of performing the interception? The 
>> Producer? Or
>>>> must the
>>>>>>    instance being handed into already be a Proxy?
>>>> The instance returned from produce() should have interceptors and 
>> decorators
>>>> applied.
>>>> 
>>>> Please let me know if above makes sense, it took me a while to work out 
>> whether
>>>> what was defined was sane. After quite a lot of thinking + talking to 
>> Jozef and
>>>> Stuart I came to the conclusion it was, but  if you can poke holes then 
>> please
>>>> do!
>>>> 
>>> _______________________________________________
>>> cdi-dev mailing list
>>> cdi-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>> 




More information about the cdi-dev mailing list