10

I have come across the JIRA post that gives a solution as including exclusion tag in each dependency tag of POM.

But I have large number of projects and each project has huge number of dependency tags. It's not feasible to include this <exclusion> in each of the dependency tags.

Question: Is there a way to globally switch off the importing of transitive dependencies in maven?

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
A.R.K.S
  • 1,692
  • 5
  • 18
  • 40
  • But why would you want such a mechanism for all dependencies of all projects? On that case probably ant is a better choice. Otherwise a script would do the job but it can easily become a maintenance nightmare ihmo. – A_Di-Matteo Mar 11 '16 at 07:47
  • We need to do this for security reasons. We have an Artifactory repo where we maintain all and only needed dependencies. We don't want unnecessary dependencies to creep into the package. I would be interested to know what an ant script you are referring to would do . Can you please explain the solution. Is it the same as text replacement on the POMs? – A.R.K.S Mar 11 '16 at 15:51
  • But then wouldn't be easier to switch Artifactory offline so that you completely govern its content? I meant ant because you use physical files as dependencies and not declarations and transitive management, so you have full control on what you are using. The script I had in mind would probably do the same as the solution explained below indeed. – A_Di-Matteo Mar 11 '16 at 16:06
  • Turning off Artifactory will also restrict from using a new needed dependency. Idea is to restrict maven pulling in transitive dependencies and make the developer manually include the dependency it if its really needed. – A.R.K.S Mar 11 '16 at 16:15
  • you could create a new virtual repo in Artifactory that contains only the dependencies you've approved. Regular development can use the main repo with everything and when you run a restricted build use only the restricted repo to ensure no unapproved dependencies get included. – tdrury Mar 18 '16 at 17:20

2 Answers2

7

In Maven you cannot switch off transitive dependencies for all declared dependencies in a single way, as stated by official documentation

Why exclusions are made on a per-dependency basis, rather than at the POM level

This is mainly done to be sure the dependency graph is predictable, and to keep inheritance effects from excluding a dependency that should not be excluded. If you get to the method of last resort and have to put in an exclusion, you should be absolutely certain which of your dependencies is bringing in that unwanted transitive dependency.


Indeed, since Maven 3.2.1 you can specify wildcards to exclude all transitive dependencies for a specific dependency, but that's still per dependency and not global.

What you actually would like to have something like the following per each and every dependency in each and every pom (!!):

<dependency>
    <groupId>groupId</groupId>
    <artifactId>artifactId</artifactId>
    <version>version</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Although this is not advisable since it may easily (and negatively) affect maintainability of concerned projects, a possible solution would be to have a common parent POM for all of the concerned projects, so that each pom would declare:

<parent>
    <groupId>com.sample</groupId>
    <artifactId>projects-governance</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

Then, in the concerned parent POM you would have:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>modules</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <dependencyManagement>
        <dependencies>
            <!-- for each and every foreseen dependency of children poms -->
            <dependency>
                <groupId>groupId</groupId>
                <artifactId>artifactId</artifactId>
                <version>version</version>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

Note the dependencyManagement section, here we are saying: to all children POMs, whenever you use the concerned dependencies I declare, for this groupId and this artifacId by default this version and this exclusions will be applied.

The main advantages of this solution is that you centralize this mechanism/management so that at least you don't have to touch each and every POM (except the change concerning the new parent).

However, you would still need to list in the parent POM all the dependencies used by all the projects and apply a wildcard exclusion for all of them.


To get a list of all dependencies per project, you can probably go for a manual approach (open each and every POM!) or run on each project the following:

mvn dependency:list -DexcludeTransitive=true -DoutputFile=dependencies.txt -DappendOutput=true

The Maven Dependency Plugin would then write in the specified dependencies.txt file the declared dependencies (in the format groupId:artifactId:packaging:version:scope) of the concerned project. Note the last parameter, appendOutput, could be helpful to write at the end of the same file in order to keep them centralized for further processing (removing duplicates, moving them to the new parent pom).


To apply wildcards to all declared dependencies, a quick hint is to simply replace (with any text editor or via shell scripting) the following tokens:

    </version>
</dependency>

By the following ones:

    </version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Then save the file. And automatically you would have in a quite safe manner applied wildcard exclusions to all dependencies.

Update by OP: Finally we decided not to do this and instead, solve the original problem by using dependency tree command to generate reports of the newly added/removed dependencies for each project and broadcast it.

A.R.K.S
  • 1,692
  • 5
  • 18
  • 40
A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
  • I read through the official documentation. Thank you. They illustrate more from user-defined projects view. But I'm more concerned about the artifacts that maven pulls in from it's central repository. This approach is what came to my mind finally too.. Guess will have to go with this.. – A.R.K.S Mar 11 '16 at 16:11
0

Even though I'm not sure why would you want such a mechanism, and I don't recommend that, only exclude transitive dependencies that you actually don't want where the dependencies which depends on them can some how run without them.

The last point is very important those transitive dependencies are needed by your dependencies in order to work probably.

So despite all the above here you go, there is a plugin from Apache Maven called Apache Maven Enforcer Plugin, one of the built in rules it has is Ban Transitive Dependencies

montss
  • 454
  • 5
  • 18