Home > Back-end >  spring dependency injection is not working in a class annotated with @WebListener
spring dependency injection is not working in a class annotated with @WebListener

Time:11-02

I tried constructor based Dependency injection in TestAppListener class which implements ServletContextListener. I got this error Exception sending context initialized event to listener instance of class [com.example.listener.TestAppListener].

I searched stack overflow but I couldn't find any solution for this scenario. Please any one help me in sort out this. I placed Implementation classes in META-INF.services folder also. My understanding is there is some problem in constructor dependency injection but this way of DI is need for my situation, because in real time I want to create datasource connection inside startup method.

Find all my classes below which i'm using,

@WebListener
public class TestAppListener implements ServletContextListener {

private static TestDao dao;

public TestAppListener(TestDao dao){
    this.dao = dao;
}
public TestAppListener(){}

@Override
public void contextInitialized(ServletContextEvent sce) {
    dao = ServiceLoader.load(TestDao.class).iterator().next();
    dao.startUp();
    System.out.println("Context initialized method called");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
    System.out.println("Context destroyed method called");
    dao.shutDown();
}

}

public interface TestDao {

void startUp();

void shutDown(); 

}

public class TestDaoImpl implements TestDao {
@Override
public void startUp() {
    System.out.println("Database is initialized");
}

@Override
public void shutDown() {
    System.out.println("Database is initialized");
}

}

@Configuration
public class SpringConfig {

public SpringConfig() {
}

@Bean
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
    ServletListenerRegistrationBean<ServletContextListener> bean = new ServletListenerRegistrationBean<>();
    bean.setListener(new TestAppListener());
    return bean;
}

}

CodePudding user response:

Change private static TestDao dao to private final TestDao dao. Spring doesn't allow statics to be used as targets for injection. Also, your TestDaoImpl class needs to be a component or a bean defined in a Spring configuration file.

CodePudding user response:

The Servlet @WebListeners are handled by Servlet containers(tomcat/Jetty) when the container is starting. So they know nothing about Spring.

For more details, see discussion in this issue.

A workaround solution is replace the @WebListener with Spring's @Component, thus you can inject Spring beans(declare your Dao as spring beans) into the listeners directly.

BTW, you have to add @ServletComponentScan on your Spring Boot application class to activate it.

I created an example project to demo @WebServlet, @WebFilter and @WebListener.

  • Related