[cdi-dev] Producer#dispose(T instance) and similar
Pete Muir
pmuir at redhat.com
Mon Dec 10 07:34:41 EST 2012
On 7 Dec 2012, at 21:56, 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!
I added this "clarification", as Gavin told me it was the intent of the 1.0 spec, and that the line from the 1.0 spec, "builds interceptors and decorators" meant that the instance returned by produce() should have them applied.
Anyway, I've never been overly happy with the result, and I do wonder if there is a better solution. For example, BeanManager.applyInterceptorsAndDecorators(T instance, Bean b); (or some other argument list that I haven't quite worked out yet). This would allow a sequence like:
WDYT? Just an idea atm.
>
> 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!
>>
More information about the cdi-dev
mailing list