I have some beans (of multiple types, CDI, @Stateless
and @Singleton
beans). Some of their fields shall get injected from database values.
public class MyBean {
@Inject
@DbConfigValue(MyConfig.HOST)
String host;
}
So I added a custom @Qualifier
(DbConfigValue
) used by a Producer. The producer reads and caches config values from a database and injects them into the beans.
@Singleton
@Lock(LockType.READ)
public class Configuration {
@Produces
@Dependent
@DbConfigValue
public String getDbConfigValue(InjectionPoint point) {
// get key for the config-value from qualifier-annotation of the injected field
String key = point.getAnnotated().getAnnotation(DbConfigValue.class).value();
// i have read+cached database config values in @PostConstruct before
return cachedConfigValues.get(key);
}
}
This works well for initial injection / bean construction. Some web tutorials out there are suggesting this approach.
Now, I think it is reasonable to assume that config values, if stored in DB, might change at runtime. So, whenever an admin changes a database config value, I currently do fire a CDI-event.
Question: is there any way to re-inject values into fields of already-initialized bean-instances? Or is injection always related to instance-creation only?
E.g. I had s.th. similar to this in mind:
public class MyEventListener {
@Inject
BeanManager beanManager;
@Asynchronous
public void onDbConfigValueChangedEvent (@Observes(during = TransactionPhase.AFTER_SUCCESS) DbConfigValueChangedEvent event) {
try {
// could be filtered by custom qualifier:
Set<Bean<?>> beans = beanManager.getBeans(Object.class,new AnnotationLiteral<Any>() {});
for (Bean<?> bean : beans) {
Set<InjectionPoint> points = bean.getInjectionPoints();
// What now? javax.enterprise.inject.spi.Bean is the
// bean-representation only.
// Can I somehow resolve the actual bean-instances here?
// Then update Field via Reflection?
}
}
catch(Exception e){
// ...
}
}
}
I also considered DeltaSpike which has some methods for injection-control. However, I did only find methods to inject into new bean instances, or even with new- or null-CreationalContexts (beans not CDI-managed afterwards)
Please note: I am aware that I can solve this specific use-case by injecting the configuration and explicitly getting the current values on each request like this:
public class MyBean {
@Inject
Configuration config;
public void someMethod(){
String host = config.getConfig(MyConfig.HOST);
// ...
}
}
However, I am wondering about the question in general: is there any support for re-injection? Or if not, do the specs (CDI or Java EE) forbid it?