Issue
I have a web project using Resteasy (which in turn uses Weld) and is deployed to Tomcat 7.0.22 (I put the specific version here in case this issue is particular to this version).
I have a ServletContextListener that looks like this:
@WebListener
public class ApplicationInitialisationListener implements ServletContextListener {
// create a logger here
@Inject
HealthCheck healthCheck;
@Override
public void contextInitialized(ServletContextEvent event) {
if (healthCheck == null) {
log.error("healthCheck is null");
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
After deploying to Tomcat, healthCheck is null
was logged, and I also noticed this line in the log:
<2013-11-13 13:27:40,191> <pack> INFO pool-2-thread-1 org.jboss.weld.environment.tomcat7.Tomcat7Container - Tomcat 7 detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported
Question 1: why is CDI injection not available in Listeners?
I looked into this answer, and it says Load on startup via @Startup. There is currently no equivalent to this in CDI.
Question 2: is the issue described in Question 1 a consequence of this?
Question 3: I am using org.jboss.weld.servlet:weld-servlet:1.2.0.Beta1
. Is there any update on startup support in later versions?
Related Questions I Looked startup class in Weld
Solution
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:
http://struberg.wordpress.com/tag/cdi/
Answered By - stackoverflower