如何在 maven-war-plugin 中正确设置清单类路径
Posted
技术标签:
【中文标题】如何在 maven-war-plugin 中正确设置清单类路径【英文标题】:How to set up manifest class-path properly in maven-war-plugin 【发布时间】:2012-03-03 11:53:01 【问题描述】:我已将 maven-ear-plugin 与 maven-war-plugin 和 maven-ejb-plugin 一起使用,成功部署并运行打包为 EAR 到 Jboss AS7 的应用程序。
.
|-- META-INF
| |-- application.xml
| |-- MANIFEST.MF
| `-- maven
| `-- com.patrac
| `-- Patrac-ear
| |-- pom.properties
| `-- pom.xml
|-- Patrac-ejb-1.0-SNAPSHOT.jar
`-- Patrac-web-1.0-SNAPSHOT.war
在应用程序源代码目录中,pom的位置如下:
.
|
|-- Patrac-ear
| `-- pom.xml
|-- Patrac-ejb
| `-- pom.xml
|-- Patrac-web
| `-- pom.xml
`-- pom.xml
我不知道如何在部署应用程序时停止一些烦人的警告消息:
12:32:03,958 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-components-ui-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,970 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-components-api-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,984 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-core-api-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,989 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-core-impl-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
Patrac-web-1.0-SNAPSHOT.war!META-INF/MANIFEST.MF 如下所示:
Manifest-Version: 1.0
Built-By: pgarner
Build-Jdk: 1.7.0_02
Class-Path: Patrac-ejb-1.0-SNAPSHOT.jar richfaces-components-ui-4.0.0.
Final.jar richfaces-components-api-4.0.0.Final.jar richfaces-core-api
-4.0.0.Final.jar richfaces-core-impl-4.0.0.Final.jar cssparser-0.9.5.
jar sac-1.3.jar guava-r08.jar
Created-By: Apache Maven
Archiver-Version: Plexus Archiver
为了可移植性,EJB 模块需要存在 ejb 类路径条目,并且 Richfaces、cssparser 和 guava 类路径条目不应出现在 WAR 的清单中。
问题是我的 WAR 依赖于所有 JAR,其中一些位于 WEB-INF/lib
(RichFaces) 中,还有一个 JAR Patrac-ejb-1.0-SNAPSHOT.jar
位于 EAR 的根目录中。每个依赖项都需要在 Patrac-web/pom.xml 中输入,但不是每个依赖项都应该出现在清单中。
Maven 将 JAR 放在正确的位置,但它会将所有 JAR 的 Class-Path 条目放入清单中。它不应该这样做。它应该只为Patrac-ejb-1.0-SNAPSHOT.jar
输入一个条目。
<!--
According to Java EE 6 spec, the application is portable if
Patrac-web.war's META-INF/MANIFEST.MF contains a Class-Path entry
for Patrac-ejb-1.0-SNAPSHOT.jar.
<optional>true</optional> is the flag that maven-war-plugin uses
to put the entry in MANIFEST.MF without copying Patrac-ejb-1.0-SNAPSHOT.jar
into WEB-INF/lib. This is what I want.
<scope>provided</scope> would cause maven-war-plugin to NEITHER
put the entry in MANIFEST.MF nor copy Patrac-ejb.jar into WEB-INF/lib,
which would not be good.
No tag at all would cause maven-war-plugin to BOTH put the entry in
MANIFEST.MF and copy Patrac-ejb.jar into WEB-INF/lib, which would
also not be good.
-->
<dependency>
<groupId>com.patrac</groupId>
<artifactId>Patrac-ejb</artifactId>
<type>ejb</type>
<optional>true</optional>
</dependency>
<!--
These two dependencies are used to copy
the other JAR files into WEB-INF/lib and there
should not be any class-path entries for such
JARs in MANIFEST.MF, in order to avoid the
error messages.
-->
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-components-ui</artifactId>
</dependency>
<dependency>
<groupId>org.richfaces.core</groupId>
<artifactId>richfaces-core-impl</artifactId>
</dependency>
我正在使用最新的 maven-war-plugin 版本 2.2。如何告诉 maven-war-plugin 将“非 ejb”JAR 放入 WEB-INF/lib 中而不将类路径条目放入 MANIFEST.MF?
非常感谢您的任何建议或指示。
参考资料:
Maven War Plugin Maven Ear Plugin【问题讨论】:
【参考方案1】:专门阅读关于瘦身战争的文章
http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html
【讨论】:
【参考方案2】:EJB 模块需要存在 ejb 类路径条目……
类路径只需要存在于引用其他 EJB 模块(在同一 EAR 的根目录中)的 EJB 模块(在 EAR 的根目录中)
【讨论】:
【参考方案3】:Maven WAR plugin 使用的Maven archiver 提供了一种在 WAR 清单中生成 Class-Path 条目的方法,但不幸的是存档器采用了全有或全无的方法。将addClassPath=true
传递给存档配置后,存档器会将 所有 WAR 必需和可选依赖项的 Class-Path 条目放入清单中。
但是,有些条目根本不属于那里。 Class-Path 条目用于表示"Download Extensions," 或对WAR 的外部 JAR 的引用。位于WEB-INF/lib
的JAR 不应该,因此在WAR 的清单中有Class-Path 条目。当您在存档器中设置addClassPath=true
时,Maven 的 War 插件会打破此规则。
此外,当您将addClassPath=true
传递给 Maven 的归档程序时,它会为所有 Class-Path 条目提供相同的目录前缀——无论依赖项位于 EAR 中的什么位置。当可选依赖项和必需依赖项位于不同的位置(例如 EAR 根目录、EAR lib
和 WAR WEB-INF/lib
)时,这会导致问题。
自然地,当部署一个 EAR 其 WAR 清单包含上述错误时,如果 WAR 类加载器最终可以找到依赖项(位于 WEB-INF/lib
中的 JAR),JBoss 会抛出警告,如果类路径前缀错误(例如 on EAR lib
目录中的 EJB JAR 或依赖项)。
因此,如果您的 WAR 和我的一样,依赖于位于 EAR 根目录的 EJB 模块,以及位于WEB-INF/lib
中的任意数量的依赖项,Maven 归档器将为所有无论它们在 EAR 中的位置如何,它们都将具有相同的前缀。
不好。
如果归档器提供一种方法来排除位于 WEB-INF 中的 JAR 的 Class-Path 条目,这个问题将会有所改善。但事实并非如此。
以下是使用addClassPath=true
时每个依赖项设置的结果摘要:
Setting Generate Copy JAR into
Class-Path WEB-INF/lib
Entry
1. <scope>provided</scope> NO NO
2. <optional>true</optional> YES NO
3. (no option -- default) YES YES
4. ????? NO YES
需要覆盖上述情况 #4:不要创建 Class-Path 条目,是的,将 JAR 复制到 WEB-INF/lib
。 Maven 归档器应该默认实现这个行为。
我能想到的最佳解决方案是使用蛮力并关闭 Maven 存档器的自动 Class-Path 条目生成。相反,我使用归档器的manifestEntries
选项在WAR 清单中为EJB 模块显式创建一个Class-Path 条目。这样做的方法是从Patrac-web/pom.xml
中删除以下内容:
<manifest>
<addClasspath>true</addClasspath>
</manifest>
并将其替换为:
<manifestEntries>
<Class-Path>Patrac-ejb-$project.version.jar</Class-Path>
</manifestEntries>
使用此配置,只为 EJB 模块显式创建一个 Class-Path 条目。
【讨论】:
【参考方案4】:对于那些需要从MANIFEST
和WEB-INF/lib
中排除的JAR,您需要将它们标记为<scope>provided</scope>
。这意味着 JAR 文件将由容器提供(在您的情况下是 EAR)。
其他选项请查看WAR manifest guide。
【讨论】:
War manifest guide 显示了 3 个示例并提供了注释:“没有显示如何在 WEB-INF/lib 但不在清单类路径中包含依赖项。”指南然后说:“查看Guide to Working with Manifests 以获取更多示例。”第二页只是让我回到 WAR 清单指南页面。我需要能够遵循未显示的示例。 您想在 WEB-INF/lib 中包含依赖项,但不在清单类路径中?为什么你需要那个?如果您的richfaces
、cssparser
和guava
留在EAR 中,那么这些依赖项应标记为provided
。
Richfaces 等是 WAR 模块的必需依赖项。因此,它们应该在 WEB-INF/lib 中。我的理解是,不需要为 WEB-INF 中的 JAR 创建 Class-Path 条目,因为此类文件由 WAR 的类加载器自动加载。只有 WAR 模块 external 的 JAR 的 Class-Path 条目需要输入到 WAR 的清单中。在我的例子中,必须为 EJB JAR 创建一个条目。这是每个 JEE 规范。 RichFaces 等是 WAR 模块的必需依赖项,因此不应标记为 provided
。
所以,一切正常。只是 RichFaces 依赖项不应在 WAR 清单中包含 Class-Path 条目。当存在 Class-Path 条目时,部署期间会出现 WARNING 消息。 JBoss 抱怨它无法在全局 EAR 目录中找到 RichFaces 依赖项,因为它从 maven-war-plugin 放在那里的清单中读取 Class-Path 条目。但是,应用程序运行良好,因为 JBoss 自动在 WEB-INF/lib 中找到 RichFaces JAR。 WEB-INF/lib 中的 JAR 不应在清单中包含 Class-Path 条目。
EAR 不是 JEE 容器,即使从类加载器的角度来看也是如此!如果您想了解 JEE 中类加载的工作原理,请阅读 JEE 规范。 tools.jar 与此讨论无关! RichFaces 永远不应该进入服务器/库,甚至不应该试图说明问题!讨论完毕。你的帖子很荒谬,没有帮助。请停下来。以上是关于如何在 maven-war-plugin 中正确设置清单类路径的主要内容,如果未能解决你的问题,请参考以下文章
通过maven-war-plugin插件对war包分环境打包
执行 org.apache.maven.plugins:maven-war-plugin:2.1.1:war 时缺少必需的类
Eclipse导入Maven项目出现:Could not calculate build plan: Plugin org.apache.maven.plugins:maven-war-plugin: