37

I am having a problem with a transitive dependency of my grails-flyway plugin. org.grails.plugins:grails-flyway:0.2.1 declares a dependency to org.flywaydb:flyway-core:4.0.1. When I include the plugin into my Grails 3.1.6 project Gradle downgrades Flyway to version 3.2.1.

+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1

My Gradle build file looks like this

buildscript {
    ext {
        grailsVersion = project.grailsVersion
    }
    repositories {
        maven { url "https://repo.grails.org/grails/core" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:${assetPipelinePluginVersion}"
        classpath "org.grails.plugins:hibernate5:5.0.5"
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0'
    }
}

version "0.40.15"
group "zsc.supporter"

apply plugin: "war"
apply plugin: "org.grails.grails-web"
apply plugin: "org.grails.grails-gsp"
apply plugin: "org.grails.grails-doc"
apply plugin: "asset-pipeline"
apply plugin: 'com.github.ben-manes.versions'

ext {
    grailsVersion = project.grailsVersion
    gradleWrapperVersion = project.gradleWrapperVersion
}

repositories {
    maven { url "https://repo.grails.org/grails/core" }
    maven { url "https://dl.bintray.com/saw303/plugins" }
}

dependencyManagement {
    imports {
        mavenBom "org.grails:grails-bom:$grailsVersion"
    }
    applyMavenExclusions false
}

dependencies {
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile "org.springframework.boot:spring-boot-starter-tomcat"
    compile "org.grails:grails-dependencies"
    compile "org.grails:grails-web-boot"
    compile "org.grails.plugins:cache"
    compile "org.grails.plugins:scaffolding"
    compile "org.grails.plugins:hibernate4"
    compile "org.hibernate:hibernate-ehcache"
    console "org.grails:grails-console"
    profile "org.grails.profiles:web:3.1.6"
    runtime "com.bertramlabs.plugins:asset-pipeline-grails:${assetPipelinePluginVersion}"
    runtime "com.h2database:h2"
    testCompile "org.grails:grails-plugin-testing"
    testCompile "org.grails.plugins:geb"
    testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.52.0"
    testRuntime "net.sourceforge.htmlunit:htmlunit:2.21"

    compile "org.grails.plugins:spring-security-core:3.0.4"
    compile "org.grails.plugins:quartz:2.0.8"
    compile "org.grails.plugins:mail:2.0.0.RC4"
    compile "eu.bitwalker:UserAgentUtils:1.18"
    compile 'org.mnode.ical4j:ical4j:1.0.7'
    compile 'org.grails.plugins:browser-detection:3.1.0'
    compile "com.googlecode.libphonenumber:libphonenumber:7.3.1"
    runtime 'org.grails.plugins:grails-flyway:0.2.1'

    testCompile "org.grails.plugins:grails-wizer:0.3"
    testCompile 'org.grails:grails-datastore-test-support:5.0.5.RELEASE'

    runtime 'mysql:mysql-connector-java:5.1.29'
}

task wrapper(type: Wrapper) {
    gradleVersion = gradleWrapperVersion
}

assets {
    minifyJs = true
    minifyCss = true
}

Currently I do not understand why Gradle downgrades my transitive dependency. Can someone provide on this?

I am aware that I can force the flyway-core:4.0.1 dependency in my build.gradle but I would like to understand what the downgrade causes.

UPDATE-1

When I run gradle dependencies | grep flyway I get the following output.

+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1
+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1
+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1
+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1

Please find the complete output at pastebin. The grails-flyway plugin and its pom.xml can be found at Bintray.

UPDATE-2

I tried to force Gradle to use org.flywaydb:flyway-core:4.0.1 according to Gradles Reference.

configurations.all {
    resolutionStrategy.force 'org.flywaydb:flyway-core:4.0.1'
}

That does not affect the problem. The dependency tree still uses version 3.2.1 of flyway-core.

+--- org.grails.plugins:grails-flyway:0.2.1
|    \--- org.flywaydb:flyway-core:4.0.1 -> 3.2.1

UPDATE-3

Gradles dependencyInsight command

gradle dependencyInsight --dependency flyway-core --configuration runtime

results in

:dependencyInsight
org.flywaydb:flyway-core:3.2.1 (selected by rule)

org.flywaydb:flyway-core:4.0.1 -> 3.2.1
\--- org.grails.plugins:grails-flyway:0.2.1
     \--- runtime 

What means (selected by rule)?

"Solution" - or how to work it around

I was not able to find the rule that causes Gradle to use flyway-core:3.2.1 instead of flyway-core:4.0.1. But I found a way to work around the problem.

I added the following to my build.gradle to modify my Gradle runtime resolution strategy.

configurations.runtime.resolutionStrategy {

    eachDependency { DependencyResolveDetails det ->

        if (det.requested.name == 'flyway-core' && det.requested.group == 'org.flywaydb') {
            det.useVersion(det.requested.version)
        }
    }
}
saw303
  • 8,051
  • 7
  • 50
  • 90
  • Is there any other dependency, which is dependent on `org.flywaydb:flyway-core:3.2.1`? Just as suppose, that there is some lib, with dependency on older version and Gradle just solves this by downgrading the plugin's version, because it seems to be most evident way – Stanislav May 11 '16 at 06:24
  • I cannot find any other flyway-core version with the dependency tree. :( – saw303 May 11 '16 at 07:14
  • You can try to inverse your search by running `./gradlew dependencyInsight --dependency flyway-core`. Then you should be able to see who requieres flyway-core. Maybe that gives you a hint – TobiSH May 11 '16 at 09:14
  • You can use this solution: https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/165#issuecomment-295651715 – Grisotto Jul 19 '18 at 17:33

2 Answers2

31

The thing causing it is the spring-boot-dependencies-1.3.3.RELEASE.pom

This forcing the flyway version to 3.2.1

According to the Spring Boot docs you should be able to add a line like this to your build.gradle: ext['flyway.version'] = '4.0.1'

Hans Bogaards
  • 648
  • 5
  • 12
  • how do you find out what dependency has such transitive dependency with lower version? I have similar problem, but cennot find out where does it come from, so I cannot determine what `ext[...]` should i overwrite – Zavael Nov 11 '20 at 15:23
  • 6
    the problem is, how do you find **it is the`spring-boot-dependencies-1.3.3.RELEASE.pom`** – http8086 Sep 07 '21 at 05:16
26

Goto your Gradle cache files folder:

cd ~/.gradle/caches/modules-2/files-2.1

search this version number:

grep -r "3.2.1" *

you will find out which pom file is using this version, usually it's something in spring-boot-dependencies-x.y.z.RELEASE.pom :

<flyway.version>3.2.1</flyway.version>
......
<groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>${flyway.version}</version>
</dependency>

which means, if you use spring-boot, it will overwrite some dependency version.

you can overwrite it again, by adding the following line in your gradle.properties file:

flyway.version=4.0.1

I encounter a similar problem and wasted several hours on it. So I left this information here, hope this could save your time if you get stuck into this problem

saw303
  • 8,051
  • 7
  • 50
  • 90
Li Ying
  • 2,261
  • 27
  • 17
  • Good catch. Here's my slightly more efficient command, assuming you know you're looking for 'pom' files: `find -name "*pom" -type f -exec grep -Hn '3.0.4.RELEASE' '{}' +` – Sparky Nov 10 '22 at 14:56