[cdi-dev] Proxy implementation leaks
Mark Struberg
struberg at yahoo.de
Tue May 24 15:15:38 EDT 2011
> 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...
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