43

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

Jacques René Mesrine
  • 46,127
  • 27
  • 66
  • 104

9 Answers9

71

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

Community
  • 1
  • 1
David Rabinowitz
  • 29,904
  • 14
  • 93
  • 125
  • Problem is that xerces for example was pulled in via transitive dependencies. I don't want to populate my pom.xml with all these extraneous filler. – Jacques René Mesrine Jun 23 '09 at 10:28
  • 9
    don't forget to package with `mvn clean package` afterwards – Otto Allmendinger Sep 23 '11 at 12:32
  • 1
    How to use this with the eclipse plugin? If I mark dependency as provided, it might be visible in the app server, but eclipse cannot compile, because the eclipse plugin does not put provided dependencies to eclipse classpath. – Oliv Feb 11 '13 at 06:09
7

I fixed it.

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

Jacques René Mesrine
  • 46,127
  • 27
  • 66
  • 104
  • Have you tried my suggestion? It will save you from mentioning every jar twice (both dependency and excludes) – David Rabinowitz Jun 23 '09 at 11:16
  • that is true for the version of the war plugin you use. in 2.1-alpha-2 it has changed to packagingExcludes. see http://jira.codehaus.org/browse/MWAR-135 for more details – Salandur May 25 '10 at 10:20
  • 2
    In 2.1.1 version of the plugin it works with: `WEB-INF/lib/xercesImpl-2.9.1.jar,WEB-INF/lib/xml-apis-1.3.04.jar`, normal exclusion doesn't seem to work. I haven't tried overriding these deps as "provided". – virgo47 Jan 26 '12 at 15:07
5

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...

accreativos
  • 161
  • 2
  • 9
4

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.

Seva Safris
  • 401
  • 4
  • 12
4

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>
        ....
2

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.

MattC
  • 5,874
  • 1
  • 47
  • 40
2

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.

Supun Wijerathne
  • 11,964
  • 10
  • 61
  • 87
1

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.

Community
  • 1
  • 1
wmorrison365
  • 5,995
  • 2
  • 27
  • 40
0

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

greuze
  • 4,250
  • 5
  • 43
  • 62