I am having a simple java maven project which generates some user Ids for a given GET request. I am using javax.servlet package.
Everything works fine when I am packaging and deploying the war file in local jetty server.
However things are not working when I am using the docker jetty image and deploying the war file. I am getting the below error
MacBook-Pro-3:UIDGenerators unbxd$ docker run 0xvoila/uid-generator:latest
2022-07-03 17:50:09.448:INFO :oejs.Server:main: jetty-11.0.11; built: 2022-06-21T21:42:55.454Z; git: 58487315cb75e0f5c81cc6fa50096cbeb3b9554e; jvm 17.0.3 7
2022-07-03 17:50:09.523:INFO :oejdp.ScanningAppProvider:main: Deployment monitor [file:///var/lib/jetty/webapps/]
2022-07-03 17:50:10.234:INFO :oejss.DefaultSessionIdManager:main: Session workerName=node0
2022-07-03 17:50:10.291:WARN :oejw.WebAppContext:main: Failed startup of context o.e.j.w.WebAppContext@4f67eb2a{Archetype Created Web Application,/uid-generator,file:///tmp/jetty-0_0_0_0-8080-uid-generator_war-_uid-generator-any-15856705197144621036/webapp/,UNAVAILABLE}{/var/lib/jetty/webapps/uid-generator.war}
java.lang.NoClassDefFoundError: javax/servlet/http/HttpServlet
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
Here is my pom.xml file
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.amit.system</groupId>
<artifactId>UIDGenerators</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>UIDGenerators Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>uid-generator</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.eclipse.jetty</groupId>-->
<!-- <artifactId>jetty-maven-plugin</artifactId>-->
<!-- <version>9.4.28.v20200408</version>-->
<!-- </plugin>-->
</plugins>
</pluginManagement>
</build>
</project>
Here is my Dockerfile
FROM maven as build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package
FROM jetty:latest
COPY --from=build /home/app/target/uid-generator.war /var/lib/jetty/webapps
CMD java -jar "$JETTY_HOME/start.jar"
I tried to debug myself and it seems like javax. servlet is not present in the jetty docker image. But in my pom.xml file I had given javax.servlet as dependencies.
Can anyone help me with the solution.
UPDATED
Here is the java code
package org.amit.system;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UIDGenerator extends HttpServlet {
int sequence = 0;
final static int sequenceBits = 12; // max is 4096
final static int maxSequence = (int)Math.pow(2, sequenceBits) - 1;
final static int nodeId = 11;
final static int nodeBits = 10; // max is 1024
public synchronized int generateSequence(long runningMillisecond){
this.sequence = this.sequence 1;
if (this.sequence >= maxSequence && runningMillisecond == System.currentTimeMillis()){
waitOneMillisecond(runningMillisecond);
this.sequence = 0;
}
return this.sequence;
}
private void waitOneMillisecond(long runningMillisecond){
while(runningMillisecond == System.currentTimeMillis()){
continue;
}
}
public int generateNodeId(){
return this.nodeId;
}
public void run(){
int nodeNumber = this.generateNodeId();
long epoch = System.currentTimeMillis();
int sequence = this.generateSequence(epoch);
// System.out.println("Echo before shift " epoch);
epoch = epoch << (this.nodeBits this.sequenceBits);
epoch = epoch | nodeNumber << this.sequenceBits;
epoch = epoch | sequence;
System.out.println("Echo after shift " epoch);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
int nodeNumber = this.generateNodeId();
long epoch = System.currentTimeMillis();
int sequence = this.generateSequence(epoch);
epoch = epoch << (this.nodeBits this.sequenceBits);
epoch = epoch | nodeNumber << this.sequenceBits;
epoch = epoch | sequence;
response.getOutputStream().print("Echo after shift " epoch);
}
}
CodePudding user response:
Jetty 9 is at End of Community Support.
See: https://github.com/eclipse/jetty.project/issues/7958
You should upgrade, to at least Jetty 10.
The problem you have is the combination of jetty-11.0.11 and javax/servlet/http/HttpServlet.
Jetty 11 supports Servlet 5.0, which underwent the Jakarta "Big Bang" and changed namespace to jakarta.servlet.*
See Past Question for details (including table in accepted answer for support levels for the combination of Jetty version, Servlet Spec version, EE governing body, and Servlet namespace)
CodePudding user response:
Problem got resolved for me. Actually problem was with my jetty image. Instead of using FROM jetty:latest, I should be using FROM jetty:9-jre8-openjdk then only classes and servlet jars would be available for my application.
Here it the complete Dockerfile
FROM maven as build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package
FROM jetty:9-jre8-openjdk
COPY --from=build /home/app/target/root.war /var/lib/jetty/webapps
EXPOSE 8080
CMD java -jar "$JETTY_HOME/start.jar"
