javaspringspring-boottomcat8

Why do I have ClassNotFoundException: javax.servlet.http.HttpFilter for a .war after updating from Spring Boot 2.5.5 to 2.6.0?


I have a Spring Boot servlet web application packaged as a WAR. When I use Spring Boot version 2.5.5 it runs fine. I just upgraded the app to Spring Boot version 2.6.0 and now I get the following error when deploying WAR to Tomcat 8.5.59:

2021-11-23 15:36:31.674 ERROR 3876 --- [ost-startStop-1] o.s.boot.SpringApplication               : Application run failed

   java.lang.NoClassDefFoundError: javax/servlet/http/HttpFilter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    

I tried running it on Tomcat 10 : I got the same error. Here is my pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.icimedia</groupId>
<artifactId>ici-autos</artifactId>
<version>3.0.0</version>
<name>ici-autos</name>
<description>Plateforme Autos Autos</description>

<packaging>war</packaging>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>11</java.version>
    <mapstruct.version>1.4.2.Final</mapstruct.version>      
    <org.projectlombok.version>1.18.12</org.projectlombok.version>
    <!-- Apache Tiles -->
    <tiles.version>3.0.8</tiles.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>         
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.batch</groupId>
        <artifactId>spring-batch-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-oxm</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${mapstruct.version}</version>
    </dependency>        
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- configuration processor to generate configuration metadata -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <!-- Tomcat embedded container-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <!-- JSTL for JSP -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <!-- <scope>provided</scope> -->
    </dependency>

    <!-- Need this to compile JSP -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>

    <!-- Need this to compile JSP,
        tomcat-embed-jasper version is not working, no idea why -->
    <dependency>
        <groupId>org.eclipse.jdt.core.compiler</groupId>
        <artifactId>ecj</artifactId>
        <version>4.6.1</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- Apache Tiles dependencies -->
    <dependency>
        <groupId>org.apache.tiles</groupId>
        <artifactId>tiles-core</artifactId>
        <version>${tiles.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tiles</groupId>
        <artifactId>tiles-extras</artifactId>
        <version>${tiles.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tiles</groupId>
        <artifactId>tiles-servlet</artifactId>
        <version>${tiles.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tiles</groupId>
        <artifactId>tiles-api</artifactId>
        <version>${tiles.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tiles</groupId>
        <artifactId>tiles-jsp</artifactId>
        <version>${tiles.version}</version>
    </dependency>
    
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        </dependency>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator-annotation-processor</artifactId>
    </dependency>
    
    <!-- FTP client -->
    <dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>    
        <version>3.7.2</version>        
    </dependency>        
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
        </dependency>
    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>               
    <dependency>
        <groupId>com.rometools</groupId>
        <artifactId>rome</artifactId>
        <version>1.15.0</version>
    </dependency>
</dependencies>

<build>
    <finalName>iciautos</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    
        <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>               
           <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
               <annotationProcessorPaths>
                <path>
                       <groupId>org.mapstruct</groupId>
                       <artifactId>mapstruct-processor</artifactId>
                       <version>${mapstruct.version}</version>
                   </path>
                   <!-- For JPA static metamodel generation -->
                   <path>
                       <groupId>org.hibernate</groupId>
                       <artifactId>hibernate-jpamodelgen</artifactId>
                       <version>${hibernate.version}</version>
                   </path>
                   <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${org.projectlombok.version}</version>
                    </path>
                   </annotationProcessorPaths>
                   <compilerArgs>
                       <arg>-Amapstruct.suppressGeneratorTimestamp=true</arg>
                       <arg>-Amapstruct.defaultComponentModel=spring</arg>
                   </compilerArgs>
           </configuration>
       </plugin>
       <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>                
            <executions>
                <execution>
                    <id>add-source</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>target/generated-sources/annotations</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>pl.project13.maven</groupId>
            <artifactId>git-commit-id-plugin</artifactId>
            <executions>
                <execution>
                    <phase>initialize</phase>
                    <goals>
                        <goal>revision</goal>
                    </goals>                        
                </execution>
            </executions>
            <configuration>
                <dateFormat>yyyyMMdd-HHmmss</dateFormat><!--  human-readable part of the version number -->
                <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
                <generateGitPropertiesFile>true</generateGitPropertiesFile>         
                <offline>true</offline>                        
            </configuration>
        </plugin>
    </plugins>        
</build>

Any ideas about what's the problem ?


Solution

  • HttpFilter is a class introduced in Servlet 4.0, therefore you need to upgrade to Tomcat 9.0.

    Regarding Tomcat 10 (Servlet 5.0), it is incompatible with previous releases and will be the target of Spring Framework 6.x (Spring Boot 3.x).

    Since Spring Framework 5.x and Spring Boot 2.x have a baseline of Servlet 3.1 (cf. documentation) this might be actually a bug, but it is impossible to tell without a full stack trace.

    Edit: Apparently the only reference to HttpFilter in Spring Boot is:

    org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter
    

    Andy already submitted a bug report (see comment below).