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

Mark Struberg struberg at yahoo.de
Mon Dec 10 04:33:29 EST 2012


> 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.

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