I'm trying to create a Docker image from my Jersey web application running on a Tomcat server. I'm developing on a Windows 7 machine.
I have deployed the web application on a local Tomcat 8.0.14 application server on my development machine and everything works as expected.
To create the Docker image I put the following Dockerfile.
in the same directory as the my-web-app.war
file.
FROM tomcat:8.0-jre8
ADD /my-web-app.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
After that I'm creating the image with the following command:
docker build -t my-web-app .
This is done sucessfully and the images shows up with the docker images -a
command.
After that I start the image through this:
winpty docker run --rm -it -p 8080:8080 my-web-app
The command prompt show that the server is successfully started and when I tried to access the web application this also works:
http://192.168.99.100:8080/my-web-app
shows the appropriate HTML welcome page.
The issue arises when I try to access any of the actual Jersey RESTful web services. Any time I try to access something different than an HTML page I get the following error message:
javax.servlet.ServletException: Servlet.init() for servlet My Web Application threw exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2527)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2516)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)
root cause
java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:308)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:337)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:178)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:370)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2527)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2516)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)
I assume there might be something wrong with the creation of the WAR file but if so how can the application be successfully deployed on my local Tomcat server.
If this is of any interest here is the pom.xml
file I used to build the WAR:
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.webapp.host</groupId>
<artifactId>my-web-app</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-web-app</name>
<build>
<finalName>my-web-app</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.26-b03</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.26-b03</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.26-b03</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b05</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19.3</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.19.3</version>
</dependency>
<!-- persistence api -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.4</version>
</dependency>
<!-- additional apis -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<!-- own apis -->
<dependency>
<groupId>my.own.utility.api</groupId>
<artifactId>utility-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
Does anyone know what the issue here is?
Any help is appreciated.
Greetings
Here is an indepth overview and a solution to all who encounter NoSuchMethodError especially in jersey context.
The problem is
In Java NoSuchMethodError is thrown when the JVM cant find the method specified in the specified class. From https://docs.oracle.com/javase/9/docs/api/java/lang/NoSuchMethodError.html
In your case JVM is complaining that
javax.ws.rs.core.Application
doesnot havegetProperties()
method.Jesey 2.x uses JEE 7. In JEE 7 version of
javax.ws.rs.core.Application
hasgetClasses()
getSingeltons()
getProperties()
methods defined. https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Application.htmlJesey 1.x uses JEE 6. In JEE 6 version of
javax.ws.rs.core.Application
only hasgetClasses()
getclass()
But
getProperties()
is not defined. https://jersey.github.io/apidocs/1.19.1/jersey/javax/ws/rs/core/Application.htmlSolution
You have jersey 2.x and 1.x versions defined in your pom.xml. Therefore there are both JEE6 and 7 versions of
javax.ws.rs.core.Application
in your classpath and classloader loads JEE 6 version of appliction class which doesnot havegetProperties()
defined but yor application wants to executegetProperties()
anyway. Hence the error.Remove all jersey 1.x versions from your pom.xml and stick to jersey 2.x version. The classloader will take care of the rest.