1
votes

The Situation

I'm working on a group web project which uses the Spring framework. We need to use a custom ANT script to build the project for use in continuous integration. Currently, I'm trying to compile the project using a custom ANT target, but I keep running into an error.

The Error

Summary:

SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener
    java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

Full:

15-Feb-2011 9:47:36 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4148)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4704)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:563)
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1397)
    at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:297)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
    at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1500)
    at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:252)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:563)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

Relevant Portions of the Build Script

This is the build script we're currently using. We are calling the "dist" target. Extraneous targets (test, doc, smoke-test, tomcat-start, tomcat-stop, etc.) have been omitted.

<!-- ******************************************************************* -->
<!-- * Project Home Directories                                        * -->
<!-- ******************************************************************* -->
<!-- * We should include most dependancy jars in the repository.       * -->
<!-- ******************************************************************* -->

<!-- Override this with "ant -Dconf.home=./conf.example deploy" -->
<property name="conf.home" value="${basedir}/conf/local" />

<!-- Load the build environment properties -->
<property file="${conf.home}/build.properties"/>

<!-- ******************************************************************* -->
<!-- * Classpath Parameters                                            * -->
<!-- ******************************************************************* -->
<!-- * The different classpaths that are used in the build process.    * -->
<!-- ******************************************************************* -->

<path id="log4j.classpath">
    <fileset dir="${log4j.home}" id="log4j.files" includes="log4j-1.2.8.jar"/>
</path>
<path id="dist.classpath">
    <pathelement location="${dist.home}"/>
</path>
<path id="bin.classpath">
    <pathelement location="${bin.home}"/>
</path>
<path id="json-simple.classpath">
    <fileset dir="${json-simple.home}" id="json-simple.files" includes="json_simple-1.1.jar"/>
</path>
<path id="cas.classpath">
    <fileset dir="${cas.home}">
        <include name="cas.jar"/>
        <include name="casclient.jar"/>
    </fileset>
</path>
<path id="jdbc.classpath">
    <fileset dir="${jdbc.home}" id="jdbc.files">
        <include name="mysql-connector*.jar"/>
    </fileset>
</path>
<path id="tomcat.classpath">
    <fileset dir="${tomcat.home}" id="tomcat.files">
        <include name="catalina-ant.jar"/>
        <include name="servlet-api.jar"/>
    </fileset>
</path>
<path id="ant-contrib.classpath">
    <fileset dir="${ant-contrib.home}" id="ant-contrib.files">
        <include name="ant-contrib-0.6.jar"/>
    </fileset>
</path>
<path id="sysUtil.classpath">
    <fileset dir="${sysUtil.home}" id="sysUtil.files">
        <include name="ca.usask.cs.sysUtil.jar"/>
    </fileset>
</path>
    <!-- TODO FIXME added by Dylan. Clean as necessary! -->
<path id="junit.classpath">
    <fileset dir="${junit.home}" id="junit.files">
        <include name="junit-4.8.2.jar"/>
    </fileset>
</path>
<path id="lib.classpath">
    <pathelement location="${lib.home}"/>
</path>
<path id="test.classpath">
    <pathelement location="${test.home}"/>
</path>
<path id="selenium.rc.classpath">
    <fileset dir="${selenium.rc.home}" id="selenium.rc.files">
        <include name="selenium-java-client-driver.jar"/>
    </fileset>
</path>
<path id="spring.classpath">
    <fileset dir="${spring.home}" id="spring.files">
        <include name="spring*.jar"/>
    </fileset>
</path>

<!-- ******************************************************************* -->
<!-- * Task Definitions                                                * -->
<!-- ******************************************************************* -->
<!-- * This area identifies the external ant tasks that we want to be  * -->
<!-- * able to use.  Of particular interest are the tomcat tasks,      * -->
<!-- * which can be used for automatic deployment, as well as the      * -->
<!-- * ant-contrib tasks which contain additional useful ant routines. * -->
<!-- ******************************************************************* -->

<taskdef name="tomcat-stop" classname="org.apache.catalina.ant.StopTask">
    <classpath refid="tomcat.classpath"/>
</taskdef>
<taskdef name="tomcat-start" classname="org.apache.catalina.ant.StartTask">
    <classpath refid="tomcat.classpath"/>
</taskdef>
<taskdef name="tomcat-deploy" classname="org.apache.catalina.ant.DeployTask">
    <classpath refid="tomcat.classpath"/>
</taskdef>
<taskdef name="tomcat-undeploy" classname="org.apache.catalina.ant.UndeployTask">
    <classpath refid="tomcat.classpath"/>
</taskdef>
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
    <classpath refid="ant-contrib.classpath"/>
</taskdef>

<!-- ******************************************************************* -->
<!-- * Targets                                                         * -->
<!-- ******************************************************************* -->
<!-- * The meat of the ant build file, each target is an action that   * -->
<!-- * you want to be able to perform.                                 * -->
<!-- ******************************************************************* -->
<target name="clean"
    description="Removes the built classes." >
    <delete dir="${dist.home}" />
    <delete dir="${admin.home}" />
</target>

<target name="build"
    depends="clean"
            description="Builds class tree from sources." >
    <mkdir dir="${bin.home}"/>
    <javac source="1.6" debug="true" deprecation="true"
                    destdir="${bin.home}" fork="true" srcdir="${src.home}"
                                            includeantruntime="false">
        <classpath refid="tomcat.classpath"/>
        <classpath refid="cas.classpath"/>
        <classpath refid="log4j.classpath"/>
        <classpath refid="json-simple.classpath" />
        <classpath refid="sysUtil.classpath"/>
        <classpath refid="jdbc.classpath"/>
        <classpath refid="spring.classpath"/>
    </javac>
</target>

<target name="dist"
    depends="build"
    description="Creates war archive to deploy application" >
    <!-- Copy configuration files into classes dir (so they're in the classpath) -->
    <copy overwrite="yes" todir="${dist.home}/WEB-INF/classes">
        <fileset dir="${conf.home}" includes="application.properties" />
        <fileset dir="${conf.home}" includes="log4j.properties" />
    </copy>

<!-- Copy context.xml to META-INF -->
    <copy overwrite="yes" file="${conf.home}/context.xml" tofile="${dist.home}/META-INF/context.xml" />

<!-- Copy web.xml to WEB-INF -->
    <copy overwrite="yes" file="${conf.home}/web.xml" tofile="${dist.home}/WEB-INF/web.xml" />

<!-- Copy *some of the* libraries into lib dir -->
    <copy overwrite="yes" todir="${dist.home}/WEB-INF/lib">
        <fileset dir="${cas.home}" includes="**/*" />
        <fileset dir="${log4j.home}" includes="**/*" />
        <fileset dir="${json-simple.home}" includes="**/*" />
        <fileset dir="${sysUtil.home}" includes="**/*" />
        <fileset dir="${jdbc.home}" includes="**/*" />
        <fileset dir="${spring.home}" includes="**/*.jar" />
        <fileset dir="${lib.home}" includes="**/*.jar" />
    </copy>
    <!-- Copy web stuff into deploy root -->
    <copy overwrite="yes" todir="${dist.home}">
        <fileset dir="${basedir}/web" includes="**/*" />
    </copy>
    <jar destfile="${basedir}/${dist.name}.war" compress="true">
        <fileset dir="${dist.home}" />
    </jar>
</target>

Further Information

  • We are using Spring 3.0.2
  • We are using Tomcat 6.0
  • We are running on Mandriva 2010 and Ubuntu 10
  • The project is worked on in Netbeans and is a free-form webproject
  • Tomcat is being started using "/bin/catalina.sh run" so that we can see any and all output easily, so that we are sure that it is running, and so that we can ensure the war file is being correctly deployed.

EDIT: Contents of /WEB_INF/lib The following files are present:

  • commons-dbcp-1.4.jar
  • commons-logging-1.1.jar
  • mysql-connector-java-3.0.11-stable-bin.jar
  • log4j-1.2.8.jar
  • commons-dbcp-1.4-javadoc.jar
  • commons-pool.jar
  • commons-dbcp-1.4-sources.jar
  • cglib-2.2.jar

The following folders are present, with the contents in parenthesis (as I don't know how to do sub lists, haha)

  • ant-contrib-0.6 (ant-contrib-0.6.jar, antprof.jar)
  • cas (casclient.jar, cas.jar)
  • json-simple-1.1 (json_simple-1.1.jar)
  • junit (junit-4.8.2.jar)
  • log4j-1.2.8 (log4j-1.2.8.jar)
  • selenium-rc (selenium-java-client-driver.jar, selenium-server.jar)
  • spring (spring-aop-3.0.2.RELEASE.jar, spring-context-support-3.0.2.RELEASE.jar, spring-jdbc-3.0.2.RELEASE.jar, spring-test-3.0.2.RELEASE.jar, spring-asm-3.0.2.RELEASE.jar, spring-core-3.0.2.RELEASE.jar, spring-jms-3.0.2.RELEASE.jar, spring-tx-3.0.2.RELEASE.jar, spring-aspects-3.0.2.RELEASE.jar, spring-expression-3.0.2.RELEASE.jar, spring-orm-3.0.2.RELEASE.jar, spring-web-3.0.2.RELEASE.jar, spring-beans-3.0.2.RELEASE.jar, spring-instrument-3.0.2.RELEASE.jar, spring-oxm-3.0.2.RELEASE.jar, spring-webmvc-3.0.2.RELEASE.jar, spring-context-3.0.2.RELEASE.jar, spring-instrument-tomcat-3.0.2.RELEASE.jar, spring-struts-3.0.2.RELEASE.jar, spring-webmvc-portlet-3.0.2.RELEASE.jar)
  • sysUtil ()
  • tomcat-5 (catalina-ant.jar, servlet-api.jar)

So, can anyone help me (us) with this error? We've been struggling with this for hours.

(TL;DR: Spring 3.0.5! Tomcat 6! Building through ANT gives "java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener"; what do?)

1
do you have spring-web-3.0.2.RELEASE.jar in your warfile/WEB_INF/lib after ant finish making war file? - gigadot
It is in warfile/WEB_INF/lib/spring - Dylan Knowles
Question updated with relevant information. - Dylan Knowles
I have never put them into subfolder of warfile/WEB_INF/lib, e.g. warfile/WEB_INF/lib/spring/*.jar. That's probably the cause (I migth be wrong). I think by default tomcat only add warfile/WEB_INF/lib/*.jar to class path. - gigadot

1 Answers

4
votes

According to http://www.coderanch.com/t/510436/Tomcat/Sub-directory-web-inf-lib

By convention, webapp servers can load classes from jars that are in the WEB-INF/lib directory, and Tomcat uses a custom classloader to do just that. However, as Misha said, it looks only in the WEB-INF/lib directory, and not in subdirectories.

You should not put jar files inside subfolder of WEB-INF/lib.

Also, catalina-ant.jar and servlet-api.jar are provided by tomcat, there is no need to add them in your war files, especially when they are older version.

JUnit is also not needed unless you are running test in your product.