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
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 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
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.
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 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>
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.
References:
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.
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.
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
.
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).
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.
Not good.
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.
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
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.
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>
and replace it with this:
<manifestEntries>
<Class-Path>Patrac-ejb-${project.version}.jar</Class-Path>
</manifestEntries>
Using this configuration only one Class-Path entry, for the EJB module, is created explicitly.