You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cloudstack.apache.org by "SuichII, Christopher" <Ch...@netapp.com> on 2013/10/24 22:04:52 UTC

Modularized Spring Modules

Darren,

I’m switching my plugin over to use the new modularized Spring stuff you just merged and there is something I’m still battling with. I have other beans that were previously instantiated before my DataStoreProvider which get injected into the provider, lifecycle, etc. So, those beans need to be instantiated before the DataStoreProvider. How can I ensure those beans are created and setup before the DataStoreProvider does?

-Chris
-- 
Chris Suich
chris.suich@netapp.com
NetApp Software Engineer
Data Center Platforms – Cloud Solutions
Citrix, Cisco & Red Hat


Re: Modularized Spring Modules

Posted by Darren Shepherd <da...@gmail.com>.
Yes avoid ComponentContext.inject() at all costs.  It is really bad.
The problem with ComponentContext.inject(), besides that it is a bad
programming pattern, is that it doesn't know which spring context you
are in.  So ComponentContext.inject() will inject only beans that are
defined in the "core" context.  So extensions are in a child of "core"
so it will not find beans in the child.  There are some ways to work
around this because API commands heavily rely on
ComponentContext.inject(), but I'd prefer that that not be used.
Basically, just don't use ComponentContext.inject().

This was also why at some point I mentioned that
List<SnapshotStrategy> can not be inject to a SnapshotObject.  The
SnapshotObject is setup with ComponentContext.inject() which will not
find the SnapshotStrategys because no SnapshotStrategys exist in the
"core" context.

I will have to work with Edison to eventually remove
ComponentContext.inject() from storage in general.

Darren

On Thu, Oct 24, 2013 at 1:40 PM, SuichII, Christopher
<Ch...@netapp.com> wrote:
> So, I kind of figured it out…
>
> In the past, I was creating my DataStoreLifeCycle with ComponentContext.inject() and it had some members which were @Injecte(d) - those were the guys that were failing to be instantiated. When I switched to simply @Inject my DataStoreLifeCycle into my DataStoreProvider, everything works fine.
>
> So, with this new system, is there some reason that using ComponentContext.inject() would fail to load beans while @Inject would succeed?
>
> -Chris
> --
> Chris Suich
> chris.suich@netapp.com
> NetApp Software Engineer
> Data Center Platforms – Cloud Solutions
> Citrix, Cisco & Red Hat
>
> On Oct 24, 2013, at 4:04 PM, SuichII, Christopher <Ch...@netapp.com> wrote:
>
>> Darren,
>>
>> I’m switching my plugin over to use the new modularized Spring stuff you just merged and there is something I’m still battling with. I have other beans that were previously instantiated before my DataStoreProvider which get injected into the provider, lifecycle, etc. So, those beans need to be instantiated before the DataStoreProvider. How can I ensure those beans are created and setup before the DataStoreProvider does?
>>
>> -Chris
>> --
>> Chris Suich
>> chris.suich@netapp.com
>> NetApp Software Engineer
>> Data Center Platforms – Cloud Solutions
>> Citrix, Cisco & Red Hat
>>
>

Re: Modularized Spring Modules

Posted by "SuichII, Christopher" <Ch...@netapp.com>.
So, I kind of figured it out…

In the past, I was creating my DataStoreLifeCycle with ComponentContext.inject() and it had some members which were @Injecte(d) - those were the guys that were failing to be instantiated. When I switched to simply @Inject my DataStoreLifeCycle into my DataStoreProvider, everything works fine.

So, with this new system, is there some reason that using ComponentContext.inject() would fail to load beans while @Inject would succeed?

-Chris
-- 
Chris Suich
chris.suich@netapp.com
NetApp Software Engineer
Data Center Platforms – Cloud Solutions
Citrix, Cisco & Red Hat

On Oct 24, 2013, at 4:04 PM, SuichII, Christopher <Ch...@netapp.com> wrote:

> Darren,
> 
> I’m switching my plugin over to use the new modularized Spring stuff you just merged and there is something I’m still battling with. I have other beans that were previously instantiated before my DataStoreProvider which get injected into the provider, lifecycle, etc. So, those beans need to be instantiated before the DataStoreProvider. How can I ensure those beans are created and setup before the DataStoreProvider does?
> 
> -Chris
> -- 
> Chris Suich
> chris.suich@netapp.com
> NetApp Software Engineer
> Data Center Platforms – Cloud Solutions
> Citrix, Cisco & Red Hat
> 


Re: Modularized Spring Modules

Posted by "SuichII, Christopher" <Ch...@netapp.com>.
Wow, this was really helpful! I was able to get my extension set up and thing seem to be injecting just fine.

-- 
Chris Suich
chris.suich@netapp.com
NetApp Software Engineer
Data Center Platforms – Cloud Solutions
Citrix, Cisco & Red Hat

On Oct 24, 2013, at 5:00 PM, Darren Shepherd <da...@gmail.com> wrote:

> Let me clarify some terms first, this might be confusing.  There is
> instantiation and then there is initialization.  Instantiation is
> calling the constructor.  Initialization is calling the
> @PostConstruct.  Beyond that there is what I've been calling
> "CloudStack Extended Lifecycle,"  This for bean implementing
> ComponentLifecycle or an extensible interface, like DataStoreProvider.
> Since I'm not sure which aspect your asking about, I'll just explain
> the whole process.
> 
> Spring is now arranged into a hierarchy of contexts.  The parent
> contexts are initialized first, and then the children afterwards.  So
> the process goes as follows
> 
> 1. Instantiate all beans in the current context - There is no way to
> deterministically control the instantiation of beans within a context.
> This is just a fundamental fact that can't change.  So beans are
> randomly instantiated.
> 2. Inject all dependencies on all beans in current context - This
> entails injecting all the dependencies defined by @Inject.  The order
> is not really deterministic which beans get injected first.
> 3. Initialize all beans in graph order - This entails calling all
> methods that have @PostConstruct.  Once the beans are all wired up
> they form a graph of dependencies.  Child beans are initialized first,
> then the parent.  CloudStack has a lot of circular dependencies in the
> beans currently, so while this is intended to be deterministic, you
> may find issues.  The storage code is particularly bad in this area,
> but if you are defining your beans in your own context then this
> doesn't apply.  Only if you add beans to the "core" context will you
> find issues.  If a class has an initialization dependency that is not
> express through its bean dependencies, you can add "depends-on" to the
> bean defintion in the XML.  This will ensure that the specified bean
> will be initialized first.
> 4. CloudStack Extended LifeCycle: Call ComponentLifecycle.configure()
> on all ComponentLifecycle implementing beans
> 5. CloudStack Extended LifeCycle: Register extensible types.  This
> phase happens really at the same time as step 4.  When an extensible
> type is registered nothing typically happens except that its stored in
> a list.  Storage is different in that when the DataStoreProvider is
> registered, at that time DataStoreProvider.configure() will be called.
> Notice that even though DataStoreProvider.configure() has the same
> signature as ComponentLifecycle.configure() it is different.  Honestly
> with the new Spring code we can remove DataStoreProvider completely,
> but that's a different discussion
> 
> After the context is initialized following the steps above, it will
> then initialize all the child contexts.  Once all contexts have been
> completely initialized, ComponentLifecycle.start() will be call on all
> beans starting with the parent context, then children.
> 
> A general guide line of when to use ComponentLifecycle.start() vs
> @PostConstruct is if your initialization logic starts a background
> thread or requires all extensible types to be registered, then you
> should use ComponentLifecycle.start().  All other initialization code
> should be in @PostConstruct.  ComponentLifecycle.configure() is
> largely useless in my mind and should be avoided.
> 
> I hope somewhere in all that is something that answered your question.
> If not you can email me directly with your spring config and I can
> help, or we can setup a GTM.
> 
> Darren
> 
> On Thu, Oct 24, 2013 at 1:04 PM, SuichII, Christopher
> <Ch...@netapp.com> wrote:
>> Darren,
>> 
>> I’m switching my plugin over to use the new modularized Spring stuff you just merged and there is something I’m still battling with. I have other beans that were previously instantiated before my DataStoreProvider which get injected into the provider, lifecycle, etc. So, those beans need to be instantiated before the DataStoreProvider. How can I ensure those beans are created and setup before the DataStoreProvider does?
>> 
>> -Chris
>> --
>> Chris Suich
>> chris.suich@netapp.com
>> NetApp Software Engineer
>> Data Center Platforms – Cloud Solutions
>> Citrix, Cisco & Red Hat
>> 


Re: Modularized Spring Modules

Posted by Darren Shepherd <da...@gmail.com>.
Let me clarify some terms first, this might be confusing.  There is
instantiation and then there is initialization.  Instantiation is
calling the constructor.  Initialization is calling the
@PostConstruct.  Beyond that there is what I've been calling
"CloudStack Extended Lifecycle,"  This for bean implementing
ComponentLifecycle or an extensible interface, like DataStoreProvider.
 Since I'm not sure which aspect your asking about, I'll just explain
the whole process.

Spring is now arranged into a hierarchy of contexts.  The parent
contexts are initialized first, and then the children afterwards.  So
the process goes as follows

1. Instantiate all beans in the current context - There is no way to
deterministically control the instantiation of beans within a context.
 This is just a fundamental fact that can't change.  So beans are
randomly instantiated.
2. Inject all dependencies on all beans in current context - This
entails injecting all the dependencies defined by @Inject.  The order
is not really deterministic which beans get injected first.
3. Initialize all beans in graph order - This entails calling all
methods that have @PostConstruct.  Once the beans are all wired up
they form a graph of dependencies.  Child beans are initialized first,
then the parent.  CloudStack has a lot of circular dependencies in the
beans currently, so while this is intended to be deterministic, you
may find issues.  The storage code is particularly bad in this area,
but if you are defining your beans in your own context then this
doesn't apply.  Only if you add beans to the "core" context will you
find issues.  If a class has an initialization dependency that is not
express through its bean dependencies, you can add "depends-on" to the
bean defintion in the XML.  This will ensure that the specified bean
will be initialized first.
4. CloudStack Extended LifeCycle: Call ComponentLifecycle.configure()
on all ComponentLifecycle implementing beans
5. CloudStack Extended LifeCycle: Register extensible types.  This
phase happens really at the same time as step 4.  When an extensible
type is registered nothing typically happens except that its stored in
a list.  Storage is different in that when the DataStoreProvider is
registered, at that time DataStoreProvider.configure() will be called.
 Notice that even though DataStoreProvider.configure() has the same
signature as ComponentLifecycle.configure() it is different.  Honestly
with the new Spring code we can remove DataStoreProvider completely,
but that's a different discussion

After the context is initialized following the steps above, it will
then initialize all the child contexts.  Once all contexts have been
completely initialized, ComponentLifecycle.start() will be call on all
beans starting with the parent context, then children.

A general guide line of when to use ComponentLifecycle.start() vs
@PostConstruct is if your initialization logic starts a background
thread or requires all extensible types to be registered, then you
should use ComponentLifecycle.start().  All other initialization code
should be in @PostConstruct.  ComponentLifecycle.configure() is
largely useless in my mind and should be avoided.

I hope somewhere in all that is something that answered your question.
 If not you can email me directly with your spring config and I can
help, or we can setup a GTM.

Darren

On Thu, Oct 24, 2013 at 1:04 PM, SuichII, Christopher
<Ch...@netapp.com> wrote:
> Darren,
>
> I’m switching my plugin over to use the new modularized Spring stuff you just merged and there is something I’m still battling with. I have other beans that were previously instantiated before my DataStoreProvider which get injected into the provider, lifecycle, etc. So, those beans need to be instantiated before the DataStoreProvider. How can I ensure those beans are created and setup before the DataStoreProvider does?
>
> -Chris
> --
> Chris Suich
> chris.suich@netapp.com
> NetApp Software Engineer
> Data Center Platforms – Cloud Solutions
> Citrix, Cisco & Red Hat
>