尝试修改现有的Java / Tomcat应用程序,以便在Heroku之后tutorial进行部署,并遇到AppAssembler未找到入门类的问题。运行目标/ 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没有使用正确的类路径,有什么建议吗?
答案 0 :(得分:6)
您的工件包装必须设置为jar
,否则找不到主类。
<pom>
...
<packaging>jar</packaging>
...
</pom>
工件本身会添加在类路径的末尾,因此除了JAR文件之外什么都不会产生任何影响。
答案 1 :(得分:3)
尝试:
mvn clean package jar:jar appassembler:assemble
答案 2 :(得分:1)
首先,您使用的是appassembler-maven-plugin的旧版本,当前版本为1.3。
我不明白为什么要定义
<assembleDirectory>target</assembleDirectory>
文件夹。这有一个很好的默认值。所以通常你不需要它。除此之外,您不需要定义绑定到包阶段的显式执行,导致appassembler-maven-plugin is by default bound to the package phase。
此外,您可以使用useWildcardClassPath配置选项缩短类路径。
<configuration>
<useWildcardClassPath>true</useWildcardClassPath>
<repositoryLayout>flat</repositoryLayout>
...
</configruation>
调用生成的脚本显示错误取决于文件夹中所有依赖项所在的存储库位置与定义的生成脚本中的位置不同。
答案 3 :(得分:1)
能够通过将"$BASEDIR"/classes
添加到生成的脚本中的CLASSPATH行来解决此问题。由于脚本在每次调用mvn package
时被重写,我编写了一个调用mvn package
的短脚本,然后添加了所需的类路径条目。
显然有点像黑客,但经过8个多小时尝试更“正确”的解决方案后,现在必须这样做。肯定会采用任何更优雅的方式来纠正这里建议的类路径。
答案 4 :(得分:1)
答案 5 :(得分:1)
前一段时间我正在阅读该教程,并且遇到了非常类似的问题。我采用了一种不同的方法,非常适合我。
首先,正如之前提到的那样,您需要将POM的类型保持为jar
(<packaging>jar</packaging>
) - 多亏了这一点,appassembler
插件将生成一个JAR文件您的类并将其添加到类路径中。所以,多亏了你的错误就会消失。
请注意,本教程Tomcat是从应用程序源目录实例化的。在许多情况下这已经足够了,但请注意,使用该方法,您将无法使用Servlet @WebServlet
注释,因为源中的/WEB-INF/classes
为空,Tomcat将无法扫描您的servlet类。所以来自该教程的HelloServlet
servlet将无法工作,除非您按照here所述添加一些额外的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-plugin
插件之前包含appassembler
:
...
<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生成一个工件。在你的情况下,应该有两个工件:
两者都应该构建为单独的POM,并作为父POM中的模块引用。如果你看一下该教程的复杂性,将它分成两个模块没有多大意义。但是如果你的应用程序变得越来越复杂(并且启动器获得了一些额外的配置等),那么进行“拆分”将会很有意义。事实上,已经创建了一些“Tomcat启动程序”库,所以你可以使用它们。