For example, I have 2 Maven projects. One is \"project-parent\". The other is \"project-child\". Obviously, \"project-child\" is the sub project of \"project-parent\".
I have managed to exclude a transient dependency from a parent pom. By re-importing it in <dependencymanagement>
and then setting exclusion por the dependency I wanted out. like this eg.:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
One hacky way to accomplish this is to specify the dependency in project-child but with 'test' scope (or whatever lightest-weight scope is available). This will "hide" the scope specified in project-parent so that it is available only to test code, and unavailable to non-test code at both compile and runtime.
I came across this bug-feature mostly by mistake. In my case, my project-child had a project-sibling with a 'compile' scope dependency, while project-parent had the same dependency specified (actually inherited from a grandparent) with 'provided' scope. project-child was an executable however that depended on project-sibling, and so a NoClassDefFoundError was thrown at runtime from project-sibling since project-child's runtime classpath was being used, which didn't include the 'provided' dependency. I fixed this by moving the 'compile' dependency from project-sibling to project-parent so that the 'compile' would "hide" the 'provided'.
I think in Maven2 there is no way to achieve this, because this is what POM inheritance is for . However there is one trick that I can think of:
Assume you have the right to upload artifact to your internal artifact repository. You may create an empty JAR, deploy it as log4j:log4j, with a obviously abnormal version (e.g. log4j:log4j:9999 ). Add such dependency in your project-child. Then it will override the dependency of parent to depends on a in-fact-empty JAR.
If I understand the question, what you need is something like the following. It pulls in a dependency and excludes that dependency from adding to its dependency list. Often this is used if you want to inject a newer version of a package instead of the one referenced in the other package.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
...
</exclusions>
...
If you are instead talking about a <parent>
relationship then I'm not sure there is a way to do this. Can you switch from being a <parent>
to a <dependency>
?
I have met the same question just like you. In my project, let call the parent pom is parent.pom. parent defined the log4j, slf4j like this:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-log4j12.version}</version>
</dependency>
child project invoke some dependency in child.pom. But I don't want the log4j-1.2.x dependency and want to increase the version of slf4j.
So. I add the dependency of parent
<dependency>
<groupId>parent</groupId>
<artifactId>myartifactId</artifactId>
<version>${my parent version}</version>
</dependency>
and use exclusions to remove the log4j
<dependency>
<groupId>parent</groupId>
<artifactId>myartifactId</artifactId>
<version>${my parent version}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
and explicitly add the slf4j and log4j2's dependency in child pom
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
then use mvn dependency:tree to show the dependency list, still see the log4j
[INFO] +- org.apache.kafka:kafka_2.10:jar:0.8.2.0:compile
[INFO] | +- com.yammer.metrics:metrics-core:jar:2.2.0:compile
[INFO] | +- org.scala-lang:scala-library:jar:2.10.4:compile
[INFO] | +- org.apache.zookeeper:zookeeper:jar:3.4.6:compile
[INFO] | | +- org.slf4j:slf4j-log4j12:jar:1.7.5:compile
[INFO] | | +- log4j:log4j:jar:1.2.17:compile
well, let's add the exclusions on that dependency...remove this guy.
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.1.1</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
then run the command again to check the dependency list. OK! clear~
Hope that can help you :>
I don't know of a way of actually excluding a dependency, but you can exclude it from the target distribution, but it's a bit of a hack. You need to change the scope of the dependency to something that you can exclude in the final distribution.
So, say that my parent had a dependency on junit 4.8, in my pom you say:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8</version>
<scope>provided</scope>
</dependency>
So we're changing the scope to provided. For an explanation of how this works, see my answer to NoClassDefFoundError: org/junit/AfterClass during annotation processing. Unfortunately, this doesn't affect the build, but when you're copying the dependencies for the final distribution, you can use the excludeScope
configuration element to not copy the dependency into the final distribution:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeScope>provided</excludeScope>
</configuration>
</execution>