gpt4 book ai didi

java - App Engine Java 11 无法在实时服务器上找到或加载主类

转载 作者:行者123 更新时间:2023-12-01 11:55:29 24 4
gpt4 key购买 nike

tl;博士:为什么这在本地有效,但在我部署到我的实时 App Engine 项目时无效?
我正在尝试使用 Java 11 版本的 App Engine 创建一个基于 servlet 的准系统 Web 应用程序。在 this guide 之后,我正在将一些项目从 Java 8 更新到 Java 11 .我也在用 this guidethis example .我的目标是使用 Jetty 运行一个非常简单的 Web 应用程序,该应用程序在 App Engine 中提供单个静态 HTML 文件和单个 servlet 文件。
当我在本地运行时,我的网络应用程序运行良好:

mvn clean install
mvn exec:java -Dexec.args="target/app-engine-hello-world-1.war"
当我运行这些命令时,我的 index.html并且我的 servlet URL 工作正常。
但是当我部署到我的实时站点时:
mvn package appengine:deploy
...命令成功,但是当我导航到我的实时 URL 时,HTML 文件和 servlet URL 均出现此错误: "Error: Server Error. The server encountered an error and could not complete your request. Please try again in 30 seconds."如果我查看 Cloud 控制台中的日志,则会看到以下错误:
Error: Could not find or load main class io.happycoding.Main
Caused by: java.lang.ClassNotFoundException: io.happycoding.Main
我的设置有问题,但我没有看到任何明显的错误。
这是我项目中的文件:
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>app-engine-hello-world</artifactId>
<version>1</version>
<packaging>war</packaging>

<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>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>

</dependencies>

<build>
<plugins>

<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>io.happycoding.Main</mainClass>
</configuration>
</plugin>

<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>happy-coding-gcloud</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/main/appengine/app.yaml
runtime: java11
entrypoint: 'java -cp "*" io.happycoding.Main app-engine-hello-world-1.war'
src/main/java/io/happycoding/Main.java
package io.happycoding;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.webapp.Configuration.ClassList;
import org.eclipse.jetty.webapp.WebAppContext;
import io.happycoding.servlets.HelloWorldServlet;

/** 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");

Server server = new Server(8080);

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");

server.setHandler(webapp);
server.join();
}
}
src/main/webapp/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Google Cloud Hello World</title>
</head>
<body>
<h1>Google Cloud Hello World</h1>
<p>This is a sample HTML file. Click <a href="/hello">here</a> to see content served from a servlet.</p>
<p>Learn more at <a href="https://happycoding.io">HappyCoding.io</a>.</p>
</body>
</html>
src/main/java/io/happycoding/servlets/HelloWorldServlet.java
package io.happycoding.servlets;

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 {
response.setContentType("text/html;");
response.getOutputStream().println("<h1>Hello world!</h1>");
}
}
我猜我如何设置实时站点的类路径有问题,但我没有看到任何明显的错误。
packaging房产在 pom.xml设置为 war , 我得到一个 .war包含以下内容的文件:
index.html
META-INF/MANIFEST.MF
META-INF/maven/io.happycoding/app-engine-hello-world/pom.properties
META-INF/maven/io.happycoding/app-engine-hello-world/pom.xml
WEB-INF/classes/io/happycoding/Main.class
WEB-INF/classes/io/happycoding/servlets/HelloWorldServlet.class
WEB-INF/classes/lib/asm-7.3.1.jar
WEB-INF/classes/lib/asm-analysis-7.3.1.jar
WEB-INF/classes/lib/asm-commons-7.3.1.jar
WEB-INF/classes/lib/asm-tree-7.3.1.jar
WEB-INF/classes/lib/javax.annotation-api-1.3.jar
WEB-INF/classes/lib/javax.servlet-api-4.0.1.jar
WEB-INF/classes/lib/jetty-annotations-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-http-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-io-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-jndi-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-plus-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-security-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-server-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-servlet-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-util-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-webapp-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-xml-9.4.31.v20200723.jar
如果我更改 packaging房产在 pom.xmljar ,然后我得到一个 .jar包含以下内容的文件:
io/happycoding/Main.class
io/happycoding/servlets/HelloWorldServlet.class
META-INF/MANIFEST.MF
META-INF/maven/io.happycoding/app-engine-hello-world/pom.properties
META-INF/maven/io.happycoding/app-engine-hello-world/pom.xml
我在实时站点的日志中收到此错误:
Error: Unable to initialize main class io.happycoding.Main 
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler
这感觉像是进步,但后来我的实时服务器也出现了 404 错误,所以我觉得很卡。
我需要对上述设置进行哪些更改才能使其在本地和我的实时服务器上都能正常工作?
编辑:我可以在 App Engine 调试器中看到以下文件:
app engine files
我尝试将此添加到我的 pom.xml文件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</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 调试器中看到这些文件:
app engine files
但我仍然得到同样的错误。
我相信问题是由我的 Main 引起的类(class)在 .war 内对类路径没有影响的文件,这就是找不到它的原因。
我如何打包我的项目以便它在本地和我的实时服务器上工作?

最佳答案

我认为您的问题是您包含了 Main war 本身中的类,而 App Engine 无法找到它。
正如您在 GCP migration guide 中看到的那样, Main类在名为 simple-jetty-main 的外部依赖项中定义.
随着 maven-dependency-plugin 的执行这个依赖被复制到 appengine-staging目录,使其可以从 Java 类路径访问。
这就是为什么Main执行来自 app.yaml 的命令时,可以在指南中建议的示例中找到类。 entrypoint :

entrypoint: 'java -cp "*" com.example.appengine.demo.jettymain.Main helloworld.war'
因此,解决方案将包括您的 Main另一个库中的类,独立于您需要部署的 war 文件。
也许您可以创建一个库 - 就像 Google 对 simple-jetty-main 所做的那样- 可以在您的 GCP 项目中重复用于此任务。
只是为了测试,为了确认这一点,你可以使用 simple-jetty-main库本身(您可以从 https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine-java11/appengine-simple-jetty-main 克隆所需的代码)。安装它,在你的 pom.xml 中包含依赖项,还包括 maven-dependency-plugin ,并定义您的 entrypoint如下:
entrypoint: 'java -cp "*" com.example.appengine.demo.jettymain.Main app-engine-hello-world-1.war'
对于您的评论,您将不希望 Main 之间有分隔符。类和其余代码。
要满足该要求,我们必须首先更改 Main类以便 Jetty 可以服务 HelloWorldSevlet和静态内容。该代码实际上与您提供的代码非常相似。请原谅设置的简单性,它基于 web.xml文件;如有必要,可以进行进一步的开发以处理注释或任何认为合适的内容:
package io.happycoding;

import java.net.URL;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;

public class Main {

public static final String WEBAPP_RESOURCES_LOCATION = "META-INF/resources";

public static void main(String[] args) throws Exception {
System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StrErrLog");
System.setProperty("org.eclipse.jetty.LEVEL", "INFO");

Server server = new Server(8080);

URL webAppDir = Thread.currentThread().getContextClassLoader().getResource(WEBAPP_RESOURCES_LOCATION);
if (webAppDir == null) {
throw new RuntimeException(String.format("Unable to find %s directory into the JAR file", WEBAPP_RESOURCES_LOCATION));
}

WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setDescriptor(WEBAPP_RESOURCES_LOCATION + "/WEB-INF/web.xml");
webAppContext.setResourceBase(webAppDir.toURI().toString());
webAppContext.setParentLoaderPriority(true);

server.setHandler(webAppContext);

server.start();

server.join();
}
}
静态资源可以从您选择的目录加载(它将在 pom.xml 中参数化)。
例如,我创建了 src/main/webapp存放静态内容的文件夹。
在这个文件夹中,您还需要定义 - 在这种情况下,由于我们设置 Jetty 的方式 - a WEB-INF与此目录 web.xml里面的文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>io.happycoding.servlets.HelloWorldServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

</web-app>
这是一个 tree我的源代码设置:
source code setup pom.xml文件与您提供的文件非常相似。我只包括了 maven-resources-plugin将 Web 应用程序静态内容复制到 jar 文件,以及 maven-shade-plugin生成一个 UberJar:
<?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>io.happycoding</groupId>
<artifactId>app-engine-hello-world</artifactId>
<version>1</version>
<packaging>jar</packaging>

<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>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- Directory where static content resides -->
<webapp.dir>./src/main/webapp</webapp.dir>
</properties>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>

</dependencies>

<build>
<plugins>
<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>io.happycoding.Main</mainClass>
</configuration>
</plugin>

<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>${webapp.dir}</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

<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>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.happycoding.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>happy-coding-gcloud</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>


</project>
通过此设置,您可以通过执行以下命令在本地运行应用程序:
mvn exec:java
您还可以直接从 java 工具在本地运行该程序:
java -jar appengine-deploy-sample-1.jar
抱歉,我无法在 GCP 中测试设置,但我认为,根据迁移指南,您可以尝试在不指明 entrypoint 的情况下部署应用程序。在您的 app.yaml .
如果它不起作用,您可以尝试通过配置 entrypoint 来运行该应用程序。类似于以下内容:
entrypoint: 'java -jar appengine-deploy-sample-1.jar'
或者可能:
entrypoint: 'java -cp "*" -jar appengine-deploy-sample-1.jar'

关于java - App Engine Java 11 无法在实时服务器上找到或加载主类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63333073/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com