0

I have referred to a very helpful previous post but facing a different issue while injecting a bean in a ServletContextListener

The Listener

    package sapphire.social.connector.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.context.support.WebApplicationContextUtils;

import sapphire.adapter.youtube.YTConnectorMgr;
import sapphire.social.connector.logger.LogManager;

public class AppServletContextListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        if (LogManager.isDebugOn()) {
            LogManager
                    .debug("AppServletContextListener ::: contextDestroyed :::");
        }

    }

    @Override
    public void contextInitialized(ServletContextEvent initializingEvent) {
        // TODO Auto-generated method stub
        if (LogManager.isDebugOn()) {
            LogManager
                    .debug("AppServletContextListener ::: contextInitialized :::");
        }

        if (LogManager.isDebugOn()) {
            LogManager
                    .debug("AppServletContextListener ::: contextInitialized ::: WebApplicationApplicationContext : "
                            + WebApplicationContextUtils
                                    .getWebApplicationContext(initializingEvent
                                            .getServletContext()));
        }

        if (LogManager.isDebugOn()) {
            LogManager
                    .debug("AppServletContextListener ::: contextInitialized ::: RequiredWebApplicationApplicationContext : "
                            + WebApplicationContextUtils
                                    .getRequiredWebApplicationContext(initializingEvent
                                            .getServletContext()));
        }

        YTConnectorMgr ytConnectorMgr = (YTConnectorMgr) WebApplicationContextUtils
                .getWebApplicationContext(initializingEvent.getServletContext())
                .getAutowireCapableBeanFactory()
                .autowire(YTConnectorMgr.class,
                        AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);

        if (LogManager.isDebugOn()) {
            LogManager
                    .debug("AppServletContextListener ::: contextInitialized ::: ytConnectorMgr : "
                            + ytConnectorMgr);
        }
    }
}

The web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">


    <!-- <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/sapphire-security.xml</param-value>
    </context-param> -->

    <listener>
        <listener-class>sapphire.social.connector.listener.AppServletContextListener</listener-class>
    </listener>

    <servlet>
    <servlet-name>central-config</servlet-name>
        <servlet-class>
                  org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>central-config</servlet-name>
        <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

central-config-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:component-scan base-package="sapphire" />

    <mvc:annotation-driven />


    <!-- Start : To by-pass MVC view resolution and pass the response to appropriate 
        media type view resolvers/views Deprecated approach since Spring 3.2.x -->
    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="favorPathExtension" value="false"></property>
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="text/xml" />
                <entry key="htm" value="text/html" />
            </map>
        </property>
        <property name="viewResolvers">
            <list>
                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
                <bean
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/views/" />
                    <property name="suffix" value=".jsp" />
                </bean>
            </list>
        </property>
        <!-- <property name="defaultContentType" value="application/json" /> <property 
            name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" 
            /> </list> </property> -->
    </bean>
    <!-- End : To by-pass MVC view resolution and pass the response to appropriate 
        media type view resolvers/views Deprecated approach since Spring 3.2.x -->


    <task:scheduler id="scheduler" pool-size="5" />

    <task:annotation-driven scheduler="scheduler" />

</beans>

I attempted to retrieve both WebApplicationContext and Required WebApplicationContext - the former came null and the latter requires a ContextLoaderListener

Fri Nov 15 12:05:55 IST 2013 [Thread-2] AppServletContextListener ::: contextInitialized :::
Nov 15, 2013 12:05:55 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class sapphire.social.connector.listener.AppServletContextListener
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:84)
    at sapphire.social.connector.listener.AppServletContextListener.contextInitialized(AppServletContextListener.java:44)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Nov 15, 2013 12:05:55 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
Nov 15, 2013 12:05:55 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/Sapphire] startup failed due to previous errors
Fri Nov 15 12:05:55 IST 2013 [Thread-2] AppServletContextListener ::: contextInitialized ::: WebApplicationApplicationContext : null
Fri Nov 15 12:05:55 IST 2013 [stop children - Catalina:j2eeType=WebModule,name=//tenantarchtst.lntinfotech.com/Sapphire,J2EEApplication=none,J2EEServer=none] AppServletContextListener ::: contextDestroyed :::
Nov 15, 2013 12:05:55 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8081"]
Nov 15, 2013 12:05:55 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8010"]
Nov 15, 2013 12:05:55 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 15184 ms

Just for reference, giving the bean that I want to inject in the ServletContextListener :

@Component(value = "YTConnectorMgr")
public class YTConnectorMgr extends ConnectorMgr {

    private static int maxWorkerThreads = 5;

    public YTConnectorMgr(int maxWorkerThreads, ConnectorType connectorType) {
        super(maxWorkerThreads, connectorType);
    }

}

I'm having a single config xml file which is taken care by the DispatcherServlet - ideally, I don't require a ContextLoaderListener! But even this previous post dictates the use of a ContextLoaderListener. As pointed by M.Deinum, I should NOT be duplicating my beans !!!

Community
  • 1
  • 1
Kaliyug Antagonist
  • 3,512
  • 9
  • 51
  • 103
  • 1
    You are aware that you are loading the configuration twice, effectively duplicating all of your beans??? (Both the `ContextLoaderListener` and `DispatcherServlet` construct and application context containing everything from **central-config-servlet.xml**. Instead of `getWebApplicationContext` try `getRequiredWebApplicationContext`. The logic in there makes me wonder why aren't you simply registering this bean in the `ApplicationContext` and use `@Scheduled`? – M. Deinum Nov 14 '13 at 09:47
  • @M.Deinum Actually, I hadn't configured the ContextLoaderListener initially as it made no sense but I guess it is required to retrieve the WebApplicationContext. Have edited my question and posted the exception too - can u have a look? – Kaliyug Antagonist Nov 15 '13 at 06:43
  • 1
    If you want a ServletListener to access an ApplicationContext it will only be able to access the root context. And the ContextLoaderListener needs to be loaded/registered **before** your own listener (else the context isn't created yet). But why are you making things so complex? Simply use dependency injection. Add fields to your `ServletContextListener` annotate those with `@Autowired` and instead of doing lookups simply call `configureBean` with your current instance of the `ServletContextListener`. Saves you all the ugly `getInstance` methods and you are basically leveraging spring. – M. Deinum Nov 15 '13 at 08:08
  • @M.Deinum Err... I couldn't figure out 'instead of doing lookups simply call configureBean with your current instance of the ServletContextListener'. Yes, I will remove the static stuff etc. from the YTConnector but a plain Autowired inServletContextListener will fail ! – Kaliyug Antagonist Nov 15 '13 at 11:37
  • No it won't you just have to call the correct methods. Make sure that your `ContextLoaderListener` is configured before your `AppServletContextListener`. The latter contains `@Autowired` annotated fields. Now in your `contextInitialized` simply call `autowire(this)` (instead of the `YTConnectorMgr`). This will inject the dependencies into your listener. But I still wonder why do you need this listener? What is so special about it that you cannot use the ApplicationContext to wire everything together? – M. Deinum Nov 15 '13 at 17:26
  • That is what my next question was gonna be! Actually, I'm new to Spring and was wondering if the context listener can be given up altogether and have something SIMILAR that initializes rest of the required beans at the application start-up itself !!! – Kaliyug Antagonist Nov 17 '13 at 06:30

1 Answers1

0

you may need use @Autowired to injecting beans : try

@Autowired
private ScheduledThreadPoolExecutor executor;
@Autowired
private ScheduledFuture scheduledFuture;
sirk
  • 1
  • I didn't get u - I'm getting NPE for the bean factory and that is where I'm stuck! How does auto-wiring the above instances help ??? – Kaliyug Antagonist Nov 14 '13 at 05:23
  • I'm so sorry,I didn't see your question clearly before.I tried later,foud that was strange,I wrote a small demo from your code above,it worked!here is the demo (http://dropbox.com/s/2pslys0wrflp8w2/webtest.rar) ---,you can try it. – sirk Nov 15 '13 at 02:39