262

In Maven2, to exclude a single transitive dependency, I have to do something like this:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

The problem with this approach is that I have to do this for every transitive dependency contributed by sample-artifactB.

Is there a way to use some sort of wildcard to exclude all transitive dependencies at once instead of one-by-one?

David Harkness
  • 35,992
  • 10
  • 112
  • 134
pbreault
  • 14,176
  • 18
  • 45
  • 38
  • At times one needs to use a latest version of the library say Spring 2.5.6 but some other dependencies include older version e.g. struts2-spring-plugin (2.1.6) includes Spring 2.5.3. In such scenarios there is a requirement for exclusion or overriding the version. – Vinod Singh Apr 28 '09 at 20:49
  • 2
    Use Ivy. Just kidding. – Jake Toronto May 07 '14 at 21:59

12 Answers12

381

What has worked for me (may be a newer feature of Maven) is merely doing wildcards in the exclusion element.

I have a multi-module project that contains an "app" module that is referenced in two WAR-packaged modules. One of those WAR-packaged modules really only needs the domain classes (and I haven't separated them out of the app module yet). I found this to work:

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>app</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

The wildcard on both groupId and artifactId exclude all dependencies that normally would propagate through to the module using this dependency.

enricopulatzo
  • 4,219
  • 2
  • 17
  • 8
  • 11
    The * wildcard for group and artifiact seems to be working in maven 3 – nkr1pt Oct 04 '11 at 13:53
  • [This feature request](http://jira.codehaus.org/browse/MNG-3832) is relevant. It doesn't seem like the wildcarding suggested here is supposed to work yet. – Haakon Jan 20 '12 at 09:27
  • For me, in NetBeans it looks like its working, as the dependencies folder in the project-tree contains only the direct dependency and not the transistive. However, come time to do maven build, this seems not to be respected... – Superole Feb 23 '12 at 09:34
  • 8
    Worked beautifully with Maven 3.0.4. Thanks *a lot*! – Evgeny Goldin Dec 26 '12 at 23:21
  • It gives a warning, but it works. See http://jira.codehaus.org/browse/MNG-3832?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel – Viktor Nordling Jan 02 '13 at 23:13
  • Gradle also supports wildcard exclusions when resolving dependencies with wildcard excludes. – Danny Thomas Feb 13 '13 at 11:49
  • 2
    maven 3.0.4 -> it did not worked well for me. resulted jar is very much different when i use asterix, or when i explicitly exclude all direct dependencies. it may have to do with the fact i'm using maven-assembly-plugin to create a fat jar. in this case, the suggested sulotion does not work! – gilad hoch Oct 27 '13 at 14:31
  • 35
    This method is valid. They fixed the warning that others are reporting in maven 3.2.1: https://issues.apache.org/jira/browse/MNG-3832 – Ryan Feb 18 '14 at 19:17
  • It's enough: * – AppLend Feb 27 '14 at 08:53
  • 1
    Beware: the suggested "solution" by AppLend doesn't always work. For us, it only works **WITH** the artifactId. – Kawu Apr 03 '14 at 17:02
  • 1
    Does not seem to work with the `requireUpperBoundDeps` rule of `maven-enforcer-plugin`, FWIW. – Jesse Glick Aug 23 '17 at 01:32
59

For maven2 there isn't a way to do what you describe. For maven 3, there is. If you are using maven 3 please see another answer for this question

For maven 2 I'd recommend creating your own custom pom for the dependency that has your <exclusions>. For projects that need to use that dependency, set the dependency to your custom pom instead of the typical artifact. While that does not necessarily allow you exclude all transitive dependencies with a single <exclusion>, it does allow you only have to write your dependency once and all of your projects don't need to maintain unnecessary and long exclusion lists.

Community
  • 1
  • 1
whaley
  • 16,075
  • 10
  • 57
  • 68
  • 12
    I would recommend against making your own pom to work around exclusions. This makes your build far less portable and reduces the comprehension. – Brian Fox Apr 12 '09 at 01:52
  • 1
    In case you don't look past accepted anwser: http://jira.codehaus.org/browse/MNG-3832 – Jakub Bochenski Mar 17 '15 at 20:39
  • @JakubBochenski the answer I've given is specific to maven 2, which is what this question is tagged with (at the time I wrote this comment). Your link is relevant only for maven 3. Regardless, I've edited my answer to link to link to the more highly upvoted answer. – whaley Mar 17 '15 at 23:50
40

One thing I have found useful:

If you put the dependency with the exclusions in the dependencyManagement section of either the parent POM for your project, or in an importable dependency management POM, then you don't need to repeat the exclusion (or the version).

For example, if your parent POM has:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

Then the modules in your project can simply declare the dependency as:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

The in the parent POM will specify both the version and the exclusions. I use this technique for nearly all of our projects and it eliminates a lot of repetition.

Joshua Davis
  • 3,499
  • 1
  • 26
  • 29
27

Three years ago I recommended using Version 99 Does Not Exist, but now I've figured out a better way, especially since Version 99 is offline:

In your project's parent POM, use maven-enforcer-plugin to fail the build if the unwanted dependency creeps into the build. This can be done using the plugin's banned dependencies rule:

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Then when that alerts you about an unwanted dependency, exclude it in the parent POM's <dependencyManagement> section:

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

This way the unwanted dependency won't show up accidentally (unlike just an <exclusion> which is easy to forget), it won't be available even during compile time (unlike provided scope), there are no bogus dependencies (unlike Version 99) and it'll work without a custom repository (unlike Version 99). This approach will even work based on the artifact's version, classifiers, scope or a whole groupId - see the documentation for details.

Community
  • 1
  • 1
Esko Luontola
  • 73,184
  • 17
  • 117
  • 128
  • Note that at least under Maven 3.1, the `` is ignored when executing the goal from the command-line and must be moved up directly under ``. – David Harkness Jul 10 '14 at 00:13
  • I just found what looks like a nasty Maven bug - version 3.5.2. I have a project with submodules where I do exclude a dependency at the parent's `` section. Running a `mvn dependency:tree` in that specific project will not have the excluded dependency at all. But all projects importing that dependency will not honor the `` from the other project parent pom - the excluded one will creep in!!! I had to move `` to each module pom directly. – cbaldan Jun 25 '20 at 16:02
  • To solve cbaldan's issue, the project should have an extra submodule where you move the `` section from the parent POM. Then the other submodules bring that new submodule into their own `` sections, using `pomimport`. [Example dependency-management submodule](https://github.com/dropwizard/dropwizard/blob/v2.1.4/dropwizard-dependencies/pom.xml) and [example use of it](https://github.com/dropwizard/dropwizard/blob/v2.1.4/dropwizard-example/pom.xml#L31-L37). – Matthew Read Nov 19 '22 at 05:52
14

I use the following workaround : instead of trying to exclude the artifact in all appropriate dependencies, I draw the dependency as "provided" at top level. For example, to avoid shipping xml-apis "whatever version" :

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Michael Zilbermann
  • 1,398
  • 9
  • 19
9

Currently, there's no way to exclude more than one transitive dependency at a time, but there is a feature request for this on the Maven JIRA site:

https://issues.apache.org/jira/browse/MNG-2315

Paulo Merson
  • 13,270
  • 8
  • 79
  • 72
Peter
  • 6,354
  • 1
  • 31
  • 29
8

if you need to exclude all transitive dependencies from a dependency artifact that you are going to include in an assembly, you can specify this in the descriptor for the assembly-plugin:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>
Superole
  • 1,329
  • 21
  • 29
7

There is a workaround for this, if you set the scope of a dependency to runtime, transitive dependencies will be excluded. Though be aware this means you need to add in additional processing if you want to package the runtime dependency.

To include the runtime dependency in any packaging, you can use the maven-dependency-plugin's copy goal for a specific artifact.

Rich Seller
  • 83,208
  • 23
  • 172
  • 177
  • 1
    This helped me work around issues with the Android Dalvik compiler which couldn't handle some of the two-level transitive inclusions---but I had to use `provided` instead of `runtime`. – Garret Wilson Nov 29 '11 at 18:16
3

If you develop under Eclipse, you can in the POM Editor (advanced tabs enabled) dependency graph look for the dependency you want to exclude of your project and then:

right click on it -> "Exclude Maven Artifact ..." and Eclipse will make the exclusion for you without the need to find out on which dependency the lib is linked.

gnat
  • 6,213
  • 108
  • 53
  • 73
Tib
  • 31
  • 1
2

What is your reason for excluding all transitive dependencies?

If there is a particular artifact (such as commons-logging) which you need to exclude from every dependency, the Version 99 Does Not Exist approach might help.


Update 2012: Don't use this approach. Use maven-enforcer-plugin and exclusions. Version 99 produces bogus dependencies and the Version 99 repository is offline (there are similar mirrors but you can't rely on them to stay online forever either; it's best to use only Maven Central).

Community
  • 1
  • 1
Esko Luontola
  • 73,184
  • 17
  • 117
  • 128
1

In a simular issue I had the desired dependency declared with scope provided. With this approach the transitive dependencies are fetched but are NOT included in the package phase, which is what you want. I also like this solution in terms of maintenance, because there is no pom, or custom pom as in whaley's solution, needed to maintain; you only need to provide the specific dependency in the container and be done

nkr1pt
  • 4,691
  • 5
  • 35
  • 55
-9

Use the latest maven in your classpath.. It will remove the duplicate artifacts and keep the latest maven artifact..

Samraj
  • 83
  • 2
  • 11