The problem I encountered is this, here is the definition in my POM file.\
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
In this dependency, It's having a sub-dependency which is starter-tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.0.0.RELEASE</version>
<scope>compile</scope>
</dependency>
But In my maven tree
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.0.0.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.3.6.RELEASE:compile
By the way this project have a parent, In parent There is a 2.3.6 starter-webdependency.
I want to know why the sub-dependency starter-tomcat in the web-starter I referenced 2.0.0 is not the 2.0.0 I see, but 2.3.6 in the parent dependency.
I got it.
There are two ways to solve this question
exclude your sub-dependency and add a new version dependency.
use to control this denpendency
Related
I have the following maven structure.
Parent Pom
<dependencyManagement>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
</dependency>
</dependencyManagement>
Service Pom
<parent>
<groupId>com.aliseeks.dependencies</groupId>
<artifactId>AliseeksLive</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
</dependencies>
Dependency Conflict:
[INFO] +- org.glassfish.jersey.core:jersey-client:jar:2.27:compile
[INFO] | +- org.glassfish.jersey.core:jersey-common:jar:2.25.1:compile
[INFO] | | +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.25.1:compile
Why does Maven pull in JerseyCommon 2.25? JerseyClient 2.27 clearly depends on JerseyCommon 2.25? Is this because JerseyClient 2.27 POM has ${project.version} as a variable and its somehow getting messed up with Dependency Management?
Dependency Tree Dump
jersey-client 2.27 version depends on jersey-common 2.27 version as per following link:
https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client/2.27
But it is definitely pulling 2.25 version of jersey-common after resolving transitive dependencies and maven finds 2.25 version as the nearest child. That's reason it decides to pull 2.25 version.
For the reference that such type of dependency conflict issues can be easily investigated with the help of maven-enforcer-plugin. Following link further explains usage of this plugin with example:
https://dzone.com/articles/solving-dependency-conflicts-in-maven
I have a project with a POM which specifies the dependency on spring-data-jpa like below:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
It is not with the version number, however when I run mvn:dependency:tree I can see the relevant section like below ...
| \- org.springframework:spring-orm:jar:4.3.3.RELEASE:compile
[INFO] +- **org.springframework.data:spring-data-jpa:jar:1.10.3.RELEASE**:compile
[INFO] | +- org.springframework.data:spring-data-commons:jar:1.12.3.RELEASE:compile
[INFO] | \- org.aspectj:aspectjrt:jar:1.8.9:compile
[INFO] +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile
[INFO] +- org.hibernate:hibernate-core:jar:5.0.11.Final:compile
... it shows it is with version 1.10.3.RELEASE.
I wonder how does it finally comes with the version number. I looked up, it is neither latest Maven Repository's Spring Data JPA version number nor there is a section in its parent POM defining that dependency. The project POM is like below:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot</artifactId>
<version>${camel-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${springboot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${springboot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${springboot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
The version of spring-data-jpa is provided by the spring-boot-parent.
You can see the relationship between spring-boot version and spring-data-jpa in the appendix-dependency-versions section of the Spring Boot docs.
For example, the latest version of Spring Boot will provide version 1.11.9.RELEASE of spring-data-jpa.
In your question you show: org.springframework.data:spring-data-jpa:jar:1.10.3.RELEASE this suggests that you are using v1.4.x of Spring Boot, the relevant dependency is shown in the docs for v1.4.1 of Spring Boot:
org.springframework.data spring-data-jpa 1.10.3.RELEASE
The relationship between spring-boot 1.4.1.RELEASE and spring-data-jpa 1.10.3.RELEASE is facilitated by Maven, since Maven follows the relationships defined in Spring Boot's POMs.
From the docs (my emphasis):
Each release of Spring Boot provides a curated list of dependencies that it supports. In practice, you do not need to provide a version for any of these dependencies in your build configuration, as Spring Boot manages that for you.
The curated list contains all the spring modules that you can use with Spring Boot as well as a refined list of third party libraries. The list is available as a standard Bills of Materials (spring-boot-dependencies) that can be used with both Maven and Gradle.
So, Spring Boot provides spring-boot-starter-data-jpa for you which in turn provides spring-data-jpa via a dependency on spring-data-releasetrain. The precise mechanism for this is:
spring-boot-starter-data-jpa declares a dependency on spring-data-jpa.
spring-boot-starter-data-jpa is parented by spring-boot-starters
spring-boot-starters is parented by spring-boot-parent
spring-boot-parent is parented by spring-boot-dependencies
spring-boot-dependencies imports the spring-data-releasetrain POM:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring-data-releasetrain.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
I have added a dependency in my parent pom under dependecymanagement.
ParentPom
<dependecyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>some version</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencyManagement>
In my child pom I am simply inherting the dependecy without version
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
When I do dependency tree on my child pom its still showing commons-logging in tree which is excluded in parent pom .
mvn dependency:tree -Dverbose -Dincludes=commons-logging:commons-logging
This is the dependecy tree from child.
[INFO] \- org.springframework:spring-core:jar:parent version .RELEASE:compile
[INFO] \- commons-logging:commons-logging:jar:some version:compile
Though version no is getting inherited why not excluded dependency is getting inherited from parent pom is what I am looking for.
Am I assuming anything wrong? or is that how maven behaves?
Valid solutions would be appreciated.
TIA
I'm using multiple spring based maven repositories in a web project, and I'm having problems with the dependencies used by child POM.
I have a parent POM like this:
<dependencyManagement>
<dependencies>
<!-- SPRING -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>4.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SPRING BOOT -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SPRING WS -->
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<!-- OTHER DEPENDENCIES OMITTED -->
</dependencies>
</dependencyManagement>
And a child POM like this:
<dependencies>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<!-- OTHER DEPENDENCIES OMITTED -->
</dependencies>
As far as my understanding of maven exclusion goes, this should avoid the overriding of the parent POM version, but due to the fact that spring-ws-security depends on a lower version of spring-core (4.0.9) whose method have been changed I can't deploy the app on a tomcat local server because of a NoSuchMethodError Exception, which can be also triggered when the app is actually deployed but the dependences to the old spring-core version remains.
How can I avoid this overriding of dependencies?
Or is there some way of using both dependencies (which as far as I've searched is not secure)?
Links visited already:
Similar problem, but from child to parent,
Exclusions example
Just a few mentions, I've visited others as well but forgot the links.
Edit: spring-ws dependencies use spring 4.0.9 which is overriding the 4.3.0 version (the one I need to use) I've defined in the parent POM.
+- org.springframework.ws:spring-ws-core:jar:2.2.3.RELEASE:compile
[INFO] | | | +- org.springframework:spring-oxm:jar:4.3.0.RELEASE:compile (version managed from 4.0.9.RELEASE)
[INFO] | | | +- org.springframework:spring-web:jar:4.3.0.RELEASE:compile (version managed from 4.0.9.RELEASE)
[INFO] | | | \- org.springframework:spring-webmvc:jar:4.3.0.RELEASE:compile (version managed from 4.0.9.RELEASE)
You can simply do explicit override in your child pom by mentioning the version 4.0.9, like below.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.9</version>
</dependency>
As quoted below, this version will affect the child-of-child pom, if any.
Forcing a version
A version will always be honoured if it is declared
in the current POM with a particular version - however, it should be
noted that this will also affect other poms downstream if it is itself
depended on using transitive dependencies.
Well, I'm not talking about the well-known commons-logging problem, I know I can disable it by setting the 99.0-does-not-exist version.
My problems is, some packages are contained in different dependencies, say, aspectjlib is contained both in org.aspectj:aspectjlib and aspectj:aspectjlib. In some cases, transitive dependencies may introduce the two jars at the same time, while of different versions, e.g., org.aspectj:aspectjlib:1.7.3, aspectj:aspectjlib:1.6.1. And mis-loading aspectj:aspectjlib:1.6.1 accidentally is not my intention. So is there a way like commons-logging that I can disable aspectj:aspectjlib completely?
I tried the same trick using 99.0-does-not-exist, only to find an error from maven:
[ERROR] Failed to execute goal on project XXX: Could not resolve
dependencies for project XXX:jar:1.0.0-SNAPSHOT: The following
artifacts could not be resolved:
aspectj:aspectjlib:jar:99.0-does-not-exist,
aspectj:aspectjrt:jar:99.0-does-not-exist,
aspectj:aspectjweaver:jar:99.0-does-not-exist: Could not find artifact
aspectj:aspectjlib:jar:99.0-does-not-exist in tbmirror
(http://mvnrepo.taobao.ali.com/mvn/repository) -> [Help 1]
Well, although some repositories do provide 99.0-does-not-exist for logging system dependencies like log4j, slf4j-log4j, commons-logging, etc., this is not a universal solution.
I find a solution to do this: use 'provided' scope.
To clarify, in my example above, I have two conflicting dependencies: org.aspectj:aspectjlib:1.7.3, aspectj:aspectjlib:1.6.1, I want to disable aspectj:aspectjlib:1.6.1, I only need to put this in top-level pom:
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjlib</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
in this way, aspectj:aspectjlib:1.6.1 will never appear in the final built lib.
You can use Maven's dependency exclusions to eliminate the version you don't want. Using your example:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>includes-new-aspectj</groupId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>includes-old-aspectj</groupId>
<exclusions>
<exclusion>
<groupId>org.aspectj<groupId>
<artifactId>aspectjlib</artifactId>
<exclusion>
</exclusions>
</dependency>
</dependencies>
Alternatively, you can simply pin the version you desire using dependency management:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjlib</artifactId>
<version>1.7.3</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>includes-new-aspectj</groupId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>includes-old-aspectj</groupId>
</dependency>
</dependencies>
If you are not sure which dependencies include which versions, you can use this to discover that info:
mvn dependency:tree -Dincludes='org.aspectj:aspectjlib'
There is no 99.0 version for aspectj:aspectjlib, your project is configured to use wrong version, check for 99.0 in your pom.xml