Creating Skinny Modules
This is a bit like skinny WARs, but taken to the next level and applied to EAR modules of type:
Starting with version 3.2.0, the Maven EAR Plugin supports referencing external JARs packaged within the EAR via the Class-Path
setting in EAR module MANIFEST.MF
.
You need to change the EAR project's pom.xml
to package those JARs in the EAR and to use the skinnyModules parameter.
Note: In this example we package all JARs into a libs/
directory within the EAR. This is just to distinguish between Java EE modules (which will be packaged in the root of the EAR) and Java libraries (which are packaged in libs/
). Also, we use non-standard outputFileNameMapping
to shorten names of files packaged in EAR and to keep them close to the names used in local repository for a better readability.
<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>war</artifactId> <version>1.0.0</version> <type>war</type> </dependency> <dependency> <groupId>com.acme</groupId> <artifactId>rar</artifactId> <version>1.0.0</version> <type>rar</type> </dependency> <dependency> <groupId>com.acme</groupId> <artifactId>sar</artifactId> <version>1.0.0</version> <type>sar</type> </dependency> </dependencies> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-ear-plugin</artifactId> <version>3.3.0</version> <configuration> <outputFileNameMapping>@{artifactId}@-@{version}@@{dashClassifier?}@.@{extension}@</outputFileNameMapping> <defaultLibBundleDir>libs/</defaultLibBundleDir> <skinnyModules>true</skinnyModules> </configuration> </plugin> </plugins> </build> ... </project>
Your EAR will contain something like this:
. |-- META-INF | `-- application.xml |-- libs | `-- shared-jar-1.0.0.jar |-- war-1.0.0.war |-- sar-1.0.0.sar `-- rar-1.0.0.rar
If you look inside the copies of war-1.0.0.war
, rar-1.0.0.ear
and sar-1.0.0.sar
, that are packaged within the EAR, you will see that they no longer contain WEB-INF/lib/shared-jar-1.0.0.jar
, shared-jar-1.0.0.jar
and lib/shared-jar-1.0.0.jar
files respectively.
Also, if you inspect the MANIFEST.MF
of WAR, SAR and HAR modules of EAR you will notice that the Class-Path
entry has been modified or added, if it was missing, and now has a reference to libs/shared-jar-1.0.0.jar
.
If an archive representing the EAR module has non-standard location of libraries, then this location can be configured using the libDirectory
property.
Here is example for SAR which contains libraries at the root of the archive (refer to sarModule for description of libDirectory
property):
<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>war</artifactId> <version>1.0.0</version> <type>war</type> </dependency> <dependency> <groupId>com.acme</groupId> <artifactId>rar</artifactId> <version>1.0.0</version> <type>rar</type> </dependency> <!-- SAR having shared-jar-1.0.0.jar at the root --> <dependency> <groupId>com.acme</groupId> <artifactId>sar</artifactId> <version>1.0.0</version> <type>sar</type> </dependency> </dependencies> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-ear-plugin</artifactId> <version>3.3.0</version> <configuration> <outputFileNameMapping>@{artifactId}@-@{version}@@{dashClassifier?}@.@{extension}@</outputFileNameMapping> <defaultLibBundleDir>libs/</defaultLibBundleDir> <skinnyModules>true</skinnyModules> <modules> <sarModule> <groupId>com.acme</groupId> <artifactId>sar</artifactId> <libDirectory>/</libDirectory> </sarModule> </modules> </configuration> </plugin> </plugins> </build> ... </project>