Search code examples
spring-boottomcat

Spring Boot application failed to start when tomcat version is set


I'm writing here because I can't find solution to my problem. I have a Spring Boot application which is deployed on an external tomcat version 10.1.6. So to have a same tomcat version on local and prod, I set Tomcat version on build.gradle with extra["tomcat.version"] = "10.1.6". But when I do that,the application failed to start:

Spring Boot version: 3.3.4

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer.customizeMaxQueueCapacity(TomcatWebServerFactoryCustomizer.java:170)

The following method did not exist:

    'void org.apache.coyote.AbstractProtocol.setMaxQueueSize(int)'

The calling method's class, org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer, was loaded from the following location:

    jar:file:/Users/USER/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/3.3.4/979234a0f3035fe60d5e505018789f98a7ec7ee3/spring-boot-autoconfigure-3.3.4.jar!/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.class

The called method's class, org.apache.coyote.AbstractProtocol, is available from the following locations:

    jar:file:/Users/USER/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-core/10.1.6/abacfdcc788fafbf671c6f68338bd2d5c27411e7/tomcat-embed-core-10.1.6.jar!/org/apache/coyote/AbstractProtocol.class

The called method's class hierarchy was loaded from the following locations:

    org.apache.coyote.AbstractProtocol: file:/Users/USER/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-core/10.1.6/abacfdcc788fafbf671c6f68338bd2d5c27411e7/tomcat-embed-core-10.1.6.jar


Action:

Correct the classpath of your application so that it contains compatible versions of the classes org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer and org.apache.coyote.AbstractProtocol


Process finished with exit code 1

To explain my problem, I have created a sample project with Spring Initializr: https://github.com/amourier63/spring-boot-set-tomcat-version

In the Build.gradle.kts line 23. If I comment the line and launch the project, the project start. But when I uncomment, the start failed.

I take any suggestion... and maybe set the tomcat version is a bad idea.

Thank you


Solution

  • The AbstractProtocol.setMaxQueueSize() method was introduced in Apache Tomcat v10.1.25 (source) and it's set as soon as server.tomcat.threads.max-queue-capacity is configured (and that property has a default value).

    So in short, Spring Boot v3.3.4 is not compatible with Apache Tomcat v10.1.6.

    Possible solutions are:

    • Updating your external Tomcat to v10.1.25 or higher (I would recommend to go to the latest v10.1.x or v10.1.30 as that's the version Spring Boot v3.3.4 uses as default).

    • Alternatively, you could set the server.tomcat.threads.max-queue-capacity to a non-positive value, because in that case TomcatWebServerFactoryCustomizer does not invoke the setMaxQueueSize() method (source). I don't recommend this though.

      server.tomcat.threads.max-queue-capacity=0
      
    • Downgrade Spring Boot to v3.3.0. This feature was introduced in Spring Boot v3.3.1 (see issue), so downgrading to v3.3.0 would not cause this error to happen. I don't recommend this either.

    • Since the error only happens in the embedded Tomcat configuration (which I assume you use for development?), you could also remove the <tomcat.version> property and run locally on the latest supported Tomcat 10.1.x version, while you deploy your WAR-file on Tomcat 10.1.6.