[cdi-dev] Proxy implementation leaks

Mark Struberg struberg at yahoo.de
Tue May 24 14:38:09 EDT 2011


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.

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 ;)

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