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);
}
}
2
Answers
Problem got resolved for me. Actually problem was with my jetty image. Instead of using
FROM jetty:latest
, I should be usingFROM jetty:9-jre8-openjdk
then onlyclasses and servlet jars
would be available for my application.Here it the complete
Dockerfile
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
andjavax/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)