[cdi-dev] Producer#dispose(T instance) and similar
Jozef Hartinger
jharting at redhat.com
Mon Dec 10 05:00:05 EST 2012
On 12/10/2012 10:33 AM, 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.
Right, I am not saying this is crystal clear in the spec. This is how I
understand the spec. The spec only says: " If the class has
interceptors, produce() is responsible for building the interceptors and
decorators of the instance"
>
> 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!
Right, an extension can either wrap an existing producer that handles
interceptors/decorators or provide its own InjectionTarget. The latter
option makes sense in situations where the extension knows that the
produced instance does not support interception/decoration. Otherwise it
is more convenient to use the former option IMHO.
>
> 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 extension that wraps/creates the InjectionTarget instance can have
the BeanManager injected. I am used to passing the BeanManager reference
to the InjectionTarget during creation of the InjectionTarget instance
and keeping it within the instance.
>
>
> 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