java - Tomcat 泽西 NoSuchMethodError
问题描述
我有一个 Tomcat 9.0.20 服务器在我的计算机上运行,JDK 12 和 Jersey 2 作为 REST API 帮助程序。这工作正常。但是当我将文件部署到运行相同 tomcat 和 Java 版本的 Ubuntu 服务器时,我收到错误 500:
javax.servlet.ServletException: Servlet.init() for servlet [jersey-serlvet] threw exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:835)
Root Cause
java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:306)
org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:292)
org.glassfish.jersey.internal.Errors.process(Errors.java:292)
org.glassfish.jersey.internal.Errors.process(Errors.java:274)
org.glassfish.jersey.internal.Errors.processWithException(Errors.java:232)
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:291)
org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:258)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:346)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingR
我使用了这些库:
我使用 Jhades 来检测重叠库,但这对我没有帮助。
>> jHades - scanning classpath for overlapping jars:
WARNING: this classloader is not supported: jdk.internal.loader.ClassLoaders$AppClassLoader
WARNING: this classloader is not supported: jdk.internal.loader.ClassLoaders$PlatformClassLoader
我的 web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>de.kai.iae</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
我的 Hello.Java:
package de.kai.iae;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello")
public class Hello {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Jersey";
}
}
解决方案
有几个问题:
您不能将应用程序 jar 放入 tomcat 的
./lib
文件夹中。相反,您应该将这些 jars 添加为内部每个应用程序的依赖项<WAR>/WEB-INF/lib
,这样您的应用程序将是独立的,并且能够使用这些库的不同版本。确保您没有打包同一依赖项的多个版本,这很可能会导致各种类加载问题,例如
ClassNotFoundException
,NoClasDefFoundError
和NoSuchMethodError
例如,您拥有jakarta.ws.rs-api
Jax-Rs 版本 2,但您也拥有jsr311-api
Jax-Rs 版本 1。
因此,在您的情况下,一些球衣代码尝试调用JaxRs-2 中引入的getProperties(),但是 JVM 已加载了JaxRs-1 中不存在该方法的Application
类。因此,删除jar 应该可以解决问题.jsr311-api
jsr311-api
推荐阅读
- r - R - S3 方法 - 绘图
- javascript - 在js中使用变量进行计算时无法得到正确的结果
- bash - bash 中的复杂条件,其中正在评估可执行文件的返回值
- javascript - 如何选择 Javascript 对象中“计数”最低的值
- sql - 基于关联的 Rails 顺序无法正常工作
- unity3d - 物体旋转的Unity3d问题
- c++ - 在 Windows 64 位中静态编译 Paho MQTT 的问题
- python - 知道 sqlalchemy 过滤器何时发现某些东西
- python - 当我输入一个存储对象的变量时,它会不断返回该对象的实例,而不是我希望它返回的列表
- javascript - AngularJS - 数据未在“数据类”属性上呈现