Assisted injection - I have a working prototype, but...
steappe Nov 18, 2016 7:11 AMI'm currently in the process of integrating a DI framework in an old Java SE legacy application. As you can imagine, this application has many classes with multiple constructors that are not eligible for injections. As we want to minimize the redesign of the application (because we want to minimize the development cost of the DI integration), these legacy constructs are a real problem with CDI. Another approach of course could be to use Guice, which is a pretty good framework in such a situation. But I don't like much the bootstrapping effort required with Guice. The programmatic binding of managed beans is just a pain, and I'm not talking about the future maintenance of it, especially in case where some dependencies between beans would have to be changed for some reasons. By the way, I'd love to hear about solid arguments for and against Guice, so I can make the right choice.
For the sake of a smooth integration, I've just implemented a CDI portable extension for the support of assisted injection, just like we can do with Guice:
- The bean is annotated with an AssistedInject annotation that specifies the class of the factory interface that must be use to create the bean, and behind the scene that will be used to call the bean's constructor.
- The constructor of the bean can have unmanaged parameters, and they are annotated with an Assisted annotation.
The CDI portable extension proceeds as follows:
- During the ProcessAnnotatedType event, it creates a Contextual Bean that acts as a producer of a dynamically created instance of the factory interface specified in the AssistedInject annotation.
- It registers each of these Contextual Bean producers during the AfterBeanDiscovery event. Therefore, the factories specified in the AssistedInject annotations are eligible for injection in other beans.
- When any of these factories is injected, a proxy is dynamically created and is associated to the constructor of the bean.
- When the factory method of the factory is called, the constructor of the bean is invoked with the arguments specified by the application.
This works pretty well, and I can even have bean constructors with a mixed of unmanaged and managed parameters (the managed parameters are injected by CDI).
However, I have at least three problems left that I know so far:
- Observer methods of the bean are not scanned, probably because the bean is not a managed bean. These beans cannot receive events.
- I've scanned the observer methods myself, and I've added them to CDI during the AfterBeanDiscovery event, but still the observer methods are not called.
- I'd love to add the beans in some context, with a dependent scope, and I don't know how to do that.
One idea I have to solve these issues is to dynamically create producers for the unmanaged parameters of the bean's constructor, and annotate the bean's constructor with Inject.
I can produce the source code of the prototype (I will probably host it on GitHub soon), if it can help in the discussion.
Thanks in advance for all the tips and suggestions you would provide to me to help me with the remaining problems, including but not limited to considering another approach.