אריזה מחדש של קובץ WAR לקובץ JAR

אם אתם מבצעים העברה לגרסה העדכנית הנתמכת של Java והאפליקציה שלכם לא משתמשת בשירותים מדור קודם, אתם צריכים לארוז מחדש את אפליקציית האינטרנט של App Engine לקובץ JAR שניתן להפעלה.

באפליקציה שלכם צריך להיות מחלקה Main שמפעילה שרת אינטרנט שמגיב לבקשות HTTP ביציאה 8080, שאולי מצוינת על ידי משתנה הסביבה PORT.

לדוגמה:

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();
  }
}

דוגמה להעברת WAR‏ (Java 21)

בהוראות הבאות מוסבר איך לארוז מחדש אפליקציית WAR של hello-world App Engine כ-JAR כדי להפעיל אותה בסביבת זמן הריצה של Java 21.

ההעברה מתבצעת באמצעות ארטיפקט appengine-simple-jetty-main. הקוד הזה מספק מחלקה מסוג Main עם שרת אינטרנט פשוט של Jetty שטוען קובץ WAR ואורז את האפליקציה שלכם לקובץ JAR שניתן להפעלה:

  1. משכפלים את ארטיפקט השרת Embedded Jetty למחשב המקומי:

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples
    

    אפשרות נוספת היא להוריד את הקובץ לדוגמה כקובץ ZIP ולחלץ אותו.

  2. עוברים לספרייה שמכילה את הקוד לדוגמה:

    cd java-docs-samples/flexible/repacking-legacy-applications/appengine-simple-jetty-main/
    
  3. יוצרים את קובץ ה-JAR של Jetty runner:

    mvn install
    

    הפעולה הזו יוצרת את jetty-jar-with-dependencies.jar בספרייה target/.

  4. מגדירים את קובץ ה-build‏ pom.xml לשרת Jetty:

    • מאפייני מהדר (Java 21):
      <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>
    • תלויות מוטמעות של 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>
    • הגדרה של maven-assembly-plugin
      
      <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>
      
  5. ממקמים את קובץ ה-jetty-jar-with-dependencies.jar שנוצר ואת קובץ ה-WAR של האפליקציה. לדוגמה, helloworld.war באותה ספרייה.

  6. יוצרים קובץ app.yaml בספריית האפליקציה כדי לציין את זמן הריצה של Java 21 ורכיב entrypoint כדי לקרוא לקובץ jetty-jar-with-dependencies.jar ולהעביר את קובץ ה-WAR כארגומנט:

    runtime: java21
    entrypoint: 'java -jar jetty-jar-with-dependencies.jar helloworld.war'
    
  7. כדי להריץ את האפליקציה באופן מקומי:

    1. מפעילים את השרת עם קובץ ה-WAR כארגומנט:

      java -jar jetty-jar-with-dependencies.jar helloworld.war
      
    2. בדפדפן האינטרנט, מזינים את הכתובת הבאה:

      http://localhost:8080

  8. כדי לפרוס את האפליקציה:

    כלי gcloud

    gcloud app deploy

    פלאגין Maven

    mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

    מחליפים את PROJECT_ID במזהה הפרויקט. Google Cloud אם קובץ pom.xml שלכם כבר מציין את מזהה הפרויקט, אין צורך לכלול את המאפיין -Dapp.deploy.projectId בפקודה שמריצים.