Java 11 Cloud SDK 的 appengine:run 是什么?
What's the equivalent of appengine:run for the Java 11 Cloud SDK?
tl;dr: 我怎么能 运行 this project locally, in a way that Datastore will work? (Zip download link here.)
我正在将使用 App Engine 和 Datastore 的 Java 8 项目迁移到 Java 11。
使用 Java 8,我使用基于 Cloud SDK 的 App Engine plugin 使用 mvn appengine:run
在本地 运行 服务器并使用 [= 部署到实时服务器18=].
我按照 this guide 告诉我删除 appengine-web.xml
文件并改用 app.yaml
..
要部署到实时服务器,我仍然可以使用 mvn appengine:deploy
,无论是否使用 Datastore,都可以正常工作。
要在本地部署,我 运行 mvn package exec:java
。这适用于 运行 没有 Datastore 的基本服务器,但如果我添加一些 example Datastore code,则会出现此错误:
java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder.
我知道这是因为我没有本地 App Engine 环境 运行ning。但是,如果我尝试使用 mvn appengine:run
运行 本地服务器,则会收到此错误,抱怨缺少 appengine-web.xml
文件:
[ERROR] Failed to execute goal com.google.cloud.tools:appengine-maven-plugin:2.2.0:run (default-cli) on project datastore-hello-world:
Failed to run devappserver: java.nio.file.NoSuchFileException:
C:\Users\kevin\Documents\GitHub\HappyCoding\examples\google-cloud\google-cloud-example-projects\datastore-hello-world\target\datastore-hello-world-1\WEB-INF\appengine-web.xml -> [Help 1]
所以我在需要 运行 mvn appengine:run
需要 appengine-web.xml
和需要更新到 Java 11 之间徘徊,后者表示要使用 [=20] =] 而不是 appengine-web.xml
.
Java 11 App Engine docs 本地只说 运行ning:
To test your application's functionality before deploying, run your application in your local environment with the development tools that you usually use.
以上 GitHub and zip 链接包含整个项目(总共 5 个文件),但为了将我的代码直接包含在问题中,以下是最重要的文件:
pom.xml
<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>io.happycoding</groupId>
<artifactId>datastore-hello-world</artifactId>
<version>1</version>
<properties>
<!-- App Engine currently supports Java 11 -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.version>9.4.31.v20200723</jetty.version>
<!-- Project-specific properties -->
<mainClass>io.happycoding.ServerMain</mainClass>
<googleCloudProjectId>YOUR_PROJECT_ID_HERE</googleCloudProjectId>
</properties>
<dependencies>
<!-- Java Servlets API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${jetty.version}</version>
</dependency>
<!-- Datastore -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-datastore</artifactId>
<version>1.104.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Copy static resources like html files into the output jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-web-resources</id>
<phase>compile</phase>
<goals><goal>copy-resources</goal></goals>
<configuration>
<outputDirectory>
${project.build.directory}/classes/META-INF/resources
</outputDirectory>
<resources>
<resource><directory>./src/main/webapp</directory></resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Package everything into a single executable jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainClass}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- Exec plugin for deploying the local server. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
<!-- App Engine plugin for deploying to the live site. -->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>${googleCloudProjectId}</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
ServerMain.java
package io.happycoding;
import java.net.URL;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/**
* Starts up the server, including a DefaultServlet that handles static files,
* and any servlet classes annotated with the @WebServlet annotation.
*/
public class ServerMain {
public static void main(String[] args) throws Exception {
// Create a server that listens on port 8080.
Server server = new Server(8080);
WebAppContext webAppContext = new WebAppContext();
server.setHandler(webAppContext);
// Load static content from inside the jar file.
URL webAppDir =
ServerMain.class.getClassLoader().getResource("META-INF/resources");
webAppContext.setResourceBase(webAppDir.toURI().toString());
// Enable annotations so the server sees classes annotated with @WebServlet.
webAppContext.setConfigurations(new Configuration[]{
new AnnotationConfiguration(),
new WebInfConfiguration(),
});
// Look for annotations in the classes directory (dev server) and in the
// jar file (live server)
webAppContext.setAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/target/classes/|.*\.jar");
// Handle static resources, e.g. html files.
webAppContext.addServlet(DefaultServlet.class, "/");
// Start the server!
server.start();
System.out.println("Server started!");
// Keep the main thread alive while the server is running.
server.join();
}
}
HelloWorldServlet.java
package io.happycoding.servlets;
import com.google.cloud.datastore.Datastore;
import com.google.cloud.datastore.DatastoreOptions;
import com.google.cloud.datastore.Entity;
import com.google.cloud.datastore.Key;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Datastore datastore = DatastoreOptions.getDefaultInstance().getService();
String kind = "Task";
// The name/ID for the new entity
String name = "sampletask1";
// The Cloud Datastore key for the new entity
Key taskKey = datastore.newKeyFactory().setKind(kind).newKey(name);
// Prepares the new entity
Entity task = Entity.newBuilder(taskKey)
.set("description", "Buy milk")
.build();
// Saves the entity
datastore.put(task);
System.out.printf("Saved %s: %s%n", task.getKey().getName(), task.getString("description"));
//Retrieve entity
Entity retrieved = datastore.get(taskKey);
response.setContentType("text/html;");
response.getWriter().println("<h1>Hello world!</h1>");
response.getWriter().println("Retrieved: " + taskKey.getName() + ": " + retrieved.getString("description"));
}
}
如何在本地 运行 Java 11 App Engine 服务器以便 Datastore 正常工作?
基于 guillaume blaquiere's suggestion in their , I tried following this guide 在本地手动 运行ning 数据存储。
我在一个命令行中 运行 gcloud beta emulators datastore start
,这似乎 运行 没问题,然后我在另一个命令行中 运行 $(gcloud beta emulators datastore env-init)
,并且我收到此错误:
ERROR: (gcloud.beta.emulators.datastore.env-init)
Unable to find env.yaml in the data_dir
[/tmp/tmp.zolNZC8fnr/emulators/datastore].
Please ensure you have started the appropriate emulator.
我回到 运行 数据存储所在的第一个命令行,我注意到输出中的这一行:
Storage: /tmp/tmp.sxkNeaNHxo/emulators/datastore/WEB-INF/appengine-generated/local_db.bin
我将该目录路径复制到 data-dir
参数中:
$(gcloud beta emulators datastore env-init --data-dir=/tmp/tmp.sxkNeaNHxo/emulators/datastore)
该命令似乎成功了(没有输出)所以我 运行 我的本地服务器:mvn package exec:java
最后,这似乎在本地有效。
总结一下:
步骤 1: 运行 此命令:gcloud beta emulators datastore start
第 2 步: 在输出中,找到如下所示的行:
Storage: /tmp/tmp.sxkNeaNHxo/emulators/datastore/WEB-INF/appengine-generated/local_db.bin
复制 /tmp/tmp.YOUR_PATH_HERE/emulators/datastore
路径。
第三步:在不同的命令行中,运行这条命令,粘贴到刚刚复制的路径中:
$(gcloud beta emulators datastore env-init --data-dir=/tmp/tmp.YOUR_PATH_HERE/emulators/datastore)
第 4 步: 在第二个命令行中,运行 您的本地服务器:mvn package exec:java
这感觉很复杂(而且没有记录),所以我仍然非常愿意接受有关如何简化它的建议。但就目前而言,这至少有效。
tl;dr: 我怎么能 运行 this project locally, in a way that Datastore will work? (Zip download link here.)
我正在将使用 App Engine 和 Datastore 的 Java 8 项目迁移到 Java 11。
使用 Java 8,我使用基于 Cloud SDK 的 App Engine plugin 使用 mvn appengine:run
在本地 运行 服务器并使用 [= 部署到实时服务器18=].
我按照 this guide 告诉我删除 appengine-web.xml
文件并改用 app.yaml
..
要部署到实时服务器,我仍然可以使用 mvn appengine:deploy
,无论是否使用 Datastore,都可以正常工作。
要在本地部署,我 运行 mvn package exec:java
。这适用于 运行 没有 Datastore 的基本服务器,但如果我添加一些 example Datastore code,则会出现此错误:
java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder.
我知道这是因为我没有本地 App Engine 环境 运行ning。但是,如果我尝试使用 mvn appengine:run
运行 本地服务器,则会收到此错误,抱怨缺少 appengine-web.xml
文件:
[ERROR] Failed to execute goal com.google.cloud.tools:appengine-maven-plugin:2.2.0:run (default-cli) on project datastore-hello-world:
Failed to run devappserver: java.nio.file.NoSuchFileException:
C:\Users\kevin\Documents\GitHub\HappyCoding\examples\google-cloud\google-cloud-example-projects\datastore-hello-world\target\datastore-hello-world-1\WEB-INF\appengine-web.xml -> [Help 1]
所以我在需要 运行 mvn appengine:run
需要 appengine-web.xml
和需要更新到 Java 11 之间徘徊,后者表示要使用 [=20] =] 而不是 appengine-web.xml
.
Java 11 App Engine docs 本地只说 运行ning:
To test your application's functionality before deploying, run your application in your local environment with the development tools that you usually use.
以上 GitHub and zip 链接包含整个项目(总共 5 个文件),但为了将我的代码直接包含在问题中,以下是最重要的文件:
pom.xml
<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>io.happycoding</groupId>
<artifactId>datastore-hello-world</artifactId>
<version>1</version>
<properties>
<!-- App Engine currently supports Java 11 -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.version>9.4.31.v20200723</jetty.version>
<!-- Project-specific properties -->
<mainClass>io.happycoding.ServerMain</mainClass>
<googleCloudProjectId>YOUR_PROJECT_ID_HERE</googleCloudProjectId>
</properties>
<dependencies>
<!-- Java Servlets API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${jetty.version}</version>
</dependency>
<!-- Datastore -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-datastore</artifactId>
<version>1.104.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Copy static resources like html files into the output jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-web-resources</id>
<phase>compile</phase>
<goals><goal>copy-resources</goal></goals>
<configuration>
<outputDirectory>
${project.build.directory}/classes/META-INF/resources
</outputDirectory>
<resources>
<resource><directory>./src/main/webapp</directory></resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Package everything into a single executable jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainClass}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- Exec plugin for deploying the local server. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
<!-- App Engine plugin for deploying to the live site. -->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>${googleCloudProjectId}</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
ServerMain.java
package io.happycoding;
import java.net.URL;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/**
* Starts up the server, including a DefaultServlet that handles static files,
* and any servlet classes annotated with the @WebServlet annotation.
*/
public class ServerMain {
public static void main(String[] args) throws Exception {
// Create a server that listens on port 8080.
Server server = new Server(8080);
WebAppContext webAppContext = new WebAppContext();
server.setHandler(webAppContext);
// Load static content from inside the jar file.
URL webAppDir =
ServerMain.class.getClassLoader().getResource("META-INF/resources");
webAppContext.setResourceBase(webAppDir.toURI().toString());
// Enable annotations so the server sees classes annotated with @WebServlet.
webAppContext.setConfigurations(new Configuration[]{
new AnnotationConfiguration(),
new WebInfConfiguration(),
});
// Look for annotations in the classes directory (dev server) and in the
// jar file (live server)
webAppContext.setAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/target/classes/|.*\.jar");
// Handle static resources, e.g. html files.
webAppContext.addServlet(DefaultServlet.class, "/");
// Start the server!
server.start();
System.out.println("Server started!");
// Keep the main thread alive while the server is running.
server.join();
}
}
HelloWorldServlet.java
package io.happycoding.servlets;
import com.google.cloud.datastore.Datastore;
import com.google.cloud.datastore.DatastoreOptions;
import com.google.cloud.datastore.Entity;
import com.google.cloud.datastore.Key;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Datastore datastore = DatastoreOptions.getDefaultInstance().getService();
String kind = "Task";
// The name/ID for the new entity
String name = "sampletask1";
// The Cloud Datastore key for the new entity
Key taskKey = datastore.newKeyFactory().setKind(kind).newKey(name);
// Prepares the new entity
Entity task = Entity.newBuilder(taskKey)
.set("description", "Buy milk")
.build();
// Saves the entity
datastore.put(task);
System.out.printf("Saved %s: %s%n", task.getKey().getName(), task.getString("description"));
//Retrieve entity
Entity retrieved = datastore.get(taskKey);
response.setContentType("text/html;");
response.getWriter().println("<h1>Hello world!</h1>");
response.getWriter().println("Retrieved: " + taskKey.getName() + ": " + retrieved.getString("description"));
}
}
如何在本地 运行 Java 11 App Engine 服务器以便 Datastore 正常工作?
基于 guillaume blaquiere's suggestion in their
我在一个命令行中 运行 gcloud beta emulators datastore start
,这似乎 运行 没问题,然后我在另一个命令行中 运行 $(gcloud beta emulators datastore env-init)
,并且我收到此错误:
ERROR: (gcloud.beta.emulators.datastore.env-init)
Unable to find env.yaml in the data_dir
[/tmp/tmp.zolNZC8fnr/emulators/datastore].
Please ensure you have started the appropriate emulator.
我回到 运行 数据存储所在的第一个命令行,我注意到输出中的这一行:
Storage: /tmp/tmp.sxkNeaNHxo/emulators/datastore/WEB-INF/appengine-generated/local_db.bin
我将该目录路径复制到 data-dir
参数中:
$(gcloud beta emulators datastore env-init --data-dir=/tmp/tmp.sxkNeaNHxo/emulators/datastore)
该命令似乎成功了(没有输出)所以我 运行 我的本地服务器:mvn package exec:java
最后,这似乎在本地有效。
总结一下:
步骤 1: 运行 此命令:gcloud beta emulators datastore start
第 2 步: 在输出中,找到如下所示的行:
Storage: /tmp/tmp.sxkNeaNHxo/emulators/datastore/WEB-INF/appengine-generated/local_db.bin
复制 /tmp/tmp.YOUR_PATH_HERE/emulators/datastore
路径。
第三步:在不同的命令行中,运行这条命令,粘贴到刚刚复制的路径中:
$(gcloud beta emulators datastore env-init --data-dir=/tmp/tmp.YOUR_PATH_HERE/emulators/datastore)
第 4 步: 在第二个命令行中,运行 您的本地服务器:mvn package exec:java
这感觉很复杂(而且没有记录),所以我仍然非常愿意接受有关如何简化它的建议。但就目前而言,这至少有效。