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(a)redhat.com>
To: Mark Struberg <struberg(a)yahoo.de>
Cc: Pete Muir <pmuir(a)redhat.com>; cdi-dev <cdi-dev(a)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(a)redhat.com>
>> To: Mark Struberg <struberg(a)yahoo.de>
>> Cc: Pete Muir <pmuir(a)redhat.com>; cdi-dev
<cdi-dev(a)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(a)redhat.com>
>>>> To: Mark Struberg <struberg(a)yahoo.de>
>>>> Cc: Pete Muir <pmuir(a)redhat.com>; cdi-dev
>> <cdi-dev(a)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(a)redhat.com>
>>>>>> To: Mark Struberg <struberg(a)yahoo.de>
>>>>>> Cc: cdi-dev <cdi-dev(a)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(a)yahoo.de>
>>>>>>>> To: cdi-dev
<cdi-dev(a)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@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(a)lists.jboss.org
>>>>>
https://lists.jboss.org/mailman/listinfo/cdi-dev