7

尝试按照他们的教程修改现有的 Java/Tomcat 应用程序以在 Heroku 上部署,并遇到 AppAssembler 找不到入口类的一些问题。运行 target/bin/webapp(或部署到 Heroku)会导致Error: Could not find or load main class org.stopbadware.dsp.Main

但是,执行java -cp target/classes:target/dependency/* org.stopbadware.dsp.Main运行正常。这是 pom.xml 的相关部分:

  <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>appassembler-maven-plugin</artifactId>
      <version>1.1.1</version>
      <configuration>
          <assembleDirectory>target</assembleDirectory>
          <programs>
              <program>
                  <mainClass>org.stopbadware.dsp.Main</mainClass>
                  <name>webapp</name>
              </program>
          </programs>
      </configuration>
      <executions>
          <execution>
              <phase>package</phase>
              <goals>
                  <goal>assemble</goal>
              </goals>
          </execution>
      </executions>
    </plugin>

我的猜测是mvn package导致 AppAssembler 不使用正确的类路径,有什么建议吗?

4

6 回答 6

6

您的工件的包装必须设置为jar,否则找不到主类。

<pom>
  ...
  <packaging>jar</packaging>
  ...
</pom>

工件本身被添加到类路径的末尾,因此除了 JAR 文件之外没有任何效果。

于 2013-12-02T16:49:44.697 回答
3

尝试:

mvn clean package jar:jar appassembler:assemble
于 2013-11-03T00:26:43.223 回答
1

首先,您使用的是旧版本的appassembler-maven-plugin,当前版本是 1.3。

我不明白你为什么要定义

<assembleDirectory>target</assembleDirectory>

文件夹。有一个很好的默认值。所以通常你不需要它。除此之外,您不需要定义绑定到包阶段的显式执行,因为appassembler-maven-plugin 默认绑定到包阶段

此外,您可以使用useWildcardClassPath配置选项来缩短您的类路径。

   <configuration>
     <useWildcardClassPath>true</useWildcardClassPath>
     <repositoryLayout>flat</repositoryLayout>
     ...
   </configruation>

并且生成的脚本的调用显示错误取决于文件夹中所有依赖项所在的存储库的位置与定义的生成脚本中的位置不同。

于 2013-03-06T10:06:30.890 回答
1

"$BASEDIR"/classes能够通过添加到生成的脚本中的 CLASSPATH 行来解决这个问题。由于脚本在每次调用时都会被重写,mvn package所以我编写了一个简短的脚本来调用mvn package然后添加所需的类路径条目。

显然有点破解,但经过 8 个多小时的尝试更“正确”的解决方案,现在必须这样做。肯定会采用更优雅的方式来纠正此处建议的类路径。

于 2013-03-06T14:24:52.083 回答
1

您可以设置CLASSPATH_PREFIX环境变量:

export CLASSPATH_PREFIX=target/classes

它将被添加到生成脚本的类路径中。

于 2013-12-31T21:53:50.313 回答
1

前段时间我正在阅读该教程并且遇到了非常相似的问题。我采用了一种不同的方法,它对我非常有效。

首先,如前所述,您需要将 POM 的类型保持为jar( <packaging>jar</packaging>) - 因此,appassembler插件将从您的类生成一个 JAR 文件并将其添加到类路径中。因此,多亏了这一点,您的错误就会消失。

请注意,本教程 Tomcat 是从应用程序源目录中实例化的。在很多情况下这就足够了,但是请注意,使用这种方法,您将无法使用 Servlet@WebServlet注释,因为/WEB-INF/classes源代码是空的,并且 Tomcat 将无法扫描您的 servlet 类。因此HelloServlet,该教程中的 servlet 将不起作用,除非您按照此处所述添加一些额外的 Tomcat 初始化(资源配置) (顺便说一句,您会发现更多关于该资源配置的 SO 问题)。

我做了一些不同的方法:

我在此期间运行一个org.apache.maven.plugins:maven-war-plugin插件(exploded目标)package并将该生成的目录用作我的应用程序的源目录。使用这种方法,我的 Web 应用程序目录将/WEB-INF/classes“填充”类。这反过来将允许 Tomcat 正确执行扫描作业(即 Servlet@WebServlet注释将起作用)。

我还必须在启动器类中更改我的应用程序的源:

public static void main(String[] args) throws Exception {
    // Web application is generated in directory name as specified in build/finalName
    // in maven pom.xml
    String webappDirLocation = "target/embeddedTomcatSample/";
    Tomcat tomcat = new Tomcat();

    // ... remaining code does not change

我添加的对 POM 的更改 - 包括maven-war-pluginappassembler插件之前:

...
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.5</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>exploded</goal>
            </goals>
        </execution>
    </executions>
</plugin>
...

请注意,exploded目标被调用。

我希望小小的改变对你有所帮助。


关于该教程和 maven 构建的另一条评论:请注意,编写该教程是为了展示构建应用程序并在 Heroku 中运行它是多么简单。但是,这不是 Maven 构建的最佳方法。

Maven 建议您应该坚持每个 POM 生成一个工件。在您的情况下,应该有两个工件:

  • Tomcat 启动器
  • Tomcat Web 应用程序

两者都应该构建为单独的 POM,并作为来自父 POM 的模块引用。如果您查看该教程的复杂性,则将其拆分为两个模块没有多大意义。但是,如果您的应用程序变得越来越复杂(并且启动器获得了一些额外的配置等),那么进行“拆分”将很有意义。事实上,已经创建了一些“Tomcat 启动器”库,因此您也可以使用其中的一个。

于 2014-12-22T14:26:07.350 回答