How can I use (refer) transitive dependency's version? - maven

I'm facing a situation that I need to specify one of transitive dependency's version.
With following dependency tree,
A <- B <- C
I need to specify A's version in C's pom.xml
Is there any way to do this? So that I can filter some file like this?
A's version is #{...a.version}

If you want to specify the version of a (possible) transitive dependency, put the dependency into the dependencyManagement section of your POM. Then it is used if the dependency occurs transitively (and silently ignored if no such transitive dependency is found).

It is not possible to directly reference the version of some arbitrary dependency (transient or not).
However, in your parent pom you can define a property:
<properties>
...
<yourCdep.version>
...
</properties>
and add the dependency in to a dependencyManagement section:
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>yourCdep.group</groupId>
<artifactId>yourCdep</artifactId>
<version>${yourCdep.version}</version>
</dependency>
...
</dependencies>
</dependencyManagement>
Remove the version from the dependency in module B as it is now "managed".
The property value in the parent pom will be accessible in both modules A and B.
In particular, this property value can now be applied when resource filtering.

Use <optional>true</optional>:
C -> B -> A
pom(B) :
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>A</artifactId>
<version></version>
<optional>true</optional>
</dependency>
...
</dependencies>
pom(C):
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>B</artifactId>
<version></version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>A</artifactId>
<version></version>
</dependency>
...
</dependencies>

Related

How should dependencies between modules be declared in a maven multi-module project?

Assume I have a maven multi-module project consisting of parent P and its modules A and B. How should a dependency of B to A be declared?
Until today I always used the following in B:
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
But a colleague just mentioned that it is also possible to create a dependency management entry for A in parent P
<depednencyManagement>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
</dependencyManagement>
and then B only needs to specify:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
</dependency>
</dependencies>
Is there any downside to either of those methods? Does maven intend one to be actually used? Or is there actually another style I'm missing?
In the project I'm working all modules have the same version and we are having much more than 3 modules and also some deeper nesting than only 2 levels. Does this have an influence on which declaration style should be preferred?

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.

Dependencies vs DependenciesManagement?

I have gone through differences between dependencymanagement and dependencies in maven but i am still unclear when to use
just dependencies tag in parent pom and when to use dependenciesManagement tag ?
My understanding is when my all child modules need to use same dependency version then we should declare the Dependencies under Dependencies tag(without dependencyManagement tag)
But on other hand if some of the child project need to use different version then we should declare the Dependencies under Dependencies tag(which will be under dependencyManagement tag). then Child modules can refer them with overridden version
Is that correct ?
Declaring a <dependency> within <dependencyManagement> does not set the specified artifact as dependency for any project – parent or childs. It just states: If you want to use this as dependency then you can use it with these settings (version, scope, ...) without having to specify the settings again, and again, and ... You can, however, override a "management" setting in a "real" <dependency> anytime.
See also POM Reference, Dependency Management.
There are two options for a parent POM regarding your second paragraph:
As you describe correctly:
<dependencies>
<dependency>
<groupId>g-id</groupId>
<artifactId>a-id</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
I'd use this for consistency:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>g-id</groupId>
<artifactId>a-id</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>g-id</groupId>
<artifactId>a-id</artifactId>
</dependency>
</dependencies>
Your third paragraph is correct..

why don't use scope maven dependency Management?

if i define this dependency at parent's pom:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework<groupId>
<artifactId>spring-core<artifactId>
<version>3.1.0.RELEASE</version>
</dependency>
and in one of the childss:
<project>
<dependencies>
<dependency> // note: no version declared
<groupId>org.springframework<groupId>
<artifactId>spring-core<artifactId>
</dependency>
so, the scope? is always compile, or can i specify?
compile is the default scope for a dependency (pom reference). You can specify scope also and it will be inherited

Dependeny Management using POM import

I am creating a project 'test-jar' in my local and i am using pom file which I don't have write access as Parent of 'test-jar' project. The parent project has already defined depedencyManagement with old versions.
As I have to update dependency versions in my project and planning to override parent's dependency Management. So, I have created another POM file with my own dependency Management and imported into 'test-jar' project.
My Project :
<project>
<artifactid>test-jar</artifactid>
<parent>
<artifactId> test-parent </artifactId>
</parent>
<dependencies>
<dependency>
<artifactId>jar/artifactId>
</dependency>
<dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>custom-pom</artifactId>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
</project>
My Parent Project:
<project>
<artifactid>test-parent</artifactid>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>jar/artifactId>
<version>1.0</version>
</dependency>
</dependencyManagement>
</project>
My Custom POM for updated dependencyManagement:
<project>
<artifactid>custom-pom</artifactid>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>jar</artifactId>
<version>3.0</version>
</dependency>
</dependencyManagement>
</project>
The problem is, I am always getting dependency version from parent pom, though i have imported new dependency management in project.
I am using Maven 2.2.1 version here.
Is there any solution how to overwrite Dependency Management from Parent POM ?
Based on the documentation:
This scope is only used on a dependency of type pom in the
section. It indicates that the specified POM
should be replaced with the dependencies in that POM's
section. Since they are replaced, dependencies
with a scope of import do not actually participate in limiting the
transitivity of a dependency.
Apart from your problem you can simply use differerent version which are different of the onses defined in the parent pom's dependencyManagement. Furthermore you could create a separate pom wich defines the dependencies with new version (dependencyManagement) and inherits from the given parent.

Resources