Here is a workaround I discovered that can inject CDI beans when an application starts.
The requirement of the problem can be summarized as:
- inject a CDI bean when the application starts
- do something with the bean
Solution outline line:
- Create a WebListener that calls
BeanManager.fireEvent(new SomeDummyEvent())
- Create an ApplicationScoped bean that responds to
SomeDummyEvent
and injects the CDI bean
Example code:
@WebListener
public class ApplicationInitialisationListener implements ServletContextListener {
private static final Logger LOG = Logger.getLogger(ApplicationInitialisationListener.class);
@Override
public void contextInitialized(ServletContextEvent event) {
BeanManager beanManager = lookUpBeanManager();
if (beanManager != null) {
beanManager.fireEvent(new SomeDummyEvent());
LOG.info("beanManager fired SomeDummyEvent.");
} else {
LOG.error("beanManager is null. Cannot fire startup event.");
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
public BeanManager lookUpBeanManager() {
try {
// See reference below about how I came up with this
InitialContext iniCtx = new InitialContext();
BeanManager result = (BeanManager) iniCtx.lookup("java:comp/env/BeanManager");
return result;
} catch (NamingException e) {
LOG.error("Could not construct BeanManager.", e);
return null;
}
}
public static class SomeDummyEvent implements Serializable {
}
}
@ApplicationScoped
public class InitializationResourceBean {
private static final Logger LOG = Logger.getLogger(InitializationResourceBean.class);
@Inject
HealthCheck healthCheck;
public void listen(@Observes ApplicationInitialisationListener.SomeDummyEvent event) {
}
@PostConstruct
public void init() {
// Do something with healthCheck
}
@PreDestroy
public void destroy() {
// Do some other thing with healthCheck
}
}
References: