Reputation: 51
Is there a reason maven-war-plugin behaves differently than the standard maven dependency resolving mechanism? I have a war maven project which has a dependency:
<dependency>
<groupId>GroupA</groupId>
<artifactId>DependencyA</artifactId>
<exclusions>
<exclusion>
<groupId>GroupB</groupId>
<artifactId>DependencyB</artifactId>
</exclusion>
</exclusions>
</dependency>
The above dependency is correctly excluded and I can verify on the dependency hierarchy view.
When I build the war with maven it includes the DependencyB in WEB-INF/lib
directory, so I have to explicitly define to exclude it using the maven-war-plugin as so:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<packagingExcludes>
WEB-INF/lib/dependencyB.jar,
</packagingExcludes>
</configuration>
</plugin>
I have to do the above cause conflicts between versions arise on my project. Why is this happening? Is there another way to achieve this?
UPDATE
So I created a test case just to showcase you what I mean, if I was not clear enough before. And the corresponding pom's are as below:
ArtifactA:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GroupA</groupId>
<artifactId>ArtifactA</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ArtifactA Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>GroupB</groupId>
<artifactId>ArtifactB</artifactId>
<type>war</type>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>ArtifactA</finalName>
</build>
ArtifactB
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GroupB</groupId>
<artifactId>ArtifactB</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ArtifactB Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<finalName>ArtifactB</finalName>
</build>
ArtifactC
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ArtifatcC</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
In the dependency Hierarchy in Eclipse, I do not see the dependency ArtifactC.
And when building the ArtifactA and unzipping the .war I get:
As you can see the transitive dependency is included in the .war in the WEB-INF/lib. I hope this is more clear now.
Some other details to add:
Upvotes: 2
Views: 211
Reputation: 49095
I too have noticed strange behavior with <exclusions>
. My best recommendation is to put this in the war project (Project A).
<dependency>
<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
notice the scope provided
I have to do this frequently for commons-logging as something always seems to somehow cause it to be included and its just a pain in the a$$ to go around and mark exclusions everywhere.
The other option is to do this in Project B:
<dependency>
<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
Then add the ArtifactC and ArtifactB dependency explicitly where you actually need it (ie deploying B in other places).
notice the optional
Like I said in my comment I don't think its a good idea to rely on <exclusions>
. It generally means something is broken. Its particularly bad if your the one causing it.
Upvotes: 0
Reputation: 34044
The problem is not so much that the war plugin handles dependency exclusion differently, but that it handles dependencies of <type>war</type>
specially. It creates a war overlay out of these, meaning it takes the whole contents of the war and puts the projects web resources on top. The war dependency really has no transitive dependencies, it already includes all jar files.
If using war overlays is really your intention then using packagingExcludes
is the correct solution. If you instead want to depend on the classes in artifact B then you should modify the pom so it creates a separate artifact (using the attachClasses
configuration) and depend on this classes
artifact. Exclusion of transitive dependencies should then work as with any other jar dependency.
Upvotes: 2