I have an Tomcat 9.0.20 server running on my computer with JDK 12 and Jersey 2 as REST API helper. This works fine. But when I deploy the files to my Ubuntu server, which is running the same tomcat and Java Version, I get an error 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
I used these libraries:
I used Jhades to detect overlapping libraries but this didn't help me.
>> 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
My 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>
My 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";
}
}
There are several issues:
You must not put application jars inside tomcat's ./lib
folder. Instead you should add those jars as dependencies for each application inside <WAR>/WEB-INF/lib
In that way your applications will be independent and will be able to use different versions of those libraries.
Make sure you do not package several versions of the same dependency, which will most probably cause various class-loading issues such as ClassNotFoundException
, NoClasDefFoundError
and NoSuchMethodError
For instance you have jakarta.ws.rs-api
wich is Jax-Rs version 2, but you also have jsr311-api
which is Jax-Rs version 1.
So in your case, some jersey code tries to call getProperties() which was introduced in JaxRs-2, but the JVM has loaded the Application
class from jsr311-api
which is JaxRs-1 where that method does not exist.So removing the jsr311-api
jar should fix the problem.