title: Why does Gradle downgrade my transitive dependencies in a Grails 3.1 application?
body: <p>I am having a problem with a transitive dependency of my <code>grails-flyway</code> plugin. <code>org.grails.plugins:grails-flyway:0.2.1</code> declares a dependency to <code>org.flywaydb:flyway-core:4.0.1</code>. When I include the plugin into my Grails 3.1.6 project Gradle downgrades Flyway to version 3.2.1.</p>
  
  <pre><code>+--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  </code></pre>
  
  <p>My Gradle build file looks like this</p>
  
  <pre><code>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
  }
  </code></pre>
  
  <p>Currently I do not understand why Gradle downgrades my transitive dependency. Can someone provide on this?</p>
  
  <p>I am aware that I can force the <code>flyway-core:4.0.1</code> dependency in my <code>build.gradle</code> but I would like to understand what the downgrade causes.</p>
  
  <p><strong>UPDATE-1</strong></p>
  
  <p>When I run <code>gradle dependencies | grep flyway</code> I get the following output.</p>
  
  <pre><code>+--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  +--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  +--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  +--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  </code></pre>
  
  <p>Please find the complete output at <a href="http://pastebin.com/MtKVu83y" rel="noreferrer">pastebin</a>. The <code>grails-flyway</code> plugin and its pom.xml can be found at <a href="https://bintray.com/saw303/plugins/grails-flyway/0.2.1/view#files/org/grails/plugins/grails-flyway/0.2.1" rel="noreferrer">Bintray</a>.</p>
  
  <p><strong>UPDATE-2</strong></p>
  
  <p>I tried to force Gradle to use <code>org.flywaydb:flyway-core:4.0.1</code> according to <a href="https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html" rel="noreferrer">Gradles Reference</a>.</p>
  
  <pre><code>configurations.all {
      resolutionStrategy.force 'org.flywaydb:flyway-core:4.0.1'
  }
  </code></pre>
  
  <p>That does not affect the problem. The dependency tree still uses version 3.2.1 of <code>flyway-core</code>.</p>
  
  <pre><code>+--- org.grails.plugins:grails-flyway:0.2.1
  |    \--- org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  </code></pre>
  
  <p><strong>UPDATE-3</strong></p>
  
  <p>Gradles <code>dependencyInsight</code> command</p>
  
  <pre><code>gradle dependencyInsight --dependency flyway-core --configuration runtime
  </code></pre>
  
  <p>results in </p>
  
  <pre><code>:dependencyInsight
  org.flywaydb:flyway-core:3.2.1 (selected by rule)
  
  org.flywaydb:flyway-core:4.0.1 -&gt; 3.2.1
  \--- org.grails.plugins:grails-flyway:0.2.1
       \--- runtime 
  </code></pre>
  
  <p>What means <code>(selected by rule)</code>?</p>
  
  <p><strong>"Solution" - or how to work it around</strong></p>
  
  <p>I was not able to find the rule that causes Gradle to use <code>flyway-core:3.2.1</code> instead of <code>flyway-core:4.0.1</code>. But I found a way to work around the problem.</p>
  
  <p>I added the following to my <code>build.gradle</code> to modify my Gradle <code>runtime</code> resolution strategy.</p>
  
  <pre><code>configurations.runtime.resolutionStrategy {
  
      eachDependency { DependencyResolveDetails det -&gt;
  
          if (det.requested.name == 'flyway-core' &amp;&amp; det.requested.group == 'org.flywaydb') {
              det.useVersion(det.requested.version)
          }
      }
  }
  </code></pre>