Question

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

Was it helpful?

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:

  1. inject a CDI bean when the application starts
  2. do something with the bean

Solution outline line:

  1. Create a WebListener that calls BeanManager.fireEvent(new SomeDummyEvent())
  2. 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/

OTHER TIPS

From: http://docs.jboss.org/weld/reference/latest-master/en-US/html/environments.html#_tomcat

"Tomcat 7 and 8 are supported. Context activation/deactivation and dependency injection into Servlets and Filters works out of the box. Injection into Servlet listeners works on Tomcat 7.0.50 and newer."

So perhaps you can upgrade your Tomcat?

Now, all this is much easy to do with deltaspike servlet module

@ApplicationScoped
public class InitializationResourceBean {

 @Inject
 HealthCheck healthCheck;

  public void onCreate(@Observes @Initialized ServletContext context) {
    //Do initialisation stuff here.
    if(HealthCheck != null) {
      ;
    }
  }
  public void onDestroy(@Observes @Destroyed ServletContext context) {
    System.out.println("Destroyed ServletContext: " + context.getServletContextName());
  }

}

http://deltaspike.apache.org/documentation/servlet.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top