Imo it is surprising, since it would break all kinds of 'business injections' (as
opposed to classic 'resource injections' - Jens Schumann can explain this well ;)
I think 5.4.2. Client proxy invocation + 6.5.2. Contextual instance of a bean goes rather
in the direction of _very_ lazy initialization ;)
Imho, the current behaviour of Weld, OWB and CanDI is correct.
LieGrue,
strub
--- On Tue, 5/24/11, Pete Muir <pmuir(a)redhat.com> wrote:
From: Pete Muir <pmuir(a)redhat.com>
Subject: Re: [cdi-dev] Proxy implementation leaks
To: "Mark Struberg" <struberg(a)yahoo.de>
Cc: cdi-dev(a)lists.jboss.org
Date: Tuesday, May 24, 2011, 7:24 PM
On 24 May 2011, at 20:15, Mark Struberg wrote:
>> Don't quite get this, spec requires that contexts
are
>> active only at particular points.
>
> yes but imagine the following
>
> @ApplicationScoped
> public class MyService {
> private @Inject User usr; /* User is RequestScoped */
>
> ...
> }
>
> and this MyService will first get invoked in an EJB
which gets initialized at startup. At this time there is NO
Request Context active!
> Thus if you would require all contextual instances
being created immediately, then you would get a
ContextNotActiveException...
Yes, but this isn't that surprising and the principle of
least surprise is a good one to follow ;-)
>
> LieGrue,
> strub
>
> --- On Tue, 5/24/11, Pete Muir <pmuir(a)redhat.com>
wrote:
>
>> From: Pete Muir <pmuir(a)redhat.com>
>> Subject: Re: [cdi-dev] Proxy implementation leaks
>> To: "Mark Struberg" <struberg(a)yahoo.de>
>> Cc: cdi-dev(a)lists.jboss.org
>> Date: Tuesday, May 24, 2011, 7:10 PM
>>
>> On 24 May 2011, at 19:38, Mark Struberg wrote:
>>
>>> Doing this in 2 phases is exactly what I mean
with
>> lazy initialisation. For the cyclic injection
prevention it
>> doesn't matter _how_ lazy.
>>>
>>> As you said: without splitting the proxy
creation from
>> the contextual instance creation, we would not be
able to do
>> proper cyclic injection. For this to work this
must be a 2
>> staged process. Like with forward references in
compilers.
>>
>> Yes, however we can require that this is all done
by a
>> certain point.
>>
>>> Of course the current _very_ lazy behaviour
might lead
>> to curious situations sometimes (as in my
example). But the
>> 'eager' mechanism might lead to 'Context not
active'
>> Exceptions if you e.g. have a @RequestScoped field
which
>> isn't even touched when an @ApllicationScoped
reference gets
>> created in an asynchronous EJB. So you can decide
between
>> bad and evil ;)
>>
>> Don't quite get this, spec requires that contexts
are
>> active only at particular points.
>>
>>>
>>> LieGrue,
>>> strub
>>>
>>> --- On Tue, 5/24/11, Pete Muir <pmuir(a)redhat.com>
>> wrote:
>>>
>>>> From: Pete Muir <pmuir(a)redhat.com>
>>>> Subject: Re: [cdi-dev] Proxy
implementation leaks
>>>> To: "Pete Muir" <pmuir(a)redhat.com>
>>>> Cc: "Mark Struberg" <struberg(a)yahoo.de>,
>> cdi-dev(a)lists.jboss.org
>>>> Date: Tuesday, May 24, 2011, 5:47 PM
>>>> On reflection, I don't believe this
>>>> is correct. The lazy init doesn't help
with
>> cyclic
>>>> injection, it is simply the presence of
proxies
>> that does
>>>> this.
>>>>
>>>> Consider that the DI graph is created
using
>> proxies, and
>>>> call this phase 1. Weld currently does
phase 1 on
>>>> injection.
>>>>
>>>> Phase 2 is the actual instantiation of the
objects
>> backing
>>>> this graph. Weld currently does phase 2
lazily,
>> when the
>>>> first method on a proxy is called and
needs to be
>> passed to
>>>> the bean (and this repeats through the
graph).
>>>>
>>>> We need to split this into two phases, but
there
>> is no
>>>> reason that we can't require
implementations to do
>> phase 2
>>>> immediately that phase 1 has completed,
before we
>> give
>>>> control to client code.
>>>>
>>>> On 9 May 2011, at 16:19, Pete Muir wrote:
>>>>
>>>>> Thanks Mark, I knew there was a reason
for the
>> lazy
>>>> init.
>>>>>
>>>>> The two-ctor call is not necessary
though.
>>>>>
>>>>> On 9 May 2011, at 16:15, Mark Struberg
wrote:
>>>>>
>>>>>> actually this behaviour is pretty
clear in
>> EE.
>>>> It's the same thing as we have with EJBs
since
>> almost ever.
>>>> That's why @PostConstruct exists.
>>>>>>
>>>>>> Whenever object proxies or
>> hidden/transparent
>>>> serialisation happens, then we need to
create the
>>>> object/proxy on the other side/new
invocation. And
>> everytime
>>>> this happens, the constructer will
obviously get
>> called.
>>>>>>
>>>>>> So this is not a bug and surely
not a
>> leak!
>>>>>>
>>>>>> This was on our list when I did a
talk
>> about CDI
>>>> pitfalls at the JSFdays last year together
with
>> Dan.
>>>>>>
>>>>>> Maybe we should doument this
better, but
>> it's
>>>> nothing for the spec, but the user
documentation
>> imo.
>>>>>>
>>>>>> Also the lazy init is imo a well
specified
>> and
>>>> welcome behaviour. Look at the discussions
way
>> back about
>>>> how to prevent cyclic injection problems.
>>>>>>
>>>>>> LieGrue,
>>>>>> strub
>>>>>>
>>>>>> --- On Mon, 5/9/11, Christian
Bauer <christian.bauer(a)gmail.com>
>>>> wrote:
>>>>>>
>>>>>>> From: Christian Bauer <christian.bauer(a)gmail.com>
>>>>>>> Subject: [cdi-dev] Proxy
>> implementation leaks
>>>>>>> To: cdi-dev(a)lists.jboss.org
>>>>>>> Date: Monday, May 9, 2011,
2:46 PM
>>>>>>> Started working with Weld
1.1.1 and
>>>>>>> found two issues that probably
should
>> be
>>>> addressed (maybe
>>>>>>> just documented). They both
look to me
>> like
>>>> leaking
>>>>>>> implementation details because
proxies
>> are
>>>> used for
>>>>>>> components which are not
@Singleton
>> or
>>>> @Dependent.
>>>>>>>
>>>>>>> @ApplicationScoped
>>>>>>> public class Bug {
>>>>>>>
>>>>>>> public
Bug() {
>>>>>>>
>>>>>>>
>> System.out.println("##########
>>>>>>> CONSTRUCT");
>>>>>>> }
>>>>>>>
>>>>>>> public
void foo() {
>>>>>>>
>>>>
System.out.println("#####
>>>>>>> FOO");
>>>>>>> }
>>>>>>>
>>>>>>> public
static void
>>>> main(String[] args) {
>>>>>>>
Weld weld =
>> new
>>>> Weld();
>>>>>>>
>> WeldContainer
>>>> weldContainer
>>>>>>> = weld.initialize();
>>>>>>>
>>>>>>>
Bug bug =
>>>>>>>
>>>>
weldContainer.instance().select(Bug.class).get();
>> //
>>>> Creates
>>>>>>> new instance of Bug
>>>>>>>
bug.foo();
>> //
>>>> Creates new
>>>>>>> instance of Bug!!!
>>>>>>>
bug.foo();
>> //
>>>> Uses existing
>>>>>>> instance
>>>>>>>
>>>>>>>
>>>> weld.shutdown();
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> The proxy of Bug will call
its
>> superclass
>>>> constructor
>>>>>>> several times during the
lifecycle of
>> the Bug
>>>> component. I
>>>>>>> don't know if that is really
>> necessary, but if
>>>> it is, you
>>>>>>> can now no longer use
constructors to
>>>> initialize your
>>>>>>> component. This is an issue
because
>>>>>>>
>>>>>>> - it's not documented that
>> constructors of
>>>>>>> @ApplciationScoped (etc.,
proxied)
>> components
>>>> behave
>>>>>>> differently than
>> @Singleton/@Dependent
>>>> constructors
>>>>>>>
>>>>>>> - even if it's documented,
it's
>> questionable
>>>> if that really
>>>>>>> should be the case.
>>>>>>>
>>>>>>> Taking away constructors as
the
>> primary means
>>>> of
>>>>>>> initializing a component -
e.g.
>> obtaining
>>>> resources such as
>>>>>>> database connections, reading
config
>> files,
>>>> etc. - is a
>>>>>>> major change in the Java
programming
>> model.
>>>> Users have to be
>>>>>>> strongly advised to use
@PostConstruct
>> then.
>>>>>>>
>>>>>>> The other issue I immediately
found is
>> also
>>>> related to
>>>>>>> behavior of proxies and how
>> transitive
>>>>>>> initializing/injection is
implemented
>> (not
>>>> sure if this is
>>>>>>> actually specified
somewhere):
>>>>>>>
>>>>>>> @ApplicationScoped
>>>>>>> public class Foo {
>>>>>>>
>>>>>>>
@Inject
>>>>>>> Bar
bar;
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> @ApplicationScoped
>>>>>>> public class Bar {
>>>>>>>
>>>>>>> @Inject
>>>>>>> Baz baz;
>>>>>>>
>>>>>>>
>> @PostConstruct
>>>>>>> void
init() {
>> ... }
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> When I obtain a reference to
Foo, I
>> get a
>>>> proxy of Foo with
>>>>>>> a reference to a proxy of Bar.
The
>> init()
>>>> method of Bar is
>>>>>>> never called. The Baz
component is
>> never
>>>> activated.
>>>>>>>
>>>>>>> This means I can't
transitively
>> initialize an
>>>>>>> application-scoped graph of
>> components. I was
>>>> trying to use
>>>>>>> CDI for wiring in a Swing
application
>> and I
>>>> imagine this
>>>>>>> would be a common usecase. It
should
>> either be
>>>> documented
>>>>>>> that there is a difference
between
>>>> @Singleton/@Dependent and
>>>>>>> proxy-implemented scopes, or
>> unification
>>>> should be
>>>>>>> considered.
>>>>>>>
>>
>>