0

So my head really hurts - I have read about Role/Purpose of ContextLoaderListener in Spring and I cannot go one step further.

I have a really old project and I'm upgrading it. So far I've managed to bring it from spring 2.x to spring 4.x and from Java 7 to Java 8, but I stuck on running application on tomcat 8. It loades ContextLoaderListener twice!? On tomcat 7 starts without problem.

Tomcat 7: apache-tomcat-7.0.29

Tomcat 8: apache-tomcat-8.5.11

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC 
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"     
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
               http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>VERSION-1.7.1</display-name>

    <context-param>
        <param-name>listenPort_http</param-name>
        <param-value>80</param-value>
    </context-param>
    <context-param>
        <param-name>listenPort_https</param-name>
        <param-value>8443</param-value>
    </context-param>

    <context-param>
        <param-name>daoType</param-name>
        <param-value>ibatis</param-value>
    </context-param>

    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>ApplicationResources</param-value>
    </context-param>

    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
        <param-value>en</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:META-INF/applicationContext-*.xml
            /WEB-INF/applicationContext-*.xml
        </param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
        <param-value>false</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.CONFIG_FILES</param-name>
        <param-value>
            /WEB-INF/faces-specification-config.xml,
            /WEB-INF/faces-operating-config.xml,
            /WEB-INF/faces-popup-config.xml,
            /WEB-INF/faces-mabr-config.xml
        </param-value>
        <description></description>
    </context-param>

    <filter>
        <filter-name>clickstreamFilter</filter-name>
        <filter-class>com.opensymphony.clickstream.ClickstreamFilter</filter-class>
    </filter>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>rewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
    </filter>
    <filter>
        <filter-name>exportFilter</filter-name>
        <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
    </filter>
    <filter>
        <filter-name>uploadExtensionsFilter</filter-name>
        <filter-class>
            org.apache.myfaces.webapp.filter.ExtensionsFilter
        </filter-class>
        <init-param>
            <param-name>uploadMaxFileSize</param-name>
            <param-value>10m</param-value>
        </init-param>
        <init-param>
            <param-name>uploadThresholdSize</param-name>
            <param-value>100k</param-value>
        </init-param>
    </filter>

    <filter>
        <filter-name>compressionFilter</filter-name>
        <display-name>Compression Filter</display-name>
        <filter-class>org.opendls.webapp.filter.GZIPFilter</filter-class>
    </filter>
    <filter>
        <filter-name>mySecurityFilter</filter-name>
        <display-name>Security Filter</display-name>
        <filter-class>org.opendls.webapp.filter.MySecurityFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>mySecurityFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>mySecurityFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>clickstreamFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>exportFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>compressionFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>uploadExtensionsFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>com.opensymphony.clickstream.ClickstreamListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.opendls.webapp.listener.StartupListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.SessionListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.ShutdownListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.opendls.webapp.listener.UserCounterListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>faces</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>wsit-jaxws-fromjava</servlet-name>
        <display-name>wsit-jaxws-fromjava</display-name>
        <description>JAX-WS endpoint - fromjava</description>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>faces</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>wsit-jaxws-fromjava</servlet-name>
        <url-pattern>/webservices/*</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>1440</session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <error-page>
        <error-code>500</error-code>
        <location>/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>400</error-code>
        <location>/index.jsp</location>
    </error-page>
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/viewExpired.jsp</location>
    </error-page>

    <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/primary</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/secondary</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>


</web-app>

StartupListener.java

public class StartupListener extends ContextLoaderListener
implements ServletContextListener {

    private static final Log log = LogFactory.getLog(StartupListener.class);

    public void contextInitialized(ServletContextEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("initializing context...");
        }

        super.contextInitialized(event);

        ServletContext context = event.getServletContext();
        String daoType = context.getInitParameter(Constants.DAO_TYPE);

        // if daoType is not specified, use DAO as default
        if (daoType == null) {
            log.warn("No 'daoType' context carameter, using hibernate");
            daoType = Constants.DAO_TYPE_HIBERNATE;
        }

        // Orion starts Servlets before Listeners, so check if the config
        // object already exists
        Map config = (HashMap) context.getAttribute(Constants.CONFIG);

        if (config == null) {
            config = new HashMap();
        }

        // Create a config object to hold all the app config values
        config.put(Constants.DAO_TYPE, daoType);
        context.setAttribute(Constants.CONFIG, config);

        // output the retrieved values for the Init and Context Parameters
        if (log.isDebugEnabled()) {
            log.debug("daoType: " + daoType);
            log.debug("populating ...");
        }
        setupContext(context);        
    }    

    public static void setupContext(ServletContext context) {
        ApplicationContext appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);

        RightsManager rightsManager = (RightsManager) appContext.getBean("rightsManager");

        context.setAttribute(Constants.AVAILABLE_ROLES, rightsManager.getAllRights());

        if (log.isDebugEnabled()) {
            log.debug("initialization complete [OK]");
        }        
    }      
}

I have tried many things on web.xml and StartupListener.java but I couldn't manage to load ContextLoaderListener only once. I am getting the same error over and over again:

Error:

27-Jan-2017 02:25:29.217 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log No Spring WebApplicationInitializer types detected on classpath
27-Jan-2017 02:25:30.071 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Initializing Spring root WebApplicationContext
27-Jan-2017 02:25:33.060 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.opendls.webapp.listener.StartupListener
 java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:297)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.opendls.webapp.listener.StartupListener.contextInitialized(StartupListener.java:48)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4725)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5189)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:952)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1823)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

27-Jan-2017 02:25:33.071 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
27-Jan-2017 02:25:33.075 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
27-Jan-2017 02:25:33.405 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized()
27-Jan-2017 02:25:33.407 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log SessionListener: contextInitialized()

where is the problem?

atoha
  • 81
  • 4
  • It doesn't say the contextloaderlistener is executed twice it only states that there already is an `ApplicationContext` registered as root context. So there is another component (probably detected through annotation scanning or implementing `ServletContainerInitializer` or due to having a `web-fragment.xml` which contains something triggering the load. Check your jars for such files. – M. Deinum Jan 27 '17 at 07:04
  • I see two jars which implement ServletContainerInitializer: `spring-framework-4.3.5.RELEASE/libs/spring-web-4.3.5.RELEASE.jar!/org/springframework/web/SpringServletContainerInitializer.class` `myfaces-2.1.10/lib/myfaces-impl-2.1.10.jar!/org/apache/myfaces/ee6/MyFacesContainerInitializer.class` Is this what makes a problem? But what should I do if I need that jars? – atoha Jan 30 '17 at 11:27
  • You are guessing... Apparently you are using frameworks and technologies for which you need to learn some basics firsts. But to answer your question on the comment no that isn't the problem. – M. Deinum Jan 30 '17 at 11:39
  • Yeah, you are right. I am very new in this area but I would love to find a path to solve this problem. Could you please give a hint where to check and how to check? – atoha Jan 30 '17 at 12:02

1 Answers1

0

ok - the problem is resolved

as M.Denim mentioned there were some duplicate listeners which was triggering the same ApplicationContext to load.

There was .tld file in WEB-INF which was containing the same listeners which was in web.xml, the file was created by ant task. A new implementation of Tomcat 8.x read them as noPluggabilityListeners and load was triggered second time.

atoha
  • 81
  • 4