[ TODO ]
Pico 3 is being worked on a github: http://picocontainer.github.com/introduction.html & https://github.com/paul-hammant/picocontainer)
Features in use
- Constructor injection
- Annotated field injection (currently with
@org.picocontainer.annotations.Inject, when PICO-380 is fixed, we can use
- we have a custom
CompositeLifecycleStrategyto work around PICO-381
- we support a
StartableLifecycleStrategy, for components implementing
- we support
- we support a custom
@info.magnolia.objectfactory.AtStartupfor components that need to be started "at startup" (how surprising), as opposed to lazily (i.e when they are requested)
For now, the only
org.picocontainer.ComponentMonitor we use is a logging component, i.e logging what the container is doing (instantiating, etc)
- try picocontainer 3 (an alpha should be released soon)
We currently have two containers:
root container is meant to be used only at startup/shutdown (i.e in
MagnoliaServletContextListener), and should only contain a minimal set of components, necessary to startup the system. Projects which would require customizing the startup procedure (for example using a different resolution mechanism for magnolia.properties files) would override this default set of component by overriding
MagnoliaServletContextListener.populateRootContainer(). I don't think it's worth investing into a more configurable setup for root components, at least until we have a good use-case. (Since one would have to implement such startup components, they might as well override
MagnoliaServletContextListener while they're at it)
main container is populated with all known components (currently from properties, in the future using components registered in module descriptors), module classes, and so on. This container is wrapped in
PicoComponentProvider.getComponent() simply provides instances of known components.
PicoComponentProvider.newInstance() makes sure the request class is not a registered component (to avoid clashes - TBC), creates a temporary container as a child of the current container, registers the request component in it and requests it immediately.
Strings and other "simple" classes
When c2b instantiates components, it now goes through PicoComponentProvider.newInstance. When instantiating, for example, LocaleDefinition, we run into potential issues (if only of performance), because LocaleDefinition has a test-friendly constructor taking 3 Strings. Pico tries to satisfy the greediest constructor, and a such checks if there are candidate for this constructor. I've noticed that, in turn (perhaps this is a flaw in c2b or PicoCP) we're trying to satisfy the java.lang.String constructors. Just found this in the javadoc of
- <li><strong>Force No-Arg constructor usage:</strong> If you wish to force a component to be constructed with
- the no-arg constructor, use a zero length Parameter array. Ex: <code>new Parameter0</code>
Session and request scopes. Containers need to somehow be "swapped".
What/where will we register in these containers ? This is maybe where "composers" might be useful (registered in module descriptors).
- User (scope=session)
- (Web)Context (scope=req)
- The request response and session objets themselves
- ... ?
Components such as rendering models could then depend on such request or session-scoped components.
This could be nice to avoid depending on configuration properties objects and do a look up there.
Instead one could depend on, say
@Named("myProperty") String myProperty.
@Named might for this, but we might want to make it more explicit with, for example
@PropertyConfiguration, which could be a
A quick investigation led me to
org.picocontainer.parameters.ConstantParameter, which is maybe where we'll need to hook up our custom property lookup
Features we could/should use
- Classloader swapping. There's PicoContainer implementation which is able to "juggle" classloaders. To investigate, but could be very useful for the module (down)loader, for example. It also makes use of
org.picocontainer.classname.ClassName, which as far as I can tell, could be useful for use, avoiding "
Class<T> silentForName(String s)". Might require changing a method from private to protected if we want to keep on using our
ClassFactorysystem, or going away from that (see groovy module)
- JMX - see http://permalink.gmane.org/gmane.comp.java.picocontainer.user/1439