Inheriting the version of an optional dependency - java

My company has 3 Maven projects organized as follows:
Project A depends on Project B.
Project B depends on Project C. (Project B has set Project C as an Optional dependency in their POM)
I am the owner of Project A. I would like to add Project C as a direct dependency in my POM. However, I do not want to be responsible for keeping the version of Project C up to date. Is there a way I can inherit the version of Project C specified in Project B's POM at all times?

If you don't control project B, it's not possible, except possibly with some plugin hackery.
If you do control project B then you can declare a dependency management section in that project which you can additionally import into project A.
Project B POM
<dependencyManagement>
<groupId>com.foo</groupId>
<artifactId>project-c</artifactId>
<version>1.2.3</version>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>project-c</artifactId>
<!-- no need for version here, comes from dependencyManagement -->
<optional>true</optional>
</dependency>
</dependencies>
Project A POM
<properties>
<!-- using a property isn't necessary, but ensures the
POM import and dependency stay in sync -->
<project.b.version>2.3.4</project.b.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>project-b</artifactId>
<version>${project.b.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>project-b</artifactId>
<version>${project.b.version}</version>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>project-c</artifactId>
<!-- version is not necessary, imported from project-b's dependency management -->
</dependency>
</dependencies>
This will mean Project A will default to Project B for all dependencies in B's dependency management section. I don't think there's a way to restrict it to just a specific one. I doubt you'll care but just something to be aware of.
Any versions that Project A defines, either in its own dependency management or directly in <dependencies>, will override any version brought in from Project B's dependency management.

Related

Changing the version of a transitive dependency in maven pom.xml

I've been trying to override a transitive dependency version in one of my projects. I found the following sample project on github to experiment on ( https://github.com/Richou/swagger-codegen-maven-plugin). The parent pom of this project contains a dependency for swagger-codegen. Swagger-codegen in turn has a dependency called slf4j-ext whose version is 1.6.3. I want to upgrade/override the version of slf4j-ext to 1.7.30 from the parent pom. I tried adding the required slf4j-version inside the property tag in the parent pom but it didn't work when I checked the maven dependency tree. What is the correct method to do it?
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen</artifactId>
<version>2.1.2</version>
</dependency>
</dependencies>
<properties>
<slf4j-version>1.7.30</slf4j-version>
<java.version>1.7</java.version>
</properties>
You can add the slf4j-ext with the version you want in the dependencyManagement section of your parent pom.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-ext</artifactId>
<version>${slf4j-version}</version>
</dependency>
</dependencies>
</dependencyManagement>

How to use unique child dependency version from parent in maven

I have a long list of modules getting properties from a parent module in maven. I want one of the modules to use a different version of spring from the parent. The other modules are using an older version of spring which will not work with module-c.
Is there a way to make the child module use its own version of spring?
// Parent
<groupId>xxx.xx.com</groupId>
<artifactId>test-environment</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>test-environment</name>
<properties>
<spring.version>4.0.6.RELEASE</spring.version>
</properties>
<modules>
<module>module-a</module>
<module>module-b</module>
<module>module-c</module>
</modules>
</project>
//Child
<project>
<parent>
<groupId>xxx.xx.com</groupId>
<artifactId>test-environment</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module-c</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
</dependencies>
</project>
//Error
java.lang.NoSuchMethodError: org.springframework.core.ResolvableType.forInstance(Ljava/lang/Object;)Lorg/springframework/core/ResolvableType;
at org.springframework.context.event.SimpleApplicationEventMulticaster.resolveDefaultEventType(SimpleApplicationEventMulticaster.java:144)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:121)
at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111)
at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:60)
at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:48)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:149)
Your approach with declaring newer dependency directly in the child pom.xml is correct. As per Introduction to the Dependency Mechanism:
Dependency mediation - this determines what version of an artifact will be chosen when multiple versions are encountered as dependencies. Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM.
You most likely need to add spring-core on which the spring-context depends to have the right version of org.springframework.core.ResolvableType class and avoid NoSuchMethodError:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
Running with multiple version of Spring in the classpath is asking for runtime problems. It's best to keep all the Spring JARs in the same version in your runtime deployment.

`'dependencies.dependency.version'` is missing in multi module inherited project though we use <dependencymanagement>

I have a common dependency that needs to be used across different poms.Here for ex spring-ws-core is what I need to use on Pom A, Pom B etc .Pom A will inherit properly but when I remove the version in Pom B it is throwing issue.
Common
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>5.0 RELEASE</version>
</dependency>
Pom A
<dependecyManagement>
<dependencies>
<dependency>
<groupId>Common</groupId>
<artifactId>Common</artifactId>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependecyManagement>
<dependencies>
Note:I am not using version since it is inheriting from
<dependencymangement > centralized pom
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<dependency>
</dependencies>
Pom B:
**Parent will be Pom A **
<parent>
<groupId>Pom A</groupId>
<artifactId>Pom A</artifactId>
<version>someversion</version>
<relativePath>pom A.xml</relativePath>
</parent>
This doesn't have <dependencymanagement> since it should be inherited from Pom A since Pom A has <dependecymanagement>
Now my issue if I add any dependency without version in Pom B it is throwing 'dependencies.dependency.version' is missing.How to inherit to Pom B from common is what I am looking for .If I add <dependencymanagement> in Pom B it is not working as expected .
Anyone can shed some light would be appreciated.

Maven manage dependencies via another pom

I have two maven projects.
-- my-common-lib
-- my-web-application
my-common-lib - contains just a pom which all dependencies.
my-web-application - is a web application.
Is there a maven plugin which I can define in "my-application" pom that makes that all dependencies defined in "my-common-lib" should not be added to "WEB-INF/lib" when building my-web-application project .
Thanks
Sundar
You can use the following to import dependencies from the other artifact.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.sample<groupId>
<artifactId>myartifact</artifactId>
<version>0.0.1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

Maven - moved code to new artifact; transitive dependencies issue

Here is my situation:
I created a new artifact in a library called 'web-ng-framework', and moved code into it from an old artifact in the library, 'web'
I deleted the 'web' artifact
And here is the problem:
ProjectA uses an older version of the library, and so it has a compile dependency on 'web'
ProjectB depends on ProjectA
ProjectB uses the latest version of the library, so when ProjectB is built, it contains both the 'web' and 'web-ng-framework' libraries, causing a possible conflict
Does anyone know how I can solve this? Thanks!
EDIT:
Would doing 'relocation' of 'web' to 'web-ng-framework' maybe work better? In ProjectA, I could include a dependency on 'web' so that Maven would see that what it really needs is 'web-ng-framework'. Would that work?
When including ProjectA in ProjectB exclude web. Like this
<dependency>
<groupId>your.group</groupId>
<artifactId>projectA</artifactId>
<exclusions>
<exclusion>
<groupId>your.group</groupId>
<artifactId>web</artifactId>
</exclusion>
</exclusions>
</dependency>
A classic solution to this problem is the 'Version 99' hack.
To do this, use the following in your root pom:
<dependencyManagement>
<dependency>
<groupId>your.group</groupId>
<artifactId>web</artifactId>
<version>99.0-does-not-exist</version>
</dependency>
</dependencyManagement>
Then put an empty web-99.0-does-not-exist.pom and web-99.0-does-not-exist.jar in your repository.
This ensures that every project that inherits from this root pom will not get the old version of the web.jar anymore.
I suggest that you use optional dependencies
This can be acheived by making web depencency optional in projectA.
<project>
<groupId>some.group</groupId>
<artifactId>projectA</artifactId>
...
<dependencies>
<!-- declare the dependency to be set as optional -->
<dependency>
<groupId>some.group</groupId>
<artifactId>web</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
When declaring some other project that depends on projectA the web dependency will not be included.
<project>
<groupId>some.group</groupId>
<artifactId>projectB</artifactId>
...
<dependencies>
<dependency>
<groupId>some.group</groupId>
<artifactId>projectA</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>some.group</groupId>
<artifactId>web-ng-framework</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
Now projectB will only have a dependency on projectA and web-ng-framework, not web.

Categories