Troubleshoot: java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer

Encountering a ClassNotFoundException is a common rite of passage for any Java developer. Specifically, the error java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer can be a head-scratcher when you’re working with web services, particularly when migrating or setting up a new project.

This exception typically indicates that your application server (like Tomcat, JBoss, or Jetty) can’t find the necessary Jersey Servlet container class. Let’s break down why this happens and how to fix it.

Understanding the Problem

The class com.sun.jersey.spi.container.servlet.ServletContainer is a core component of the older **Jersey 1.x** framework. It’s responsible for bootstrapping and handling requests for your RESTful services. If your application attempts to load this class and it’s not present in the classpath, you’ll get the ClassNotFoundException.

The most common reasons for this are:

  1. Missing Dependency: The required Jersey servlet JAR file is not included in your project’s build path or deployed WAR file.
  2. Incorrect Version: You’re using a mix of Jersey 1.x and Jersey 2.x (or later) dependencies, or your configuration points to a Jersey 1.x class while you’re using Jersey 2.x.
  3. Build Tool Misconfiguration: Your build tool (Maven, Gradle) isn’t correctly packaging the dependency.
  4. Deployment Issue: The JAR file isn’t correctly placed in the application server’s classpath (e.g., in WEB-INF/lib for web applications).

The Solution: Adding the Correct Dependency

The fix usually involves ensuring the correct Jersey 1.x servlet dependency is present. If you’re building with Maven, you’ll need to add the following to your pom.xml:

For Maven Projects (Recommended)

Add the following dependency to your pom.xml within the <dependencies> block:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.19.4</version> <!-- Use the latest 1.x version -->
</dependency>

Important: Refer to Maven Central (search for jersey-servlet) to ensure you are using the latest stable 1.x version. At the time of writing, 1.19.4 is commonly used for Jersey 1.x projects.

After adding the dependency, remember to:

  • Run mvn clean install or mvn clean package to rebuild your project.
  • Redeploy your WAR file to your application server.

For Gradle Projects

If you’re using Gradle, add this to your build.gradle file:

dependencies {
    implementation 'com.sun.jersey:jersey-servlet:1.19.4' // Or your desired 1.x version
}  

Then run gradle clean build and redeploy.

Manual Dependency Management (Not Recommended for Production)

If you’re managing dependencies manually (e.g., in a simple development setup or if you’re not using a build tool), you’ll need to download the jersey-servlet-1.x.x.jar file and place it in the application’s classpath:

  • For web applications deployed as WARs, place the JAR in the WEB-INF/lib directory.
  • For standalone applications, ensure it’s on the application’s classpath when you run it (e.g., using the -cp flag with Java).

Addressing Configuration: web.xml

Another crucial piece of information is how your web.xml (for Servlet API-based deployments) is configured to use the Jersey servlet. If you’re using Jersey 1.x, your web.xml will likely contain a servlet definition like this:

<web-app ...>
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.yourcompany.rest</param-value> <!-- Your package with REST resources -->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/rest/*</url-pattern> <!-- Your desired URL pattern -->
    </servlet-mapping>
</web-app>     

Ensure that the <servlet-class> precisely matches com.sun.jersey.spi.container.servlet.ServletContainer if you intend to use Jersey 1.x.

Differentiating Jersey 1.x and Jersey 2.x

It’s important to understand the significant difference between Jersey 1.x and Jersey 2.x. If you are starting a new project, **it is highly recommended to use Jersey 2.x (or later)** as Jersey 1.x is no longer actively developed and maintained.

If you are encountering this error, and you *intended* to use Jersey 2.x, then the ClassNotFoundException is a strong indicator that you have a mix of old (Jersey 1.x) and new (Jersey 2.x) dependencies, or your web.xml is configured for Jersey 1.x.

For Jersey 2.x Applications:

If you *should* be using Jersey 2.x, the corresponding servlet class is different, and the web.xml configuration also changes. The class name for Jersey 2.x is org.glassfish.jersey.servlet.ServletContainer.

Your web.xml for Jersey 2.x would look something like this:

<web-app ...>
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.yourcompany.rest</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app> 

And your Maven dependency for Jersey 2.x would typically be:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.34</version> <!-- Use the latest 2.x version -->
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.34</version> <!-- Matches previous version -->
</dependency>     

If you’re seeing the ClassNotFoundException for com.sun.jersey… and you’re aiming for Jersey 2.x, you need to go through your pom.xml (or build.gradle) and web.xml and ensure all references are updated to the Jersey 2.x equivalents.

Conclusion

The java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer is almost always a classpath issue related to missing or incorrect Jersey 1.x dependencies. By carefully checking your project’s build configuration (Maven/Gradle) and your web.xml, you should be able to resolve this exception quickly. For new projects, always consider using the latest stable version of Jersey (2.x or later) to benefit from improved features and ongoing support.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.