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

Jozef Hartinger jharting at redhat.com
Mon Dec 10 07:47:54 EST 2012


On 12/10/2012 12:58 PM, Mark Struberg wrote:
>> 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"
> Oh you are right, this is even in the CDI-1.0 spec already :/
>
>
>
>> 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.
> Well, this option is only possible if the BeanManager doesn't change depending on the horizontal layer you are in. You remember your 1.a decision? Imo that might blast all those approaches, doesn't it?
Yes, for this to work correctly one would need to use the appropriate 
BeanManager for the given bean archive which is tricky and not really 
portable ATM. What I've seen so far is passing the BeanManager instance 
that the extension gets, which works mostly but breaks if the deployment 
structure gets more complicated (ear) or if alternatives are used.
>
> 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 11:00 AM
>> Subject: Re: [cdi-dev] Producer#dispose(T instance) and similar
>>
>> 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