Home > Blockchain >  Running Java Maven project using Jetty docker image
Running Java Maven project using Jetty docker image

Time:07-05

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"
  • Related