Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Weld says "Injection into Listeners is not supported" on Tomcat?

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

like image 964
stackoverflower Avatar asked Nov 13 '13 15:11

stackoverflower


1 Answers

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/

like image 131
stackoverflower Avatar answered Nov 07 '22 08:11

stackoverflower