如何在maven-war-plugin中正确设置清单类路径

如何在maven-war-plugin中正确设置清单类路径

问题描述:

我已经将maven-ear-plugin与maven-war-plugin和maven-ejb-plugin一起成功地部署并运行了打包为EAR的应用程序到Jboss AS7.

I've used the maven-ear-plugin with the maven-war-plugin and maven-ejb-plugin to successfully deploy and run an application packaged as EAR to 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的位置如下:

In the application source code directories, the poms are located as follows:

.
|
|-- Patrac-ear
|   `-- pom.xml
|-- Patrac-ejb
|  `-- pom.xml
|-- Patrac-web
|   `-- pom.xml
`-- pom.xml

我不知道在部署应用程序时如何停止一些烦人的警告消息:

I can't figure out how to stop a few annoying warning messages when I deploy the application:

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看起来像这样:

Patrac-web-1.0-SNAPSHOT.war!META-INF/MANIFEST.MF looks like this:

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的清单中.

The ejb class-path entry needs to be present for the EJB module, for portability, and the richfaces, cssparser and guava class-path entries should NOT be in the WAR's manifest.

问题是我的WAR依赖于所有JAR,其中一些驻留在WEB-INF/lib(RichFaces)中,而一个JAR驻留在EAR的根目录中.每个依赖项都需要在Patrac-web/pom.xml中输入,但不是每个依赖项都应出现在清单中.

The problem is that my WAR depends on all of the JARs, some of which live in WEB-INF/lib (RichFaces), and one JAR, Patrac-ejb-1.0-SNAPSHOT.jar, that lives in the root directory of the EAR. Each dependency needs to be entered in Patrac-web/pom.xml but NOT each of the dependencies should appear in the manifest.

Maven将JAR放在正确的位置,但是它将所有JAR的类路径条目放入清单中.它不应该这样做.它只应在Patrac-ejb-1.0-SNAPSHOT.jar中输入一个条目.

Maven puts the JARs in the correct places, but it puts Class-Path entries for ALL of the JARs into the manifest. It should not do this. It should ONLY put an entry in for 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将"non-ejb" JAR放入WEB-INF/lib,而不将类路径条目放入MANIFEST.MF?

I'm using the most recent maven-war-plugin version, 2.2. How do I tell the maven-war-plugin to put the "non-ejb" JARs into WEB-INF/lib while not putting class-path entries in MANIFEST.MF?

非常感谢您提出的任何建议或建议.

Any advice or pointers you have are greatly appreciated.

参考文献:

  • Maven War Plugin
  • Maven Ear Plugin

Maven存档器 Maven WAR插件使用的a>提供了一种生成类的方法-WAR清单中的路径条目,但不幸的是,存档器采用了全有或全无的方法.将addClassPath=true传递到存档配置后,存档器会将WAR的必需和可选依赖项的 all 的Class-Path条目放入清单中.

The Maven archiver, used by the Maven WAR plugin, provides a means to generate Class-Path entries in the WAR's manifest but unfortunately the archiver takes an all-or-nothing approach. Once you pass addClassPath=true to the archive configuration, the archiver puts Class-Path entries for all of the WAR's required- and optional dependencies into the manifest.

但是,有些条目根本不属于该条目.类路径条目用于表示下载扩展程序" 或对WAR的外部 JAR的引用.位于WEB-INF/lib的JAR不应不是,因此,在WAR的清单中具有类路径条目.在存档器中设置addClassPath=true时,Maven的War插件违反了此规则.

However, some entries simply do not belong in there. Class-Path entries are used to denote "Download Extensions," or references to JARs external to the WAR. JARs located in WEB-INF/lib should not, therefore, have Class-Path entries in the WAR's manifest. Maven's War plugin breaks this rule when you set addClassPath=true in the archiver.

此外,当您将addClassPath=true传递给Maven的存档器时,它将为所有的Class-Path条目赋予相同的目录前缀-不管依赖关系在EAR中位于何处.当可选依赖项和必需依赖项位于单独的位置(例如EAR根目录,EAR lib和WAR WEB-INF/lib)时,这会导致问题.

Moreover, when you pass addClassPath=true to Maven's archiver, it gives all of the Class-Path entries the same directory prefix -- no matter where the dependencies are located within the EAR. This causes problems when optional- and required dependencies are located in separate locations such as the EAR root directory, EAR lib and WAR WEB-INF/lib.

自然地,当部署一个其WAR清单包含上述错误的EAR时,如果WAR类加载器最终可以找到依赖项(位于WEB-INF/lib的JAR),则JBoss会发出警告;如果类路径前缀错误(例如,在EAR lib目录中的EJB JAR或依赖项.

Naturally, when one deploys an EAR whose WAR manifest contains the above errors JBoss throws warnings if the WAR class loader can ultimately find a dependency (JARs located in WEB-INF/lib) or errors if the class path prefix is wrong (e.g. on an EJB JAR or a dependency in the EAR lib directory).

因此,如果您的WAR(如我的)依赖于EAR根上的EJB模块以及WEB-INF/lib中的任意数量的依赖项,则Maven归档程序将为所有WAR生成Class-Path条目.依赖关系,并且无论它们在EAR中的位置如何,它们都将具有相同的前缀.

Therefore, if your WAR, like mine, depends on an EJB module, located at the root of the EAR, and any number of dependencies that are located inWEB-INF/lib, Maven archiver will generate Class-Path entries for all of the dependencies and they will all have the same prefix regardless of their location within the EAR.

不好.

如果归档程序将提供一种排除位于WEB-INF中的JAR的类路径条目的方法,则将在某种程度上缓解该问题.但事实并非如此.

The problem would be ameliorated somewhat if the archiver would provide a means to exclude Class-Path entries of the JARs located in WEB-INF. But it does not.

以下是使用addClassPath=true时每个依赖项设置的结果摘要:

Here's a summary of the outcome for each dependency setting when one uses 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存档器应实现此行为.

What is needed is coverage for situation #4, above: do not create a Class-Path entry and, yes, do copy the JAR into WEB-INF/lib. Maven archiver should implement this behavior by default.

我能想到的最好的解决方案是使用蛮力并关闭Maven存档器的自动Class-Path条目生成.相反,我使用存档器的manifestEntries选项为WAR清单中的EJB模块显式创建了Class-Path条目.这样做的方法是从Patrac-web/pom.xml中删除以下内容:

The best solution I can think of is to use brute force and turn off the Maven archiver's automatic Class-Path entry generation. Instead, I explicitly create a Class-Path entry for the EJB module in the WAR's manifest using the archiver's manifestEntries option. The way to do this is to remove the following from Patrac-web/pom.xml:

<manifest>
    <addClasspath>true</addClasspath>
</manifest>

并替换为:

<manifestEntries>
    <Class-Path>Patrac-ejb-${project.version}.jar</Class-Path>
</manifestEntries>

使用此配置,仅为EJB模块显式创建一个Class-Path条目.

Using this configuration only one Class-Path entry, for the EJB module, is created explicitly.