Hi Antoine
there are many things in your post. I just start picking one also lets see if other add their cents... ;-)
One thing that would be very nice, if I could programmatically bootstrap my container. This would be very easy to define the features I need and additionally also is very useful for mocking. Given your ideas above and the proposed high level componentization I see similarities with other containers, where I basically require two aspects:
- a way to define components (and optionally perhaps also modules)
- a way of controlled explicit interaction between them (synchronously or asynchronously)
So looking at your proposal I would see something like
- a container managing modules, whereas modules exist exactly once per container (I know OSGI also has versioning support here, but maybe we should keep it simple here)..
- the container should provide some interfaces to register additional modules.
- modules can expose components (beans), either statically or contextually.
- the event layer basically is also nothing more than a shared module, providing synchronous and asynchronous communication features.
- also interception and decoration can be seen as another module.
- basic DI basically is nothing more than a module that scans the classpath for components and auto-registers them. So basic DI knows about classes, constructors, methods, annotations etc. Hereby basic DI can define some interception mechanisms to intercept injection.
- contextual aspects could be added as a module that implements these interception mechanism.
So given that I coud write something like this:
CDI container = new CDI.Builder().addModules(CDIInitialConfig.class, EventServices.class, ComponentContainer.class, InterceptionServices.class, DIScanner.class,
ContextualServices.class).create();
Hereby the modules can be easily used as adapters, so the CDI container can also be programmatically configured. Given that I could for example easily setup a minimal container, even without component scanning:
Container container = new Container.Builder().addModules(CDIInitialConfig.class, EventServices.class, ComponentContainer.class)
.loadModules().create();
ComponentContainer compCont = container.getModule(ComponentContainer.class);
compCont.addPackage("com.mycomp.test").addBeans(MyBean.class, MyMockedBean.class, MyBean2.class);
compCont.startup();
The above would allow me to setup very lean and modular containers as required, and also be able to share them across multiple ears/web applications in a EE context. A similar mechanism could be used to combine containers, e.g.
Container container2 = new Container.Builder().addModules(CDIInitialConfig.class, EventServices.class, ComponentContainer.class)
.loadModules().create();
ComponentContainer compCont = container.getModule(ComponentContainer.class).addParentContainer(container);
container2.startup();
Summarizing we would get an incredible flexible container. Many of the features, e.g. the Service SPI in Weld would basically match these concepts. Beside that this infrastructure would allow us to build up a configuration layer in an early system stage, it would also greatly simplify testing, because I could easily create the runtime container as needed for my tests. Beside a common contract for modules, each module can define its own API, e.g. the ComponentContainer.class can provide meta-data on the components known, ...
Of course, thinking on such things requires several other topics to be considered like classloader isolation or modules/component isolation in general. Also versioning of modules/components could be a topic, but it is arguable if we really want to rebuild thw whole OSGI ;-) Beside that I think the basic complexity should be manageable. What also would be considered is backward compatibility...
And of course, such a flexible container infrastructure would also be usable on small devices and as a base for configuration...
So these are my spontanous ideas. Hope other will also provide their cents (e.g. Antonio ;-) ).
Best,
Anatole