NoClassDefFoundError in web application running on Tomcat 7

Fyodor Sherstobitov picture Fyodor Sherstobitov · Apr 4, 2013 · Viewed 30.6k times · Source

I have web application written in Java using gucie-servlet framework being built by Maven 3. When I deploy it on Tomcat 7 container and try to access it using browser, Tomcat replies with 404 status code. This is log from Tomcat:

Apr 4, 2013 11:39:50 AM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextDestroyed()
Apr 4, 2013 11:39:50 AM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextDestroyed()
Apr 4, 2013 11:39:55 AM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class ru.hive.webserver.config.HiveServletConfig
java.lang.NoClassDefFoundError: ru/hive/base/db/modules/DatabaseModule
    at ru.hive.webserver.config.HiveServletConfig.getInjector(HiveServletConfig.java:24)
    at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:45)
    at ru.hive.webserver.config.HiveServletConfig.contextInitialized(HiveServletConfig.java:19)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:977)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1655)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: ru.hive.base.db.modules.DatabaseModule
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1713)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1558)
    ... 17 more
Apr 4, 2013 11:39:55 AM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Apr 4, 2013 11:39:55 AM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Apr 4, 2013 11:39:55 AM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: attributeAdded('org.apache.jasper.compiler.TldLocationsCache', 'org.apache.jasper.compiler.TldLocationsCache@e8606c')

Exception says that there is no class named ru.hive.base.db.modules.DatabaseModule in CLASSPATH of my app, but it is not true:

frodo@shire:~/apache-tomcat-7.0.37/webapps/hive/WEB-INF/lib$ ls -l
total 30132
-rw-rw-r-- 1 frodo frodo     4467 нояб. 22 13:46 aopalliance-1.0.jar
-rw-rw-r-- 1 frodo frodo 27010023 апр.   4 11:39 base-0.0.42-SNAPSHOT.jar
-rw-rw-r-- 1 frodo frodo   232019 дек.  18 10:12 commons-beanutils-1.8.3.jar
-rw-rw-r-- 1 frodo frodo    58160 авг.   2  2011 commons-codec-1.4.jar
-rw-rw-r-- 1 frodo frodo   196768 дек.  18 10:12 commons-digester-2.1.jar
-rw-rw-r-- 1 frodo frodo   163151 нояб. 22 13:46 commons-io-2.1.jar
-rw-rw-r-- 1 frodo frodo    60686 авг.   2  2011 commons-logging-1.1.1.jar
-rw-rw-r-- 1 frodo frodo   189285 нояб. 28 15:01 gson-2.2.2.jar
-rw-rw-r-- 1 frodo frodo   710492 февр.  6 18:59 guice-3.0.jar
-rw-rw-r-- 1 frodo frodo    65012 февр. 13 13:21 guice-servlet-3.0.jar
-rw-rw-r-- 1 frodo frodo   352585 нояб. 22 13:46 httpclient-4.1.3.jar
-rw-rw-r-- 1 frodo frodo   181410 нояб. 22 13:46 httpcore-4.1.4.jar
-rw-rw-r-- 1 frodo frodo    26938 нояб. 22 13:46 httpmime-4.1.3.jar
-rw-rw-r-- 1 frodo frodo     2497 февр.  6 18:59 javax.inject-1.jar
-rw-rw-r-- 1 frodo frodo    31866 февр.  6 18:59 jsr305-2.0.1.jar
-rw-rw-r-- 1 frodo frodo    25962 нояб. 22 13:46 slf4j-api-1.6.4.jar
-rw-rw-r-- 1 frodo frodo   371816 нояб. 22 13:46 solr-solrj-4.0.0.jar
-rw-rw-r-- 1 frodo frodo   520969 нояб. 22 13:46 wstx-asl-3.2.7.jar
-rw-rw-r-- 1 frodo frodo   608239 нояб. 22 13:46 zookeeper-3.3.6.jar

JAR base-0.0.42-SNAPSHOT.jar contains class which Tomcat can't find. The directory structure inside JAR is the same as in full class name in stack trace. The pom.xml for my project is:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>webserver</artifactId>
    <version>0.0.42-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>Api servlet</name>

    <parent>
        <groupId>ru.hive</groupId>
        <artifactId>main</artifactId>
        <version>0.0.41-SNAPSHOT</version>
        <relativePath>../main</relativePath>
    </parent>

    <profiles>
        <profile>
            <id>dev</id>

            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>

            <properties>
                <solr.url>http://localhost:8983/solr</solr.url>
            </properties>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.tomcat.maven</groupId>
                        <artifactId>tomcat7-maven-plugin</artifactId>
                        <version>2.0</version>
                        <configuration>
                            <server>local_tomcat</server>
                            <url>http://192.168.0.39:8080/manager/text</url>
                            <path>/hive</path>
                            <update>true</update>
                            <username>user</username>
                            <password>pass</password>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>production</id>

            <properties>
                <solr.url>http://localhost:8983/solr/hive</solr.url>
            </properties>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.tomcat.maven</groupId>
                        <artifactId>tomcat7-maven-plugin</artifactId>
                        <version>2.0</version>
                        <configuration>
                            <server>production_tomcat</server>
                            <url>http://some.ip.address:8080/manager/text</url>
                            <path>/hive</path>
                            <update>true</update>
                            <username>user</username>
                            <password>pass</password>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

    <dependencies>
        <dependency>
            <groupId>ru.hive</groupId>
            <artifactId>base</artifactId>
            <version>0.0.42-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.google.inject.extensions</groupId>
            <artifactId>guice-servlet</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>jsr305</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>Maven Repository Switchboard</name>
            <url>http://repo1.maven.org/maven2</url>
        </repository>
        <repository>
            <id>repo</id>
            <releases>
                <enabled>true</enabled>
                <checksumPolicy>ignore</checksumPolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <url>file://${project.basedir}/lib</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <releases>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>Maven Plugin Repository</name>
            <url>http://repo1.maven.org/maven2</url>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <finalName>hive</finalName>

        <sourceDirectory>src/main/java</sourceDirectory>
        <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <outputDirectory>target/classes</outputDirectory>
        <testOutputDirectory>target/test-classes</testOutputDirectory>
        <directory>target</directory>

        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.3</version>
                </plugin>
                <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.2-beta-5</version>
                </plugin>
                <plugin>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>2.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-release-plugin</artifactId>
                    <version>2.0</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <id>default-war</id>
                        <phase>package</phase>
                        <goals>
                            <goal>war</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <addClasspath>true</addClasspath>
                                    <classpathPrefix>lib/</classpathPrefix>
                                </manifest>
                            </archive>
                        </configuration>
                    </execution>
                </executions>

                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                    </archive>
                    <webResources>
                        <webResource>
                            <directory>src/main/webapp/META-INF</directory>
                            <includes>
                                <include>context.xml</include>
                            </includes>
                            <filtering>true</filtering>
                            <targetPath>META-INF</targetPath>
                        </webResource>
                    </webResources>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <id>default-clean</id>
                        <phase>clean</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.3.1</version>
                <executions>
                    <execution>
                        <id>default-install</id>
                        <phase>install</phase>
                        <goals>
                            <goal>install</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.4.3</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <id>default-resources</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>resources</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-testResources</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>testResources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.7.1</version>
                <executions>
                    <execution>
                        <id>default-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <executions>
                    <execution>
                        <id>default-testCompile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <reporting>
        <outputDirectory>target/site</outputDirectory>
    </reporting>
</project>

So the question is what am I doing wrong and why I get this ClassDefNotFound exception?

PS. Edited version of maven-war-plugin config:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <id>default-war</id>
            <phase>package</phase>
            <goals>
                <goal>war</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <webResources>
            <webResource>
                <directory>src/main/webapp/META-INF</directory>
                <includes>
                    <include>context.xml</include>
                </includes>
                <filtering>true</filtering>
                <targetPath>META-INF</targetPath>
            </webResource>
        </webResources>
    </configuration>
    </plugin>

PPS. ru.hive.webserver.config.HiveServletConfig class listing

package ru.hive.webserver.config;

import javax.servlet.ServletContextEvent;

import ru.hive.base.db.modules.DatabaseModule;
import ru.hive.base.state.modules.StateManagerModule;
import ru.hive.webserver.api.ApiServlet;
import ru.hive.webserver.scheduler.Scheduler;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;

public class HiveServletConfig extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
            @Override
            protected void configureServlets() {
                install(new DatabaseModule());
                install(new StateManagerModule());

                serve("/api").with(ApiServlet.class);
                serve("/scheduler").with(Scheduler.class);
            }
        });
    }

}

PPPS. The list of JARs in <TOMCAT_HOME>/lib:

`-rw-r--r-- 1 jcdenton jcdenton   15264 марта 22 18:38 annotations-api.jar
-rw-r--r-- 1 jcdenton jcdenton   54176 марта 22 18:38 catalina-ant.jar
-rw-r--r-- 1 jcdenton jcdenton  132729 марта 22 18:38 catalina-ha.jar
-rw-r--r-- 1 jcdenton jcdenton 1563926 марта 22 18:38 catalina.jar
-rw-r--r-- 1 jcdenton jcdenton  255182 марта 22 18:38 catalina-tribes.jar
-rw-r--r-- 1 jcdenton jcdenton 1796326 марта 22 18:38 ecj-4.2.1.jar
-rw-r--r-- 1 jcdenton jcdenton   46085 марта 22 18:38 el-api.jar
-rw-r--r-- 1 jcdenton jcdenton  123241 марта 22 18:38 jasper-el.jar
-rw-r--r-- 1 jcdenton jcdenton  599131 марта 22 18:38 jasper.jar
-rw-r--r-- 1 jcdenton jcdenton   88690 марта 22 18:38 jsp-api.jar
-rw-r--r-- 1 jcdenton jcdenton  177599 марта 22 18:38 servlet-api.jar
-rw-r--r-- 1 jcdenton jcdenton    6873 марта 22 18:38 tomcat-api.jar
-rw-r--r-- 1 jcdenton jcdenton  795308 марта 22 18:38 tomcat-coyote.jar
-rw-r--r-- 1 jcdenton jcdenton  235411 марта 22 18:38 tomcat-dbcp.jar
-rw-r--r-- 1 jcdenton jcdenton   77364 марта 22 18:38 tomcat-i18n-es.jar
-rw-r--r-- 1 jcdenton jcdenton   48693 марта 22 18:38 tomcat-i18n-fr.jar
-rw-r--r-- 1 jcdenton jcdenton   51678 марта 22 18:38 tomcat-i18n-ja.jar
-rw-r--r-- 1 jcdenton jcdenton  123958 марта 22 18:38 tomcat-jdbc.jar
-rw-r--r-- 1 jcdenton jcdenton   23174 марта 22 18:38 tomcat-util.jar`

Answer

Fyodor Sherstobitov picture Fyodor Sherstobitov · Apr 5, 2013

OK, I've found the solution. After careful study of my <TOMCAT_HOME>/logs/catalina.log I've found this record:

Apr 5, 2013 1:38:26 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(/home/frodo/apache-tomcat-7.0.37/webapps/hive/WEB-INF/lib/base-0.0.42-SNAPSHOT.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

This question explains the reason of this message - my JAR base-0.0.42-SNAPSHOT.jar contains something related to Servlet API and can't be loaded by Tomcat because of it. So, my web app can't find classes in this JAR after start. I'm using some parts of Twitter commons inside this JAR which contain realization of Servlet API. After revision of the dependencies of base-0.0.42-SNAPSHOT.jar my app starts and loads classes needed. Thank you to everyone!