Kemas ulang file WAR menjadi file JAR

Dokumen ini menjelaskan cara mengemas ulang aplikasi Java 8 sebagai file JAR untuk dijalankan di runtime Java yang didukung. Untuk menggunakan runtime Java yang didukung, Anda dapat menyematkan server seperti Jetty atau membuat container aplikasi dengan Docker untuk runtime kustom tanpa menulis ulang aplikasi sepenuhnya. Anda dapat menjalankan aplikasi WAR yang ada di platform Java modern atau lingkungan cloud fleksibel. Pilih dari metode berikut yang paling sesuai dengan strategi dan infrastruktur deployment Anda:

Siapkan aplikasi web Java 8 (file WAR) Anda

Sebelum memaketkan ulang aplikasi Java 8 sebagai file JAR yang didukung, Anda harus membuat file WAR. Bagian ini menyediakan aplikasi Java 8 contoh yang mem-build file WAR. Ikuti petunjuk untuk membuat aplikasi hello-world Java 8:

  1. Buat file HelloServlet.java di direktori sumber Anda:

    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/hello")
    public final class HelloServlet extends HttpServlet {
      /**
       * This method handles GET requests to the /hello endpoint.
       *
       * <p>Subclasses should not override this method.
       *
       * @param request the HttpServletRequest object
       * @param response the HttpServletResponse object
       * @throws ServletException if a servlet-specific error occurs
       * @throws IOException if an I/O error occurs
       */
      @Override
      protected void doGet(
          final HttpServletRequest request, final HttpServletResponse response)
          throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello, World!</h1>");
      }
    }
  2. Buat file deployment descriptor web.xml untuk mengonfigurasi aplikasi web Anda:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
    </web-app>
  3. Buat halaman landing index.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Hello App Engine</title>
    </head>
    <body>
        <h1>Welcome to Google App Engine!</h1>
        <p><a href="hello">Say Hello</a></p>
    </body>
    </html>
    
  4. Tambahkan kode berikut di file pom.xml untuk menentukan build bagi aplikasi Java 8 Anda:

    • Konfigurasi pengemasan WAR:

      <groupId>com.example</groupId>
      <artifactId>HelloWorldApp</artifactId>
      <version>1.0</version>
      <packaging>war</packaging>
      
    • Plugin maven-war-plugin dengan sumber dan target maven.compiler yang ditetapkan ke versi 1.8:

      <properties>
          <maven.compiler.source>1.8</maven.compiler.source>
          <maven.compiler.target>1.8</maven.compiler.target>
          <java.version>8</java.version>
      </properties>
      
    • Dependensi javax.servlet-api:

      <dependencies>
          <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>javax.servlet-api</artifactId>
              <version>3.1.0</version>
              <scope>provided</scope>
          </dependency>
      </dependencies>
      
    • Konfigurasi Maven:

        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version> <configuration>
                        <source>${maven.compiler.source}</source>
                        <target>${maven.compiler.target}</target>
                    </configuration>
                </plugin>
      
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.3.2</version>
                </plugin>
      
            </plugins>
        </build>
      

    Direktori project Anda akan terlihat seperti struktur berikut:

    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── com
            │       └── example
            │           └── HelloServlet.java
            └── webapp
                ├── WEB-INF
                │   └── web.xml
                └── index.jsp
    
    
  5. Jalankan mvn install di direktori project aplikasi Anda untuk membuat file WAR HelloWorldApp-1.0.war di direktori target.

Menggunakan Dockerfile untuk men-deploy aplikasi Anda (direkomendasikan)

Runtime kustom cocok untuk platform yang mendukung container kustom, seperti runtime kustom App Engine. Runtime kustom memberikan fleksibilitas dengan memungkinkan Anda mengonfigurasi lingkungan runtime. Untuk contoh panduan penerapan runtime kustom, lihat Membuat aplikasi runtime kustom di lingkungan fleksibel App Engine.

Petunjuk berikut menjelaskan cara membuat container aplikasi Java 8 menggunakan Dockerfile:

  1. Siapkan aplikasi web Java 8 Anda (file WAR)
  2. Bangun image container dan kirimkan ke Artifact Registry
  3. Men-deploy aplikasi Anda

Bangun image container dan kirimkan ke Artifact Registry

Bagian ini menjelaskan cara membangun image Docker menggunakan Cloud Build dan mengirimkannya ke repositori Artifact Registry. Ikuti langkah-langkah berikut untuk membuat image penampung aplikasi Anda:

  1. Buat file cloudbuild.yaml di direktori sumber Anda untuk membangun image Docker dan mengirim ke Artifact Registry:

    steps:
    # Step 1: Build the Docker image
    - name: "gcr.io/cloud-builders/docker"
        args:
        - "build"
        - "-t"
        - "$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION"
        - "."
    
    # Step 2: Push the Docker image to Artifact Registry
    - name: "gcr.io/cloud-builders/docker"
        args:
        - "push"
        - "$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION"
    
    images:
    - "$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION"
    

    Ganti:

    • LOCATION dengan Google Cloud region tempat Anda men-deploy aplikasi.
    • PROJECT dengan Google Cloud project ID Anda.
    • REPOSITORY dengan nama repositori Artifact Registry Anda.
    • IMAGE dengan URL image container Anda.
    • TAG dengan tag image container Anda.
  2. Buat Dockerfile dengan konfigurasi berikut:

    
    # Use Maven to build the project with JDK 8
    FROM maven:3.8.6-openjdk-8 AS build
    
    # Set working directory
    WORKDIR /app
    
    # Copy the application source code
    COPY . .
    
    # Build the application
    RUN mvn clean package
    
    # Use Jetty as the runtime
    FROM jetty:9.4-jdk8
    
    # Set Jetty working directory
    WORKDIR /var/lib/jetty/webapps
    
    # Copy the built WAR file
    COPY --from=build /app/target/*.war ./ROOT.war
    
    # Expose the default Jetty port
    EXPOSE 8080
    
    # Start Jetty correctly
    CMD ["java", "-Djetty.base=/var/lib/jetty", "-jar", "/usr/local/jetty/start.jar"]
  3. Download dan instal Docker untuk menguji aplikasi contoh, dan jalankan container Hello World di komputer lokal.

  4. Bangun image container dan kirimkan ke Artifact Registry:

    gcloud builds submit .
    

Men-deploy aplikasi Anda

Untuk men-deploy aplikasi App Engine Anda:

  1. Konfigurasi file app.yaml untuk menggunakan runtime kustom di direktori sumber:

    runtime: custom
    env: flex
    instance_class: F1
    
    handlers:
      - url: /.*
        script: auto

    Direktori project Anda akan terlihat seperti struktur berikut:

    ├── Dockerfile
    ├── README.md
    ├── app.yaml
    ├── cloudbuild.yaml
    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── com
            │       └── example
            │           └── HelloServlet.java
            └── webapp
                ├── WEB-INF
                │   └── web.xml
                └── index.jsp
    
  2. Deploy aplikasi Anda menggunakan perintah gcloud app deploy:

    gcloud app deploy --image-url=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:tag
    

    Ganti:

    • LOCATION dengan Google Cloud region tempat Anda men-deploy aplikasi.
    • PROJECT dengan Google Cloud project ID Anda.
    • REPOSITORY dengan nama repositori Artifact Registry Anda.
    • IMAGE dengan URL image container Anda.
    • TAG dengan tag image container Anda.

Menggunakan runtime Java tersemat

Petunjuk berikut menunjukkan cara memaketkan ulang aplikasi Java 8 App Engine dengan server tersemat (Jetty) untuk dijalankan sebagai JAR mandiri di runtime Java yang didukung:

  1. Membuat server Jetty tersemat
  2. Siapkan aplikasi web Java 8 Anda (file WAR)
  3. Jalankan file WAR dengan Jetty tersemat dan deploy aplikasi Anda

Membuat server Jetty Tersemat

Untuk memaketkan file WAR aplikasi Anda dengan server Jetty yang disematkan, ikuti langkah-langkah berikut:

  1. Buat class Main untuk melakukan inisialisasi dan mengonfigurasi server Jetty agar menjalankan file WAR Anda. Class Main menyiapkan port server yang secara default adalah 8080. Anda juga dapat mengubah kode sumber untuk menggunakan port yang ditentukan dalam variabel lingkungan PORT. Class Main mengonfigurasi pengendali WebAppContext untuk menayangkan file WAR Anda:

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.webapp.Configuration.ClassList;
    import org.eclipse.jetty.webapp.WebAppContext;
    
    /** Simple Jetty Main that can execute a WAR file when passed as an argument. */
    public class Main {
    
      public static void main(String[] args) throws Exception {
        if (args.length != 1) {
          System.err.println("Usage: need a relative path to the war file to execute");
          System.exit(1);
        }
        System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StrErrLog");
        System.setProperty("org.eclipse.jetty.LEVEL", "INFO");
    
        // Create a basic Jetty server object that will listen on port defined by
        // the PORT environment variable when present, otherwise on 8080.
        int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
        Server server = new Server(port);
    
        // The WebAppContext is the interface to provide configuration for a web
        // application. In this example, the context path is being set to "/" so
        // it is suitable for serving root context requests.
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        webapp.setWar(args[0]);
        ClassList classlist = ClassList.setServerDefault(server);
    
        // Enable Annotation Scanning.
        classlist.addBefore(
            "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
            "org.eclipse.jetty.annotations.AnnotationConfiguration");
    
        // Set the the WebAppContext as the ContextHandler for the server.
        server.setHandler(webapp);
    
        // Start the server! By using the server.join() the server thread will
        // join with the current thread. See
        // "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()"
        // for more details.
        server.start();
        server.join();
      }
    }
  2. Buat file project Maven pom.xml dan tambahkan konfigurasi berikut:

    1. Tetapkan properti maven.compiler.source dan maven.compiler.target ke runtime Java yang didukung:

      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <jetty.version>9.4.57.v20241219</jetty.version>
      </properties>
    2. Tambahkan dependensi untuk Jetty:

      <dependencies>
        <!-- Embedded Jetty dependencies -->
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-server</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-webapp</artifactId>
          <version>${jetty.version}</version>
          <type>jar</type>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-util</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-annotations</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <!-- extra explicit dependency needed because there is a JSP in the sample-->
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>apache-jsp</artifactId>
          <version>${jetty.version}</version>
        </dependency>
      </dependencies>
    3. Konfigurasi properti maven-assembly-plugin ke dependensi paket:

      
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <finalName>jetty</finalName>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.example.appengine.jetty.Main</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      

    Direktori project Anda akan terlihat seperti struktur berikut:

    ├─src
    │  └─main
    │      └─java
    │          └─jetty
    │              └─Main.java
    └─pom.xml
    
  3. Jalankan perintah mvn install di direktori project peluncur Jetty. Tindakan ini akan membuat jetty-jar-with-dependencies.jar di direktori target Anda.

  4. Ikuti petunjuk di bagian Siapkan aplikasi web Java 8 (file WAR) untuk membuat file WAR.

Jalankan file WAR dengan Jetty tersemat dan deploy aplikasi Anda

Bagian ini memberikan langkah-langkah untuk mengemas aplikasi Anda ke dalam file JAR yang dapat dieksekusi. Ikuti petunjuk berikut untuk mengemas dan men-deploy aplikasi Anda:

  1. Tempatkan JAR runner Jetty yang dihasilkan jetty-jar-with-dependencies.jar dan file WAR aplikasi Anda HelloWorldApp-1.0.war di direktori yang sama.

  2. Jalankan aplikasi menggunakan runtime Java yang didukung:

        java -jar jetty-jar-with-dependencies.jar HelloWorldApp-1.0.war
    
    1. Di browser web Anda, buka http://localhost:8080. Anda akan melihat halaman selamat datang aplikasi.
  3. Buat elemen entrypoint dalam file app.yaml untuk memanggil file jetty-jar-with-dependencies, dan teruskan file WAR sebagai argumen. Versi yang Anda tentukan dalam file WAR harus sama dengan versi file pom.xml:

    runtime: java
    env: flex
    runtime_config:
      operating_system: ubuntu22
      runtime_version: 21
    entrypoint: "java -jar jetty-jar-with-dependencies.jar sample.war"
    handlers:
      - url: /.*
        script: this field is required, but ignored
    
    manual_scaling:
      instances: 1
  4. Deploy aplikasi Anda menggunakan perintah gcloud app deploy.