Scenario
In a spring-boot application that uses spring-boot-dependencies instead of spring-boot-starter-parent and a third party library that depends on elasticsearch version that is not comparable with version 6.x, elasticsearch dependency version get mixed up creating class loading issue.
Steps to reproduce
Create a spring-boot project and include spring-boot-dependencies in the dependency management section of the maven pom.xml
<properties>
<spring.boot.version>2.1.6.RELEASE</spring.boot.version>
<spring.cloud.version>Greenwich.RELEASE</spring.cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Later, in the dependencies section include a third party library that depends on elastic search version 5.6.8
<dependnecies>
<dependency>
<groupId>com.netflix.conductor</groupId>
<artifactId>conductor-es5-persistence</artifactId>
<version>2.8.1</version>
</dependency>
</dependnecies>
Note that conductor-es5-persistence depends on elasticsearch version 5.6.8
The try to run mvn dependency:tree
on your project and observe the following:
[INFO] +- com.netflix.conductor:conductor-es5-persistence:jar:2.8.1:compile
[INFO] | +- org.elasticsearch:elasticsearch:jar:6.4.3:compile
[INFO] | | +- org.elasticsearch:elasticsearch-core:jar:6.4.3:compile
Where 6.4.3 is coming from?
Diagnostic
Turns out mvn dependency:tree
shows the issue, but it does not say where org.elasticsearch:elasticsearch:jar:6.4.3:compile
is comming from. The best command for the job is:
mvn -Dverbose=true help:effective-pom
This command outputs effective POM that can be redirected to a file mvn -Dverbose=true help:effective-pom > ~/pom.xml
and analysed. The effective pom will look something like this
...
<dependency>
<groupId>org.elasticsearch</groupId> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1965 -->
<artifactId>elasticsearch</artifactId> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1966 -->
<version>6.4.3</version> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1967 -->
</dependency>
...
Magic! now we can see exactly where the problem is:
<!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1967 -->
Solution
Lets look at this import dependency:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
spring-boot-dependencies is imported, so there is no easy way to exclude elasticsearch dependency that it pulls into our project. A simple maven <exclude>
will not work here. The only way to solve the issue is to bring elasticsearch dependencies into your project dependency management block like this:
<properties>
<spring.boot.version>2.1.6.RELEASE</spring.boot.version>
<spring.cloud.version>Greenwich.RELEASE</spring.cloud.version>
<elasticsearch.version>5.6.8</elasticsearch.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.distribution.integ-test-zip</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
Now run mvn -Dverbose=true help:effective-pom
and confirm that the problem is fixed.