Excluding Files From the EAR

It is possible to exclude certain files from the EAR, by using the <packagingIncludes> and <packagingExcludes> configuration parameters. They each take a comma-separated list of Ant file set patterns. You can use wildcards such as ** to indicate multiple directories and * to indicate an optional part of a file or directory name.

Shared libraries

One use case for this is if you want to use shared libraries in your application server. This involves configuring a location in your application server that contains some libraries that you want to share between several EARs. This is a bit like skinny WARs, but taken to the next level. With skinny WARs you share libraries (JARs) between web applications within an enterprise application. Shared libraries as described here shares libraries (JARs) between enterprise applications.

As an example, let's say that we want to exclude all non-in-house artifacts from the generated EARs, so that the EAR files we distribute only contains our own artifacts. The other dependencies we want to put in a shared library on our application server. They only serve to bloat our EAR files, especially if we're building or deploying several EARs, each with all of those dependencies in them.

Our company in this example, the Acme Corporation, have wisely set a naming convention for all their in-house artifacts. The artifactId is always prefixed with "acme-". If they do not use a shared library, the directory layout for their applications might look like this:

 acme-ear-1
 |-- acme-ejb-1.jar
 |-- acme-library-1.jar
 |-- acme-library-2.jar
 |-- acme-war-1.war
 |-- acme-war-2.war
 |-- external-library-1.jar
 |-- external-library-2.jar
 `-- external-library-3.jar

 acme-ear-2
 |-- acme-ejb-1.war
 |-- acme-library-1.jar
 |-- acme-library-2.jar
 |-- acme-war-3.war
 |-- acme-war-4.war
 |-- external-library-2.jar
 |-- external-library-3.jar
 `-- external-library-4.jar

Configuring the EARs

In order for us to avoid having duplicate copies of the external libraries we need to do two things. First we make sure that our EARs only contain our own artifacts. We do this with the <packagingIncludes> parameter, which tells the EAR Plugin what files to include in the EAR. Everything else will be excluded. This configuration should be used in all of Acme's EAR projects, so it would be better to move this configuration to a parent that is shared by all of Acme's EAR projects.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
          <packagingIncludes>META-INF/**,**/acme-*.jar,**/acme-*.war</packagingIncludes>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Creating the shared library EAR

Next we create a shared library EAR that contains all the dependencies that we want to share between the EARs. In this example we are packaging our shared library as an EAR. What type of packaging you can use differ between various application servers.

Note: The <version> elements of the dependencies have been omitted here for brevity.

<project>
  ...
  <artifactId>external-shared-libraries</artifactId>
  <packaging>ear</packaging>
  ...
  <dependencies>
    <dependency>
      <groupId>com.external.supplier</groupId>
      <artifactId>external-library-1.jar</artifactId>
    </dependency>
    <dependency>
      <groupId>com.external.supplier</groupId>
      <artifactId>external-library-2.jar</artifactId>
    </dependency>
    <dependency>
      <groupId>com.external.supplier</groupId>
      <artifactId>external-library-3.jar</artifactId>
    </dependency>
    <dependency>
      <groupId>com.external.supplier</groupId>
      <artifactId>external-library-4.jar</artifactId>
    </dependency>
  </dependencies>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>3.3.0</version>
      </plugin>
    </plugins>
  </build>
  ...
</project>

The results

With all the Maven configuration done, the resulting directory layout would look like this:

 external-shared-libraries
 |-- external-library-1.jar
 |-- external-library-2.jar
 |-- external-library-3.jar
 `-- external-library-4.jar

 acme-ear-1
 |-- acme-ejb-1.jar
 |-- acme-library-1.jar
 |-- acme-library-2.jar
 |-- acme-war-1.war
 `-- acme-war-2.war

 acme-ear-2
 |-- acme-ejb-1.war
 |-- acme-library-1.jar
 |-- acme-library-2.jar
 |-- acme-war-3.war
 `-- acme-war-4.war

Note: You would also need to configure your application server to use external-shared-libraries as a shared library. How you do that is however out of scope for this example.

Transitive artifacts

For those who have good reason to exclude transitive dependencies, they can configure their pom.xml like this when using Maven3

  <dependency>
    <groupId>GROUPID</groupId>
    <artifactId>ARTIFACTID</artifactId>
    <version>VERSION</version>
    <exclusions>
      <exclusion>
        <groupId>*</groupId>
        <artifactId>*</artifactId>
      </exclusion>
    </exclusions>
  </dependency>

As you can see exclusions support wildcard expressions, so you can have fast and full control over all the dependencies you'd like to exclude.