Tomcat 10部署Guacamole 1.5.3出现NoSuchMethodError异常求助
异常详情
部署Guacamole 1.5.3到Tomcat 10时,日志抛出如下java.lang.NoSuchMethodError异常:
org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for
java.lang.NoSuchMethodError: 'void jakarta.servlet.http.HttpServletResponse.setStatus(int, java.lang.String)'
at org.glassfish.jersey.servlet.internal.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:147)
at org.glassfish.jersey.server.ServerRuntime$Responder$1.getOutputStream(ServerRuntime.java:639)
当前使用Jersey版本为3.1.3,项目pom.xml依赖配置如下:
pom.xml依赖配置
<!-- Jakarta servlet API --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.el</groupId> <artifactId>jakarta.el-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <!-- Jakarta WebSocket API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-api</artifactId> <version>2.1.0</version> <scope>provided</scope> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <exclusions> <!-- Exclude optional dependency on JavaMail --> <exclusion> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> </exclusion> </exclusions> </dependency> <!-- Guacamole Extension API --> <dependency> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-ext</artifactId> <version>1.5.3</version> </dependency> <!-- Guacamole JavaScript API --> <dependency> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-common-js</artifactId> <version>1.5.3</version> <type>zip</type> <scope>runtime</scope> </dependency> <!-- Jetty 8 servlet API (websocket) --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-websocket</artifactId> <version>8.1.1.v20120215</version> <scope>provided</scope> </dependency> <!-- Jetty 9.0 servlet API (websocket) --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-parent</artifactId> <version>20</version> <scope>provided</scope> <type>pom</type> </dependency> <dependency> <groupId>org.eclipse.jetty.websocket</groupId> <artifactId>websocket-api</artifactId> <version>9.0.7.v20131107</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.eclipse.jetty.websocket</groupId> <artifactId>websocket-servlet</artifactId> <version>9.0.7.v20131107</version> <scope>provided</scope> </dependency> <!-- Tomcat servlet API (websocket) --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>7.0.37</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>7.0.37</version> <scope>provided</scope> </dependency> <!-- Guice - Dependency Injection --> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice</artifactId> <version>5.1.0-rc.2</version> </dependency> <dependency> <groupId>com.google.inject.extensions</groupId> <artifactId>guice-assistedinject</artifactId> <version>7.0.0</version> </dependency> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice-assistedinject</artifactId> <version>5.1.0-rc.2</version> </dependency> <!-- Jersey Implementation --> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>guice-bridge</artifactId> <version>3.0.4</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>listenablefuture</artifactId> <version>1.0</version> </dependency> <!-- jakarta annotations --> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>2.1.1</version> </dependency> <!-- Guava Base Libraries --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> <!-- Force use of version 1.2.2 (transitive dependencies of jersey-media-json-jackson disagree on 1.2.1 vs. 1.2.2) --> <dependency> <groupId>jakarta.activation</groupId> <artifactId>jakarta.activation-api</artifactId> <version>2.0.1</version> </dependency> </dependencies>
问题原因
- Servlet API版本不匹配:Tomcat 10实现的是Jakarta Servlet 5.0规范,而pom.xml中引入的
jakarta.servlet-api是6.0.0版本,版本过高。HttpServletResponse.setStatus(int, String)方法在Servlet 6.0中被彻底移除,导致运行时Tomcat 10找不到该方法。 - 老旧依赖冲突:pom.xml中引入的Jetty 8/9、Tomcat 7依赖属于Java EE时代的javax命名空间,与Tomcat 10的jakarta命名空间存在类加载冲突风险。
- Guice版本不一致:同时引入了不同版本的Guice辅助注入依赖,会引发依赖冲突。
解决方案
1. 调整Servlet API版本适配Tomcat 10
将Jakarta相关API版本降级到匹配Tomcat 10的版本:
<dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.el</groupId> <artifactId>jakarta.el-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency>
2. 移除老旧Java EE Servlet容器依赖
删除所有Jetty 8/9、Tomcat 7的依赖,这些依赖与Tomcat 10不兼容且无实际作用:
<!-- 删除以下所有依赖块 --> <!-- Jetty 8 servlet API (websocket) --> <!-- Jetty 9.0 servlet API (websocket) --> <!-- Tomcat servlet API (websocket) -->
3. 统一Guice依赖版本
删除冲突的Guice依赖,仅保留适配Jakarta的版本:
<!-- 删除 com.google.inject.extensions:guice-assistedinject:7.0.0 --> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice</artifactId> <version>5.1.0-rc.2</version> </dependency> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice-assistedinject</artifactId> <version>5.1.0-rc.2</version> </dependency>
4. 可选:降级Jersey版本增强兼容性
若调整后仍有问题,可将Jersey版本降级到3.0.x系列,该版本对Servlet 5.0的适配更稳定。
验证步骤
- 执行
mvn clean package重新构建项目。 - 将生成的war包部署到Tomcat 10。
- 启动Tomcat并检查日志,确认
NoSuchMethodError异常消失。
内容的提问来源于stack exchange,提问作者Rihab Kasim

