[cdi-dev] Proxy implementation leaks

Pete Muir pmuir at redhat.com
Tue May 24 15:24:13 EDT 2011


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 at redhat.com> wrote:
> 
>> From: Pete Muir <pmuir at redhat.com>
>> Subject: Re: [cdi-dev] Proxy implementation leaks
>> To: "Mark Struberg" <struberg at yahoo.de>
>> Cc: cdi-dev at 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 at redhat.com>
>> wrote:
>>> 
>>>> From: Pete Muir <pmuir at redhat.com>
>>>> Subject: Re: [cdi-dev] Proxy implementation leaks
>>>> To: "Pete Muir" <pmuir at redhat.com>
>>>> Cc: "Mark Struberg" <struberg at yahoo.de>,
>> cdi-dev at 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 at gmail.com>
>>>> wrote:
>>>>>> 
>>>>>>> From: Christian Bauer <christian.bauer at gmail.com>
>>>>>>> Subject: [cdi-dev] Proxy
>> implementation leaks
>>>>>>> To: cdi-dev at 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.
>>>>>>> 
>> 
>> 




More information about the cdi-dev mailing list