Jacques René Mesrine
Jacques René Mesrine

Reputation: 47785

How to exclude jars generated by maven war plugin?

Because of transitive dependencies, my wars are getting populated by xml-apis, xerces jars. I tried following the instructions on the reference page for maven-war-plugin but it is not working.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
      <packagingExcludes>WEB-INF/lib/xalan-2.6.0.jar,WEB-INF/lib/xercesImpl-2.6.2.jar,WEB-INF/lib/xml-apis-1.0.b2.jar,WEB-INF/lib/xmlParserAPIs-2.6.2.jar</packagingExcludes>
      <webXml>${basedir}/src/main/webapp/WEB-INF/web.xml</webXml>
      <warName>project1</warName>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
    </configuration>
</plugin>

What am I doing wrong ? If it matters, I discovered that the maven-war-plugin I'm using is at version 2.1-alpha-1

Upvotes: 43

Views: 105441

Answers (9)

Seva Safris
Seva Safris

Reputation: 503

The correct solution is to use the <packagingExcludes> configuration, as the <scope>provided</scope> solution is a hack.

Consider the following multi-module project:

        A
      (war)
      /   \
     B     C
   (jar) (jar)
    /     /
   D     /
 (jar)  /
 / | \ /
e  f  g

In this multi-module project, module A requires modules {B, C, D}, but not {e, f, g}. However, modules B and D do require {e, f g}, and C requires {g}.


First, let's try to solve this problem with the <scope>provided</scope> approach:

To exclude {e, f, g} from A, the <scope>provided</scope> spec must be present in D's POM. But wait, B requires {e, f, g}. So to fix that, the dependency declarations for {e, f, g} must be present in B's POM as well (with <scope>provided</scope>). This means that the dependency spec complexity from D must be been pulled into B. Similarly, since C depends on {g}, the dependency declarations for {g} must be present in C's POM.

With the the <scope>provided</scope> solution, modules B, C, and D must all have knowledge of the fact that A cannot have {e, f, g}.

This approach breaks the encapsulation principle, and is not practical in multi-module projects that have complex dependency graphs.


Second, let's try to solve this problem with the <packagingExcludes> approach:

To exclude {e, f, g} from A, one must provide the following in A's POM:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
      <packagingExcludes>B*.jar,C*.jar</packagingExcludes>
    </configuration>
</plugin>

With this solution, the complexity of "what must be excluded from A" is contained solely in A's POM. This frees modules B, C and D from having to care about excluding transitive dependencies for the sake of A.

This solution upholds the encapsulation principle.

Upvotes: 4

Supun Wijerathne
Supun Wijerathne

Reputation: 12938

You can do this by specifying inside <packagingExcludes></packagingExcludes> inside </configuration><configuration>.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          <packagingExcludes>
            WEB-INF/lib/ex1-*.jar,
            WEB-INF/lib/ex2-logging-*.jar
          </packagingExcludes>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

You can specify by wild cards and regular expressions too. Refer the documentation for more info.

Upvotes: 2

wmorrison365
wmorrison365

Reputation: 6288

See my answer here. The packaging-excludes entry only works with maven-war-plugin version 2.1-alpha-1 and above. So, you may need to upgrade the version used or, you may prefer to use dependency-level injection as it's more precise exclusion of specific jars.

Upvotes: 1

MattC
MattC

Reputation: 6324

To add some clarification, you absolutely can exclude transitive dependencies. For example, if you have a local dependency on A, which has a dependency on M, which in turn has a dependency on X, then you can exclude X where you specify your A dependency.

For example, say you depend on 'myPackageA', which depends on Rampart, which depends on Xerces, then you can exclude Xerces in your myPackageA dependency:

 <groupId>myPackageA.dependsOnRampart.whichDependsOnXerces</groupId>
 <artifactId>someArtifact</artifactId>
 <version>2.1</version>
 <exclusions>
   <exclusion>
     <groupId>org.apache.xerces</groupId>
     <artifactId>xmlParserAPIs</artifactId>
   </exclusion>
   <exclusion>
     <groupId>org.apache.xerces</groupId>
     <artifactId>xml-apis</artifactId>
   </exclusion>
   <exclusion>
     <groupId>org.apache.xerces</groupId>
     <artifactId>xercesImpl</artifactId>
   </exclusion>
   <exclusion>
     <groupId>org.apache.xerces</groupId>
     <artifactId>resolver</artifactId>
   </exclusion>
   <exclusion>
     <groupId>org.apache.xerces</groupId>
     <artifactId>serializer</artifactId>
   </exclusion>
 </exclusions>

To check your dependencies afterwards, run 'mvn dependency:tree' and hopefully you won't see any xerces dependencies.

Upvotes: 2

greuze
greuze

Reputation: 4398

When compiling with maven 3 (I used 3.0.2) with provided scope you have the problem with the transitive dependencies (you have a los of JARs inside the WAR). If you use older versions of maven (I used 2.2.1), the WAR contains what is spected (only dependencies not provided

Upvotes: 0

SmithHCoder
SmithHCoder

Reputation: 41

I had no possibility to modify depending war file. I needed to avoid some old jar file from lib. This snippet of POM.xml configuration works well for me. I use Maven 2.2.

<build>
    <plugins>
        <!-- put aside some unwanted jars from war...-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.1.1</version>
            <configuration>
                <overlays>
                    <overlay>
                        <groupId>com.company.app</groupId>
                        <artifactId>web_app</artifactId>
                        <excludes>
                            <exclude>WEB-INF/lib/json-lib-2.2.2-jdk13.jar</exclude>                                
                        </excludes>
                    </overlay>
                </overlays>
            </configuration>
        </plugin>
        ....

Upvotes: 4

accreativos
accreativos

Reputation: 161

About exclusion of transitive dependencies, i think don't work with transtive of transitive dependecies, and i think this could be the case.

For example, add dependency of hibernate-core -> dom4j -> xml-apis if add exclude of xml-apis near your hibernate-core, still add xml-apis...

Upvotes: 5

David Rabinowitz
David Rabinowitz

Reputation: 30448

You can mark these dependencies as provided:

<dependency>
  <groupId>xerces</groupId>
  <artifactId>xerces</artifactId>
  <version>2.4.0</version>
  <scope>provided</scope>
</dependency>

This way the maven will add them to the compilation classpath, but will not package them. It is assumed they exist in your servlet container.

See more about maven scopes here under "scope"

Edit If you want to remove classes added via transitive dependencies you can exclude them from the dependency like this:

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
        <exclusions>
                <exclusion>
                        <groupId>commons-logging</groupId>
                        <artifactId>commons-logging</artifactId>
                </exclusion>
        </exclusions>
</dependency>

(taken from this answer)

See more here

Upvotes: 71

Jacques Ren&#233; Mesrine
Jacques Ren&#233; Mesrine

Reputation: 47785

I fixed it.

Rereading the reference with a bit more care, I discovered that the element packagingExcludes should be warSourceExcludes.

Upvotes: 8

Related Questions