Автовайринг в слушатель. Падает web app. Spring MVC + Servlet Listeners

Рейтинг: 0Ответов: 1Опубликовано: 17.04.2015

Не получается инжектировать Bean в слушатель сесии.

Есть бин-конфигуратор.

@Configuration(value = "battleshipBeans")
public class BattleshipBeansConfiguration {
   ...много разных бинов-бобов.
}

Мне нужно инжектировать этот бин-конфигуратор этот в слушатель

public class HttpSessionDestroyed implements HttpSessionListener{

    @Resource(name = "battleshipBeans")
    private BattleshipBeansConfiguration battleshipBeans;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
    }
}

А также в файле web.xml объявил сам слушатель:

<listener>
    <description>HttpSessionListener</description>
    <listener-class>com.pack.battleship.web.controller.HttpSessionDestroyed</listener-class>
</listener>

Погуглив, нашёл раз , и два. Это очень красиво и то, что нужно. Пробовал оба способа - вставляю код который я нашёл по ссылкам в метод sessionDestroyed, именно этот метод мне нужен, но у меня приложение падает отказывается запускаться вовсе. Пробовал реализовывать ServletContextListener как в тех примерах и вставлял код в метод contextInitialized но и это непомогло.

17-Apr-2015 13:20:44.461 INFO [http-nio-8080-exec-6] org.apache.catalina.core.ApplicationContext.log No Spring WebApplicationInitializer types detected on classpath
17-Apr-2015 13:20:44.601 SEVERE [http-nio-8080-exec-6] org.apache.catalina.core.StandardContext.listenerStart Error configuring application listener of class com.pack.battleship.web.controller.HttpSessionDestroyed
 javax.naming.NamingException: Cannot create resource instance

Почему?

Ответы

▲ 1Принят
public class HttpSessionDestroyed implements HttpSessionListener {

    private BattleshipBeansConfiguration battleshipBeans;

    public void sessionCreated(HttpSessionEvent event) {

        if (battleshipBeans == null)
            obtainBattleshipBeans(event);
        ...
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        if (battleshipBeans == null)
            obtainBattleshipBeans(event);
        ...
    }

    private void obtainBattleshipBeans(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
        battleshipBeans = (BattleshipBeansConfiguration) ctx.getBean("battleshipBeans");
    }

}

web.xml

...
   Spring's ContextLoaderListener
...

<listener>
    <listener-class>
        com.pack.battleship.web.controller.HttpSessionDestroyed
    </listener-class>
</listener>

Начиная с Servlet 3.0 ServletContext имеет метод addListener. Вместо добавления слушателя в web.xml можно сделать так.

@Component
public class MyHttpSessionListener implements javax.servlet.http.HttpSessionListener, ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof WebApplicationContext) {
        ((WebApplicationContext) applicationContext).getServletContext().addListener(this);
        } else {

            throw new RuntimeException("Должен быть внутри контекста веб приложения");
        }
    }           
}

После чего слушатель будет зарегистрирован в контексте приложения.

Нет возможности проверить этот способ, т.к. пока нет проектов с Servlet 3.0