[cdi-dev] Producer#dispose(T instance) and similar
Mark Struberg
struberg at yahoo.de
Mon Dec 10 08:04:25 EST 2012
Another point is that we allow private methods for quite some parts. E.g. @PreDestroy and @PostConstruct are per commons-annotations perfectly fine as private methods. As are CDI event observers and @Inject methods. But for invoking private methods you need to 'bypass' the proxy. And this only works if the CDI container knows the proxy internas. That would just not work if the Producer<T> creates the interceptor proxy and the rest is unaware of the implementation details.
First we need a list of all the methods invoked via the container which could probably be private. After that we can think about which functionality is possible to implement fully portable. I fear we might find a few blockers...
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 1:47 PM
> Subject: Re: [cdi-dev] Producer#dispose(T instance) and similar
>
> 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