I am using: * Spring Boot 2.3.M4 * Gradle 6.3 * AdoptOpenJDK-14
My build is using the Spring Boot and the Spring Dependency management plugin:
buildscript {
repositories {
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
plugins {
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
apply plugin: "org.springframework.boot"
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude module: "spring-boot-starter-tomcat"
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// …
}
On applying Querydsl to the project I've noticed that two versions of javax.persistence.Entity
are pulled into the classpath:
- 1st via
jakarta.persistence:jakarta.persistence-api
as direct dependency oforg.springframework.boot:spring-boot-starter-data-jpa
- 2nd via
javax.persistence:javax.persistence-api
as transitive dependencies oforg.hibernate:hibernate-core
This results in duplicated classes on the classpath and might cause hard to track down problems.
Please see attached screenshots.
Is that the intended behaviour? Am I missing something here?
Comment From: wilkinsona
Thanks for the report. This isn't intended behaviour. We've seen this problem before (https://github.com/spring-projects/spring-boot/issues/20532) but it should have been fixed by Gradle 6.3. Can you please double-check that you are using that version of Gradle?
Comment From: holgerstolzenberg
Comment From: holgerstolzenberg
Here is the version output from the CLI:
❯ ./gradlew --version
------------------------------------------------------------
Gradle 6.3
------------------------------------------------------------
Build time: 2020-03-24 19:52:07 UTC
Revision: bacd40b727b0130eeac8855ae3f9fd9a0b207c60
Kotlin: 1.3.70
Groovy: 2.5.10
Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM: 14.0.1 (AdoptOpenJDK 14.0.1+7)
OS: Mac OS X 10.15.4 x86_64
Comment From: holgerstolzenberg
As there are other dependencies involved, I could provide the full build script, but it looks like javax.persistence:javax.persistence-api
does not get excluded from Hibernate.
Comment From: wilkinsona
On second reading, I suspect "on applying Querydsl to the project" is key to this. I can't see that dependency in the build.gradle
script your provided above.
My suspicion is that QuerryDSL has a transitive dependency on hibernate-core
where there is no exclusion of the javax.persistence:javax.persistence-api
dependency. For an exclusion to be effective in Gradle, it has to be applied on all routes to the unwanted dependency. We may be able to add an exclusion in our dependency management for QueryDSL, but we'll need confirmation of my assumption first. Can you please provide a complete and minimal build.gradle
script that reproduces the behaviour you have described?
Comment From: holgerstolzenberg
Commenting out the querydsl dependencies does not make a difference in my build. I have stripped down the build script:
buildscript {
repositories {
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
plugins {
id 'org.gradle.wrapper'
id 'org.gradle.java'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
// TODO scheduled RC 24.04. id 'org.springframework.boot'
id 'com.intershop.gradle.buildinfo' version '6.0.0'
}
apply plugin: "org.springframework.boot"
wrapper {
gradleVersion = '6.3'
}
repositories {
maven {
url "http://repo.spring.io/milestone"
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
annotationProcessor 'javax.annotation:javax.annotation-api'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor group: 'com.querydsl', name: 'querydsl-apt', classifier: 'jpa'
compileOnly 'org.springframework.boot:spring-boot-devtools'
compileOnly "org.projectlombok:lombok"
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude module: "spring-boot-starter-tomcat"
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation "org.zalando:problem-spring-web-starter:${zalandoProblemVersion}"
implementation "org.springdoc:springdoc-openapi-ui:${openApiUiVersion}"
implementation "com.google.guava:guava:${guavaVersion}"
implementation 'org.flywaydb:flyway-core'
implementation 'org.postgresql:postgresql'
implementation 'org.hibernate:hibernate-java8'
implementation 'com.querydsl:querydsl-jpa'
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
testAnnotationProcessor "org.projectlombok:lombok"
testCompileOnly "org.projectlombok:lombok"
testImplementation "org.springframework.cloud:spring-cloud-starter"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation "io.rest-assured:rest-assured:${restAssuredVersion}"
testImplementation "io.rest-assured:json-path:${restAssuredVersion}"
testImplementation "io.rest-assured:xml-path:${restAssuredVersion}"
testImplementation 'org.assertj:assertj-core'
testImplementation "com.playtika.testcontainers:embedded-keycloak:${testcontainersVersion}"
testImplementation "com.playtika.testcontainers:embedded-postgresql:${testcontainersVersion}"
}
compileJava {
// so that spring-boot config processor picks up meta data
inputs.files(processResources)
}
bootJar {
excludeDevtools = true
}
Let me know if you need the full one.
guavaVersion=28.2-jre
openApiUiVersion=1.2.33
mapstructVersion=1.3.1.Final
restAssuredVersion=4.2.0
springBootVersion=2.3.0.M4
springCloudVersion=Hoxton.SR3
testcontainersVersion=1.48
zalandoProblemVersion=0.25.2
Comment From: wilkinsona
Thanks. That's not really minimal, but I think I've managed to identify the problem. It's caused by your org.hibernate:hibernate-java8
dependency. It introduces another route to org.hibernate:hibernate-core
that does not exclude javax.persistence:persistance-api
. You can avoid the problem by adding an exclusion:
implementation('org.hibernate:hibernate-java8') {
exclude group: 'javax.persistence', module: 'javax.persistence-api'
}
I also had to correct the milestone repository URLs (to use HTTPS) and add mavenCentral()
. This left things looking like the following:
buildscript {
repositories {
maven {
url "https://repo.spring.io/milestone"
}
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
plugins {
id 'org.gradle.wrapper'
id 'org.gradle.java'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
// TODO scheduled RC 24.04. id 'org.springframework.boot'
id 'com.intershop.gradle.buildinfo' version '6.0.0'
}
apply plugin: "org.springframework.boot"
wrapper {
gradleVersion = '6.3'
}
repositories {
maven {
url "https://repo.spring.io/milestone"
mavenCentral()
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
annotationProcessor 'javax.annotation:javax.annotation-api'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor group: 'com.querydsl', name: 'querydsl-apt', classifier: 'jpa'
compileOnly 'org.springframework.boot:spring-boot-devtools'
compileOnly "org.projectlombok:lombok"
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude module: "spring-boot-starter-tomcat"
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation "org.zalando:problem-spring-web-starter:${zalandoProblemVersion}"
implementation "org.springdoc:springdoc-openapi-ui:${openApiUiVersion}"
implementation "com.google.guava:guava:${guavaVersion}"
implementation 'org.flywaydb:flyway-core'
implementation 'org.postgresql:postgresql'
implementation('org.hibernate:hibernate-java8') {
exclude group: 'javax.persistence', module: 'javax.persistence-api'
}
implementation 'com.querydsl:querydsl-jpa'
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
testAnnotationProcessor "org.projectlombok:lombok"
testCompileOnly "org.projectlombok:lombok"
testImplementation "org.springframework.cloud:spring-cloud-starter"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation "io.rest-assured:rest-assured:${restAssuredVersion}"
testImplementation "io.rest-assured:json-path:${restAssuredVersion}"
testImplementation "io.rest-assured:xml-path:${restAssuredVersion}"
testImplementation 'org.assertj:assertj-core'
testImplementation "com.playtika.testcontainers:embedded-keycloak:${testcontainersVersion}"
testImplementation "com.playtika.testcontainers:embedded-postgresql:${testcontainersVersion}"
}
compileJava {
// so that spring-boot config processor picks up meta data
inputs.files(processResources)
}
bootJar {
excludeDevtools = true
}
org.hibernate:hibernate-java8
is now empty as the functionality has been merged into hibernate-core
. I'd recommend you remove the dependency entirely.
In the future, please use Gradle's built in support for diagnosing this sort of problem. You can use dependencyInsight
to see that hibernate-java8
was involved in the dependency being present:
$ gradle dependencyInsight --dependency javax.persistence:javax.persistence-api
> Task :dependencyInsight
javax.persistence:javax.persistence-api:2.2
variant "compile" [
org.gradle.status = release (not requested)
org.gradle.usage = java-api
org.gradle.libraryelements = jar (compatible with: classes)
org.gradle.category = library
Requested attributes not found in the selected variant:
org.gradle.dependency.bundling = external
org.gradle.jvm.version = 8
]
Selection reasons:
- Selected by rule
- By constraint
javax.persistence:javax.persistence-api:2.2
+--- org.hibernate:hibernate-core:5.4.13.Final
| +--- org.springframework.boot:spring-boot-starter-data-jpa:2.3.0.M4 (requested org.hibernate:hibernate-core)
| | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-data-jpa)
| | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4
| | +--- org.springframework.boot:spring-boot-starter-web:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-web)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-jetty:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-jetty)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-actuator:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-actuator)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-security:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-security)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-data-jpa:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-oauth2-resource-server)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-oauth2-client:2.3.0.M4
| | | +--- compileClasspath (requested org.springframework.boot:spring-boot-starter-oauth2-client)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-json:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter-web:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-aop:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter-data-jpa:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-jdbc:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter-data-jpa:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter-web:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-actuator:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-security:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-oauth2-client:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-json:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-aop:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-starter-jdbc:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-actuator-autoconfigure:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter-actuator:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-autoconfigure:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter:2.3.0.M4 (*)
| | | +--- org.zalando:problem-spring-web-autoconfigure:0.25.2 (requested org.springframework.boot:spring-boot-autoconfigure:2.2.0.RELEASE)
| | | | \--- org.zalando:problem-spring-web-starter:0.25.2
| | | | \--- compileClasspath
| | | +--- org.springdoc:springdoc-openapi-common:1.2.33 (requested org.springframework.boot:spring-boot-autoconfigure:2.2.4.RELEASE)
| | | | \--- org.springdoc:springdoc-openapi-webmvc-core:1.2.33
| | | | \--- org.springdoc:springdoc-openapi-ui:1.2.33
| | | | \--- compileClasspath
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter:2.3.0.M4 (*)
| | | +--- org.springframework.boot:spring-boot-autoconfigure:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-starter-logging:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-starter:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | +--- org.springframework.boot:spring-boot-actuator:2.3.0.M4
| | | +--- org.springframework.boot:spring-boot-actuator-autoconfigure:2.3.0.M4 (*)
| | | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| | \--- org.springframework.boot:spring-boot-devtools:2.3.0.M4
| | +--- compileClasspath (requested org.springframework.boot:spring-boot-devtools)
| | \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| +--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
| \--- org.hibernate:hibernate-java8:5.4.13.Final
| +--- compileClasspath (requested org.hibernate:hibernate-java8)
| \--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
\--- org.springframework.boot:spring-boot-dependencies:2.3.0.M4 (*)
(*) - dependencies omitted (listed previously)
Comment From: holgerstolzenberg
Fix confirmed - removed dependency completely. Thanks for pointing me in the right direction. Didn't know about dependencyInsight
which is quite useful.