Given that:
- I am using Weld as my underlying CDI framework implementation.
- I have a class ClassWithoutControl without a no-arg constructor (a.k.a. not a valid Bean).
- I create a custom Bean for that class.
- I add this bean via an Extension when a AfterBeanDiscovery event is triggered.
- When create(CreationalContext<> ctx) is called on this bean I construct a new instance of class ClassWithoutControl.
- I have created a set of InjectionPoints for that custom Bean.
- One of those InjectionPoints is a field of ClassWithControl.
How do I ensure that CDI will inject an instance of the type required by the InjectionPoint?
In other words, how do I construct a custom bean for a class over which I have no control, in such a way that I can still inject an instance of a class over which I do have control into a particular field?
My current (non-functional) code looks like this:
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager beanManager) {
final AnnotatedType<ClassWithoutControl> annotatedType = beanManager.createAnnotatedType(ClassWithoutControl.class);
AnnotatedField<ClassWithoutControl> annotatedField = null;
for (AnnotatedField<? super ClassWithoutControl> field : annotatedType.getFields()) {
if ("field".equals(field.getJavaMember().getName()) && ClassWithControl.class.equals(field.getJavaMember().getType())) {
annotatedField = (AnnotatedField<ClassWithoutControl>) field;
break;
}
}
final InjectionPoint injectionPoint = beanManager.createInjectionPoint(annotatedField);
final HashSet<InjectionPoint> injectionPoints = new HashSet<>();
injectionPoints.add(injectionPoint);
BiFunction<CreationalContext<ClassWithoutControl>, Bean<ClassWithoutControl>, ClassWithoutControl> creator = (creationalContext, bean) -> {
final InjectionTarget<ClassWithoutControl> injectionTarget = beanManager.createInjectionTarget(annotatedType);
ClassWithoutControl instance = new ClassWithoutControl(this.paramater1, this.parameter2);
injectionTarget.inject(instance, creationalContext);
injectionTarget.postConstruct(instance);
return instance;
};
customBeanBuilder.setInjectionPoints(injectionPoints).setCreator(creator);
final BeanAttributes<ClassWithoutControl> beanAttributes = beanManager.createBeanAttributes(annotatedType);
customBeanBuilder.setBeanAttributes(beanAttributes);
abd.addBean(customBeanBuilder.build());
}
CustomBeanBuilder is a class which creates an instance of CustomBean which extends Bean. The creator BiFunction is called in the create(CreationalContext ctx) function of a CustomBean. The creator's parameters are the CreationalContext as passed to create() and a CustomBean (this).
I know why the above does not work. A NonProducibleInjectionTarget is returned by Weld, since the AnnotatedType that is used by weld to create the InjectionTarget has no no-args constructor. I am however looking for a way that I can do this, without having to depend on Weld's internal implementations. I can't find a way to trick the CDI into accepting my instance of ClassWithoutControl while retraining the ability to inject another instance.
I have looked at https://docs.jboss.org/weld/reference/latest/en-US/html_single/#_wrapping_an_injectiontarget but I do not quite understand how to create such a wrapper. So any help in that direction would be appreciated as well.