I am using CDI 1.2 (Weld 2.3.5) and want to manually instantiate a bean and inject its dependencies during an AfterBeanDiscovery
event listener. I'm expecting that this would allow me to ensure that its Initialization would precede the @PostConstruct
initialization of other beans in the deployment container.
However, I am looking to use a bean declared via @Produces
as a dependency for the bean I am trying to create. According to the BeanManager API doc, I am not allowed to call a BeanManager.getReference()
method during the AfterBeanDiscovery
event. So I find myself a little stuck; I'm not sure if/how I can retrieve/use a dependency declared in the container as a parameter when constructing my bean in my ABD listener.
So far, I have the following:
// Producer bean configuration
@Produces
@CustomConfigType
public CustomConfig auditConfig() {
CustomConfig config = new CustomConfig();
config.setConfigFile("config/myconfig.properties");
config.setDataSource(datasource);
config.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
return config;
}
// CDI Extension
public class CDIBootstrap implements Extension {
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
AnnotatedType<CDICustomConfig> at = bm.createAnnotatedType(CDICustomConfig.class);
// this clearly fails as I am not allowed to use forEach() and retrieve an instance of the CustomConfig as declared using the @Produces annotation. But my goal is to accomplish something like this
CDI.current().select(CustomConfig.class, new AnnotationLiteral<CustomConfigType>(){}).forEach(config -> {
Bean instance = new Bean<CDICustomConfig>() {
@Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(CDICustomConfig.class);
types.add(Object.class);
return types;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
...
// Bolierplate methods
...
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public CDICustomConfig create(CreationalContext<CDICustomConfig> ctx) {
// I would like to use the @Produces bean reference here in the instance constructor
CDICustomConfig instance = new CDICustomConfig(config, config.getDataSource(), config.getResourceAccessor());
it.inject(instance, ctx);
it.postConstruct(instance);
return instance;
}
@Override
public void destroy(CDICustomConfig instance, CreationalContext<CDICustomConfig> ctx) {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
};
abd.addBean(instance);
});
}
I'm still learning how to best leverage the JEE/CDI events and listeners, so perhaps this is not the right approach. Is there anyway to legally do what I am hoping to do? Is there any way to use/access a CDI controlled bean instance from within the ABD event listener?
I'm looking to support multiple @Produces CustomConfig
beans, and generate a CDICustomConfig
for each instance of a CustomConfig bean found in the context. How should I approach this?