WAR-Datei neu in eine JAR-Datei verpacken

In diesem Dokument wird beschrieben, wie Sie eine Java 8-Anwendung als JAR-Datei neu verpacken, um sie in den Java 11/17-Laufzeiten auszuführen.

Ihre Anwendung muss eine Main-Klasse haben, die einen Webserver startet. Dieser antwortet auf HTTP-Anfragen von dem Port, der mit der PORT-Umgebungsvariablen festgelegt wurde, in der Regel 8081.

Beispiel:

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

Beispiel für eine WAR-Migration

In der folgenden Anleitung wird gezeigt, wie Sie eine App Engine Java 8 hello-world-Anwendung als JAR-Paket zur Ausführung in der Java 11/17-Laufzeit neu verpacken.

Bei der Migration wird das Artefakt appengine-simple-jetty-main verwendet. Dadurch wird eine Main-Klasse mit einem einfachen Jetty-Webserver bereitgestellt, der eine WAR-Datei lädt und Ihre Anwendung in einer ausführbaren JAR-Datei verpackt:

  1. Klonen Sie das Artefakt des eingebetteten Jetty Server auf Ihren lokalen Computer:

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

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

  2. Wechseln Sie in das Verzeichnis, das den Beispielcode enthält:

    cd java-docs-samples/appengine-java11/appengine-simple-jetty-main/
    
  3. Installieren Sie die Abhängigkeit lokal:

    mvn install
    
  4. Fügen Sie folgenden Code in die pom.xml-Datei ein.

    • appengine-simple-jetty-main Abhängigkeit
      <dependency>
        <groupId>com.example.appengine</groupId>
        <artifactId>simple-jetty-main</artifactId>
        <version>1</version>
        <scope>provided</scope>
      </dependency>
    • maven-dependency Plug-in
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.6.1</version>
        <executions>
          <execution>
            <id>copy</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>
                ${project.build.directory}/appengine-staging
              </outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      App Engine stellt Dateien im Verzeichnis ${build.directory}/appengine-staging bereit. Wenn Sie dem Build das Plug-in maven-dependency hinzufügen, installiert App Engine die angegebenen Abhängigkeiten in den richtigen Ordner.
  5. Erstellen Sie ein entrypoint-Element in Ihrer app.yaml-Datei, um das appengine-simple-jetty-main-Objekt aufzurufen, und übergeben Sie die WAR-Datei als Argument. Die WAR-Version muss mit der Version übereinstimmen, die in der Datei pom.xml aufgeführt ist:

    runtime: java
    env: flex
    runtime_config:
      operating_system: ubuntu18
      runtime_version: 11
    entrypoint: 'java -cp "*" com.example.appengine.jetty.Main helloworld-1.war'
    handlers:
    - url: /.*
      script: this field is required, but ignored
    
    manual_scaling:
      instances: 1
  6. So führen Sie Ihre Anwendung lokal aus:

    1. Verpacken Sie Ihre Anwendung:

      mvn clean package
      
    2. Starten Sie den Server mit Ihrer WAR-Datei als Argument.

      Sie können den Server beispielsweise im helloworld-war-Beispiel starten, indem Sie den folgenden Befehl aus dem Ordner java-docs-samples/appengine-java11/appengine-simple-jetty-main/ ausführen:

      mvn exec:java -Dexec.args="../flexible/java-11/helloworld-war/target/helloworld-1.war"
      
    3. Geben Sie im Webbrowser die folgende Adresse ein:

      http://localhost:8080

  7. So stellen Sie die Anwendung mit dem Maven-Plug-in bereit:

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

    Ersetzen Sie PROJECT_ID durch die ID Ihres Google Cloud-Projekts. Wenn in der Datei pom.xml bereits Ihre Projekt-ID angegeben ist, müssen Sie das Attribut -Dapp.deploy.projectId nicht in dem von Ihnen ausgeführten Befehl einfügen.