Gradle 选择了错误的依赖版本

Posted

技术标签:

【中文标题】Gradle 选择了错误的依赖版本【英文标题】:Gradle is selecting wrong dependency version 【发布时间】:2018-06-12 10:05:27 【问题描述】:

我在我的 Gradle 构建中发现了一些奇怪之处。我有一个 Spring Boot 应用程序(它使用 Gradle 进行构建),并试图同时引入 Hibernate Validator 和 Hibernate Core。这是我的build.gradle 文件中的dependencies 声明:

dependencies 
    compile('org.springframework.boot:spring-boot-starter-web') 
        exclude module: 'spring-boot-starter-tomcat'
    

    compile(
        'org.codehaus.groovy:groovy-all:2.4.12'
        ,'com.google.inject:guice:4.1.0'
        ,'ch.qos.logback:logback-classic:1.2.3'
        ,'org.slf4j:jul-to-slf4j:1.7.25'
        ,'org.apache.logging.log4j:log4j-to-slf4j:2.9.1'
        ,'commons-cli:commons-cli:1.4'
        ,'org.apache.commons:commons-lang3:3.7'
        ,'io.dropwizard.metrics:metrics-core:3.2.5'
        ,'io.dropwizard.metrics:metrics-json:3.2.5'
        ,'org.springframework.security:spring-security-jwt:1.0.9.RELEASE'
        ,'org.springframework.security.oauth:spring-security-oauth2:2.2.1.RELEASE'
        ,'io.jsonwebtoken:jjwt:0.9.0'
        ,'org.hibernate:hibernate-validator:6.0.7.Final'
        ,'mysql:mysql-connector-java:6.0.6'
        ,'org.hibernate:hibernate-core:5.2.12.Final'

        ,'com.h2database:h2:1.4.196'

        ,'org.springframework.boot:spring-boot-starter-jetty'
        ,'org.springframework.boot:spring-boot-starter-actuator'
        ,'org.springframework.boot:spring-boot-starter-security'
        ,'org.springframework.boot:spring-boot-starter-data-rest'
        ,'org.springframework.boot:spring-boot-starter-data-jpa'
    )

    dev('org.springframework.boot:spring-boot-devtools')

    testCompile(
        'org.spockframework:spock-core:1.0-groovy-2.4'
        ,'junit:junit:4.12'
    )

当我运行 ./gradlew dependencies 时,我得到了巨大的输出,但从 compile 依赖关系树中我看到以下内容:

|    +--- org.springframework.boot:spring-boot-starter:1.5.8.RELEASE
|    +--- org.hibernate:hibernate-validator:5.3.5.Final -> 6.0.7.Final
|    |    \--- org.hibernate.validator:hibernate-validator:6.0.7.Final
|    |         +--- javax.validation:validation-api:2.0.1.Final -> 1.1.0.Final
|    |         +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.1.Final
|    |         \--- com.fasterxml:classmate:1.3.1 -> 1.3.4

所以在我看来,spring-boot-starter:1.5.8.RELEASE 似乎在拉动validation-api:2.0.1.Final,但出于某种原因,Gradle 为我选择了validation-api:1.1.0.Final……我读对了吗?在我的 IDE 编译类路径中,我只看到 validation-api:1.1.0.Final,而不是 2.0.1.Final

为什么 Gradle 选择 1.1.0.Final 而不是 2.0.1.Final 我问是因为 Hibernate Validator 5.x is not compatible with Validation API 1.x 并且当我的应用程序运行时,我会遇到各种与 Hibernate Validation 相关的错误。

更新

更多输出:

gradle -q dependencyInsight --configuration compile --dependency validation-api
javax.validation:validation-api:1.1.0.Final (selected by rule)

javax.validation:validation-api:2.0.1.Final -> 1.1.0.Final
\--- org.hibernate.validator:hibernate-validator:6.0.7.Final
     \--- org.hibernate:hibernate-validator:6.0.7.Final
          +--- compile
          \--- org.springframework.boot:spring-boot-starter-web:1.5.8.RELEASE
               +--- compile
               \--- org.springframework.boot:spring-boot-starter-data-rest:1.5.8.RELEASE
                    \--- compile

完整的编译配置输出can be found here。

【问题讨论】:

发布编译配置的完整树。还可以考虑使用dependencyInsight (mrhaki.blogspot.fr/2014/08/…) 并发布输出。 感谢@JBNizet (+1) - 请参阅我的 pastebin 链接添加到此问题的顶部。如果对您有帮助,我还为validation-api 库添加了dependencyInsigh 的输出!再次感谢! 【参考方案1】:

版本由 Spring Boot 强制执行。

查看 POM 以了解 Spring Boot 依赖项:http://search.maven.org/remotecontent?filepath=org/springframework/boot/spring-boot-dependencies/1.5.8.RELEASE/spring-boot-dependencies-1.5.8.RELEASE.pom 并查找“javax-validation.version”。

有关如何覆盖 Spring Boot 版本的更多信息,请参阅 https://docs.spring.io/platform/docs/Brussels-SR4/reference/html/getting-started-overriding-versions.html。

我建议直接覆盖“javax-validation.version”和“hibernate-validator.version”,而不是重新定义依赖项。

【讨论】:

感谢@Guaillaume (+1) 我以前从未这样做过(直接覆盖 javax.validation.version + hibernate-validator.version)。这是我在 build.gradle 或 application.yml 中做的事情吗? 查看我给你的链接,你有一段关于如何用 Gradle 覆盖版本:docs.spring.io/platform/docs/Brussels-SR4/reference/html/…。 谢谢,我看到了,所以这个 ext['foo.version'] = '1.1.0.RELEASE' 声明,我是把它放在 Gradle 中的 dependencies 声明中,还是把它放在那个声明之外(可能在它上面,等等)? 我更像是一个 Maven 人,但我会在依赖声明上方的 build.gradle 的根部说(啊,使用 javax.validation.version,而不是 foo.version ;)) . 文档中描述的 gradle 覆盖对我不起作用。但是这样做了:github.com/spring-projects/spring-boot/issues/6507【参考方案2】:

与另一个在编译类路径中拉旧 1.1.0 的依赖项存在一些冲突。

这意味着其他一些在 gradle 构建顺序中具有更高优先级的库依赖于旧的 1.1.0 版本。

您可以在此处查看more info,了解如何指定 gradle 构建顺序。

【讨论】:

谢谢@Tal (+1) - 请查看我的 pastebin 链接添加到这个问题的顶部。如果对您有帮助,我还为验证 API 库添加了dependencyInsigh 的输出!再次感谢! 另外@Tal 根据所有这些依赖树的输出,org.hibernate.validator:hibernate-validator:6.0.7.Final 是唯一拉入validation-api... 注意休眠版本 5.x.x 。下拉 javax.validation:validation-api:1.1.0.Final 我看到你也有 org.hibernate:hibernate-core:5.2.12.Final 谢谢@Tal,但我不明白你的意思......它听起来就像你在说org.hibernate:hibernate-core:5.2.12.Final 拉下validation-api:1.1.0.Final 但我没有看到在我的依赖树中证明了这一点。能再详细一点吗? 你有--- org.hibernate:hibernate-validator:5.3.5.Final -> 6.0.7.Final | | \--- org.hibernate.validator:hibernate-validator:6.0.7.Final【参考方案3】:

我遇到过类似的问题,后来发现是使用gradle中的依赖管理引起的:

plugins 
     ...
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'


dependencyManagement 
    imports 
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR8"
    

这种依赖管理影响传递依赖版本解决方案。注释掉之后。所有版本都是正确的。

【讨论】:

以上是关于Gradle 选择了错误的依赖版本的主要内容,如果未能解决你的问题,请参考以下文章

我在 Kapt Debug Kotlin 中遇到错误。我在 gradle 文件中更新了依赖项的版本。仍然面临这个问题

将SDK版本26更改为28时如何解决Gradle错误

Gradle - 获取依赖项的最新发布版本

错误:Android Gradle 插件仅支持 Kotlin Gradle 插件版本 1.3.0 及更高版本

Gradle下载依赖错误

错误:无法打开 zip 文件。 Gradle 的依赖缓存可能已损坏