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

3

7

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

Contractile answered 13/11, 2013 at 15:25 Comment(3)
As for question 3: Note that the message says it it not supported by CDI i.e. the CDI spec doesn't define that. This might be added to a future version and thus to any version of Weld which implements that future CDI version.Calumet
@Calumet CDI isn't specific to servlets so it won't define anything related to injecting in a Java EE environment. This is a weld and JSR 299 feature .Fugato
@SotiriosDelimanolis ah, yes you're right. συγνώμη :)Calumet
C
1

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/

Contractile answered 21/11, 2013 at 12:34 Comment(0)
B
0

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

Bauble answered 20/2, 2014 at 12:10 Comment(0)
S
0

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?

Shantelleshantha answered 16/9, 2015 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.