Creating Skinny WARs

In a typical J2EE environment, a WAR is packaged within an EAR for deployment. The WAR can contain all its dependent JARs in WEB-INF/lib but then the EAR can quickly grow very large if there are multiple WARs, due to the presence of duplicate JARs. Instead the J2EE specification allows WARs to reference external JARs packaged within the EAR via the Class-Path setting in their MANIFEST.MF.

Starting with version 2.7 Maven EAR Plugin has basic support for this mode of operation.

First we need to change the EAR project's pom.xml to package those JARs in the EAR, using the skinnyWars parameter.

Note: In this example we package all JARs into a lib/ directory within the EAR. This is just to distinguish between J2EE modules (which will be packaged in the root of the EAR) and Java libraries (which are packaged in lib/).

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
          <defaultLibBundleDir>lib/</defaultLibBundleDir>
          <skinnyWars>true</skinnyWars>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Now the painful part. Your EAR project's pom.xml needs to list every dependency that you want to share through the EAR.

<project>
  ....
  <dependencies>
    <!-- This is the JAR we want to share -->
    <dependency>
      <groupId>com.acme</groupId>
      <artifactId>shared-jar</artifactId>
      <version>1.0.0</version>
    </dependency>
    <dependency>
      <groupId>com.acme</groupId>
      <artifactId>war1</artifactId>
      <version>1.0.0</version>
      <type>war</type>
    </dependency>
    <dependency>
      <groupId>com.acme</groupId>
      <artifactId>war2</artifactId>
      <version>1.0.0</version>
      <type>war</type>
    </dependency>
  </dependencies>
  ...
</project>

Your EAR will contain something like this:

 .
 |-- META-INF
 |   `-- application.xml
 |-- lib
 |   `-- shared-jar-1.0.0.jar
 |-- war1-1.0.0.war
 `-- war2-1.0.0.war

If you look inside the copies of war1-1.0.0.war and war2-1.0.0.war, that are packaged within the EAR, you will see that they no longer contain the file WEB-INF/lib/shared-jar-1.0.0.jar.

Also, if you inspect the MANIFEST.MF of the WARs you will notice that the Class-Path entry has been modified and now has a reference to lib/shared-jar-1.0.0.jar.