Discussion:
[picocontainer-dev] Desired behavior for Picocontainer and Static injection
Michael Rimov
2013-06-05 05:04:42 UTC
Permalink
Ok, so this is the last thing on the todo list to get the TCK + all optional
tests running for JSR-330.



The TCK wants static initialization, but to keep track of things so that we
only inject statics one time.



To me that means we have to maintain some sort of state about what's been
initialized, but what scope?



Do we do it across all containers? (ie a static variable inside default
picocontainer) (for the record, my own personal opinion on this solution.
ick!)



Personally I'm of the opinion that we keep track of static initialization
once per container. (via a Non static member variable, probably a
WeakHashSet. weak so it doesn't prevent classloaders from gc'ing a class?)



If we have multiple containers (not in a parent-child way) referencing the
same class, then it would mean that a static variable will be initialized
multiple times, but personally I think this is an edge case behavior that we
can live with compared to having to have Static variables inside DPC.



I suppose a complicated way would be to run a class enhancer to offload the
state information there. but that seems like a lot of work for what we would
call an recommended way of doing things.



Thoughts?




-Mike
Paul Hammant
2013-06-08 05:12:32 UTC
Permalink
Mike,

I'm not really happy with JSR330's patronage of injection into class
variables. If we had to say we're not going to do it, but we'll do
everything else from JSR 330 that's instance based, then I'd not be unhappy.

Can we do it in a separate class? StaticEnabledPicoContainer (implements
MPC, has-a DPC) ? Then it's a take it or leave it thing.
Post by Michael Rimov
Ok, so this is the last thing on the todo list to get the TCK + all
optional tests running for JSR-330.****
** **
The TCK wants static initialization, but to keep track of things so that
we only inject statics one time.****
** **
To me that means we have to maintain some sort of state about what’s been
initialized, but what scope?****
** **
Do we do it across all containers? (ie a static variable inside default
picocontainer) (for the record, my own personal opinion on this solution…
ick!)****
** **
Personally I’m of the opinion that we keep track of static initialization
once per container. (via a Non static member variable, probably a
WeakHashSet… weak so it doesn’t prevent classloaders from gc’ing a class?)
****
** **
If we have multiple containers (not in a parent-child way) referencing the
same class, then it would mean that a static variable will be initialized
multiple times, but personally I think this is an edge case behavior that
we can live with compared to having to have Static variables inside DPC.
****
** **
I suppose a complicated way would be to run a class enhancer to offload
the state information there… but that seems like a lot of work for what we
would call an recommended way of doing things.****
** **
Thoughts?****
** **
-Mike****
Michael Rimov
2013-06-09 06:46:32 UTC
Permalink
Paul,



Well, according to the TCK's comments, static member injection IS optional.
That said just to get this far means I have a significant portion of the
work done to make it 100% pass the tck, and I'm kind of with the mindset
that since we're this far, go for it for "buzzword compliance" even if we
don't recommend the use of static member injection.



I think I'll peel the logic out into separate injectors that are turned off
by default but still included in Adapting injection. That way a person
could explicitly turn it on with:



pico.as(STATIC_INJECTION).addComponent(..);



but it would sit in a default "off" state. This would also help with
keeping track of statics initialization on a per-container basis. If
somebody wants to share a class across multiple unconnected containers, only
the container with STATIC_INJECTION turned on for the component registration
would be initializing the statics.






-Mike





From: Paul Hammant [mailto:paul-POq8DFUn+***@public.gmane.org]
Sent: Friday, June 07, 2013 10:13 PM
To: Michael Rimov
Cc: dev
Subject: Re: Desired behavior for Picocontainer and Static injection



Mike,



I'm not really happy with JSR330's patronage of injection into class
variables. If we had to say we're not going to do it, but we'll do
everything else from JSR 330 that's instance based, then I'd not be unhappy.



Can we do it in a separate class? StaticEnabledPicoContainer (implements
MPC, has-a DPC) ? Then it's a take it or leave it thing.



On Wed, Jun 5, 2013 at 12:04 AM, Michael Rimov <rimovm-***@public.gmane.org>
wrote:

Ok, so this is the last thing on the todo list to get the TCK + all optional
tests running for JSR-330.



The TCK wants static initialization, but to keep track of things so that we
only inject statics one time.



To me that means we have to maintain some sort of state about what's been
initialized, but what scope?



Do we do it across all containers? (ie a static variable inside default
picocontainer) (for the record, my own personal opinion on this solution.
ick!)



Personally I'm of the opinion that we keep track of static initialization
once per container. (via a Non static member variable, probably a
WeakHashSet. weak so it doesn't prevent classloaders from gc'ing a class?)



If we have multiple containers (not in a parent-child way) referencing the
same class, then it would mean that a static variable will be initialized
multiple times, but personally I think this is an edge case behavior that we
can live with compared to having to have Static variables inside DPC.



I suppose a complicated way would be to run a class enhancer to offload the
state information there. but that seems like a lot of work for what we would
call an recommended way of doing things.



Thoughts?




-Mike
Michael Rimov
2013-06-10 19:53:44 UTC
Permalink
1) Could the root-most container permanently turn off static injection for
subsequent child containers ?



If you want to completely enforce no static injection:



new JSRPicoContainer(new AdaptingInjection() {

protected boolean allowStaticInjection() {

return false;

}

});



OR because the state variable that will keep track of what classes have been
statically initialized is only going to set in JSRPicoContainer



new DefaultPicoContainer(new AdaptingInjection());



will work as well, but you lose automatic key generation and automatic
caching management based on the annotations this way.





2) Like #1, but for any subsequent container whether child or not.



pico.makeChildContainers()



will propagate ComponentAdapterFactories like normal, so whatever behavior
you have will propagate.



Otherwise, if you manually construct your own container:



new DefaultPicoContainer(new AdaptingInjection() { ... }, parentContainer)
to force no static injection.



3) What about serialization de-serialization for containers that do or don't
have static injection turned on, and if that could override previous
all-container settings?



Don't know what the current rules for ComponentAdapterFactories are. It
would follow whatever we have already in place since it's just another
ComponentAdapterFactory + InjectionAdapter and explicitly turned on by a
property.



4) Does STATIC_INJECTION as you're designing it, transcend scopes of
containers somewhat ? Or is it a scope in itself that's parent of
"Application scope" (called singleton scope in other containers)?



Well the state mechanism I'm going to use will sit as an instance variable
in a JSRPicoContainer. So if you have:



appScopeContainer.as(Characteristics.STATIC_INJECTION).addComponent(A.class)
;



and



requestScopeContainer.as(Characteristics.STATIC_INJECTION).addComponent(A.cl
ass);



Then the static methods are going to initialize twice.



I have no interest in sharing state between Picocontainers in such a way so
that statics (clearly an edge case and a mediocre one at that) are
guaranteed to initialize only once across multiple containers.



The way I'm designing it will pass the TCK (since it only uses one
container), and I think that's good enough. To completely guarantee
only-once initialization across multiple containers, I think I'd need to
either resort to static state variables in containers. (ICK!), or bytecode
modification to pass the state off to the actually class. I personally
don't think adding a bytecode modification library for an edge case is a
good reason to further bloat Pico.



Additionally, since static initialization is an OPTIONAL feature of the JSR,
I think it's worth it to say we support static initialization with a few
caveats and if the joker that LOVES static initialization gets ticked off @
Picocontainer , so be it. But if some poor sot is stuck with static
initialization because of the code he inherited, I'd say let's be merciful
to him and give him a way to get it done.




-Mike
Michael Rimov
2013-06-11 00:20:43 UTC
Permalink
Never answered the other behavior part of serialization: statics will be
reinitialized because the list of methods of what has been injected cannot
be serialized. So the next time an object is retrieved, static injection
will proceed anew.



I guess my stance is still "allow them at it if they need it," but as soon
as they start doing "Pico-y" things with the container, then its caveat
emptor.




-Mike



P.S. Good questions :)



From: Michael Rimov [mailto:rimovm-***@public.gmane.org]
Sent: Monday, June 10, 2013 12:54 PM
To: 'Paul Hammant'; dev-qxt/k92ZUMzOYGyH7mwfjrEhcVWVsK+***@public.gmane.org
Subject: [picocontainer-dev] RE: Desired behavior for Picocontainer and
Static injection
1) Could the root-most container permanently turn off static injection for
subsequent child containers ?



If you want to completely enforce no static injection:



new JSRPicoContainer(new AdaptingInjection() {

protected boolean allowStaticInjection() {

return false;

}

});



OR because the state variable that will keep track of what classes have been
statically initialized is only going to set in JSRPicoContainer



new DefaultPicoContainer(new AdaptingInjection());



will work as well, but you lose automatic key generation and automatic
caching management based on the annotations this way.





2) Like #1, but for any subsequent container whether child or not.



pico.makeChildContainers()



will propagate ComponentAdapterFactories like normal, so whatever behavior
you have will propagate.



Otherwise, if you manually construct your own container:



new DefaultPicoContainer(new AdaptingInjection() { ... }, parentContainer)
to force no static injection.



3) What about serialization de-serialization for containers that do or don't
have static injection turned on, and if that could override previous
all-container settings?



Don't know what the current rules for ComponentAdapterFactories are. It
would follow whatever we have already in place since it's just another
ComponentAdapterFactory + InjectionAdapter and explicitly turned on by a
property.



4) Does STATIC_INJECTION as you're designing it, transcend scopes of
containers somewhat ? Or is it a scope in itself that's parent of
"Application scope" (called singleton scope in other containers)?



Well the state mechanism I'm going to use will sit as an instance variable
in a JSRPicoContainer. So if you have:



appScopeContainer.as(Characteristics.STATIC_INJECTION).addComponent(A.class)
;



and



requestScopeContainer.as(Characteristics.STATIC_INJECTION).addComponent(A.cl
ass);



Then the static methods are going to initialize twice.



I have no interest in sharing state between Picocontainers in such a way so
that statics (clearly an edge case and a mediocre one at that) are
guaranteed to initialize only once across multiple containers.



The way I'm designing it will pass the TCK (since it only uses one
container), and I think that's good enough. To completely guarantee
only-once initialization across multiple containers, I think I'd need to
either resort to static state variables in containers. (ICK!), or bytecode
modification to pass the state off to the actually class. I personally
don't think adding a bytecode modification library for an edge case is a
good reason to further bloat Pico.



Additionally, since static initialization is an OPTIONAL feature of the JSR,
I think it's worth it to say we support static initialization with a few
caveats and if the joker that LOVES static initialization gets ticked off @
Picocontainer , so be it. But if some poor sot is stuck with static
initialization because of the code he inherited, I'd say let's be merciful
to him and give him a way to get it done.




-Mike

Loading...