Gradle dependency with test classifier - maven

I've been trying to reference an artefact without luck.
With maven I have no problem doing this:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.13</artifactId>
<version>3.0.0</version>
<classifier>test</classifier>
</dependency>
Maven selects the correct artefact.
However, with gradle, it always seems to include the artefact without the classifier, no matter what I try:
implementation 'org.apache.kafka:kafka_2.13:3.0.0:test'
I have read the gradle documentation and it suggests this syntax, maybe it has something to do with this specific artefact?
Update
My goal is to use spring-kafka-test. Our internal artefact repository is not set up to use pom resolution, which is why I need to add transitives manually.
I've ruled out the fact that it might be our internal repository by only using maven central; and I get the same results.

I managed to include only the mentioned jar, with:
dependencies {
implementation ('org.apache.kafka:kafka_2.13:3.0.0:test') {
exclude group: 'org.apache.kafka' // or finer grained, if we like
}
...
}
See also: How to specify a classifier in a gradle dependency's dependency?

But
Your assumptions about maven were also wrong:
Maven pulls all! (In module-test-parents no dependencies defined.)
To achieve the same (and even more) in maven we'd also have to:
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.13</artifactId>
<version>3.0.0</version>
<classifier>test</classifier>
<exclusions>
<exclusion> <!--sledge hammer -->
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
<!-- or selectively ... -->
</exclusions>
</dependency>
</dependencies>
In gradle the according would be (tested):
implementation ('org.apache.kafka:kafka_2.13:3.0.0:test'){
exclude group: '*'
}

Related

Maven enforcer plugin should honor dependency exclusions

How can I ensure that in my pom certain dependecies do not occur, also transitively?
This doesn't work with the maven enforcer plugin.
I added the following new dependency
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.1.0</version>
</dependency>
After restarting the app, my logback logging no longer works. A quick search shows that the dependency mentioned above comes with log4j and this messes up my logback logging.
So I don't want the transitive log4j dependency to get into my target artifact and exclude it:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.1.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
How can I check in the future whether a new dependency may also bring a transitive dependency for log4j with it?
With the maven enforcer plugin I can check this:
<bannedDependencies>
<excludes>
<exclude>org.apache.logging.log4j</exclude>
</excludes>
<searchTransitive>true</searchTransitive>
</bannedDependencies>
But it ALWAYS raises an alarm, although I have excluded it via <exlusion> mentioned above. However, if I switch to
<searchTransitive>false</searchTransitive>
then the log4j is no longer found, since I didn't declare it as a dependency directly in my pom and the enforcer check is pointless.
Now how do I get the maven enforcer plugin to honor dependency exclusions?

How to find out if any class from dependency is being used in the maven application?

I have a huge maven application with nearly about 100 maven dependencies in the pom.xml file.
One starter dependency is downloading log4j.jar which is not required at all. So, is there an easy to find in order to make sure no class from a particular jar is being used so that we can exclude it directly from starter dependency as shown below.
<dependency>
<groupId>com.example.group</groupId>
<artifactId>example-artifact</artifactId>
<version>1.11.5</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Basically I want to exclude the jar which I am not using at all but simply comes as a transitive dependency.
More specifically, this will show you exactly what you're asking:
https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html

Using dependencies of an artifact

I have a complex Spring project with tens of dependencies and modules. I notice that some of them might be replaced by spring-boot-starters.
However, when I'm replacing some dependencies with starters in main, parent pom, I'm getting errors in children modules.
Here's an example:
PARENT POM
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
MODULE POM
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
According to maven repository spring-boot-starter-activemq depends on, among others, spring-boot-starter and spring-jms.
Should these dependencies be available for modules?
Is there a way to use dependencies like that? I would make pom files shorter.
Or maybe is it a bad idea to do it like that and I should define all dependencies I will use in dependencyManagement?
In a POM, you should have all the dependencies that you directly use in your code. Do not rely on transitive resolution for things you actively use.
Your construction does not work because you did not manage the spring-jsm and spring-boot-starter in your dependencyManagement. Being a dependency of the managed dependency does not help.

How to turn off transitive dependencies for maven projects?

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

How do I indicate to maven that one dependency provides another?

After version 11.0.2, Google's guava library switched to Java 6. Fortunately, for those of us stuck on Java 5, they also released a "guava-jdk5" artifact.
Unfortunately, some of my dependencies pull in guava 11.0.2 transitively. Which leaves my project containing both guava-jdk5 and guava.
Normally when I have conflicting versions, I can use the "dependencymanagement" tag to indicate which version to pull in. But since these are two different artifacts, I do not understand how to do this. Ultimately I want to tell maven, guava and guava-jdk5 are the same artifact and I want the 17.0 version of guava-jdk5 to be the one that is used. How do I do this?
Thanks!
One easy way is to use a dependency exclusion, nutshell from the link:
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

Resources