Understanding why Gradle pulls in old 3rd party versions

I’m having a problem with dependency resolution. After upgrading derby and hibernate (which is only used in the :database subproject), gradle is still pulling in old versions, and that is causing issues. Part of the build.gradle:

dependencies {

	implementation "org.apache.derby:derby:${derbyVersion}"
	implementation "org.apache.derby:derbynet:${derbyVersion}"
	implementation "org.apache.derby:derbyclient:${derbyVersion}"
	implementation "org.apache.derby:derbyshared:${derbyVersion}"

	implementation ("org.hibernate:hibernate-core:${hibernateVersion}"){
		exclude group: "javax.el"
	}
	implementation "org.hibernate:hibernate-validator:${hibernateValidatorVersion}"

	implementation project(":api")
	implementation project(":util")
    implementation project(":common")
    implementation project(":foundation")
    testImplementation project(":json")
    testImplementation project(":email")
    testImplementation project(":api").sourceSets.test.output

}

Versions variables are defined as:

derbyVersion = "10.15.1.3"
hibernateValidatorVersion = "6.0.16.Final"
hibernateVersion = "5.4.2.Final"

And the result of gradle dependencies for :database:

|    +--- project :database
|    |    +--- org.apache.derby:derby:10.15.1.3 -> 10.14.2.0
|    |    +--- org.apache.derby:derbynet:10.15.1.3
|    |    |    \--- org.apache.derby:derby:10.15.1.3 -> 10.14.2.0
|    |    +--- org.apache.derby:derbyclient:10.15.1.3
|    |    +--- org.apache.derby:derbyshared:10.15.1.3
|    |    +--- org.hibernate:hibernate-core:5.4.2.Final -> 5.3.9.Final (*)
|    |    +--- org.hibernate:hibernate-validator:6.0.16.Final
|    |    |    \--- org.hibernate.validator:hibernate-validator:6.0.16.Final (*)
|    |    +--- project :api (*)
|    |    +--- project :util (*)
|    |    +--- project :common (*)
|    |    \--- project :foundation (*)

How can I find out the reason for 10.15.1.3 -> 10.14.2.0? The :database subproject is only a few classes, and nowhere else in the system is derby or hibernate used. If there were another transitive dependency relying on derby 10.14.x, I would expect that to be in the tree (as it is if I do the same with maven).

More info: using dependencyInsight, I got the following output, but “selected by rule” doesn’t explain why it picked 10.14.2.0. The subprojects :usersession and server only have a dependency on the :database subproject, not derby or hibernate itself.

gradle dependencyInsight --configuration compile --dependency derby

> Task :dependencyInsight
org.apache.derby:derby:10.14.2.0 (selected by rule)
   variant "runtime" [
      org.gradle.status   = release (not requested)
      org.gradle.usage    = java-runtime (not requested)
      org.gradle.category = library (not requested)
   ]

org.apache.derby:derby:10.15.1.3 -> 10.14.2.0
+--- project :database
|    +--- project :server
|    |    +--- compile
|    |    +--- project :app
|    |    |    \--- compile
|    |    +--- project :client
|    |    |    +--- compile
|    |    |    \--- project :app (*)
|    |    +--- project :headline
|    |    |    \--- project :client (*)
|    |    \--- project :pdf_puzzles
|    |         \--- project :client (*)
|    \--- project :usersession
|         \--- project :server (*)
\--- org.apache.derby:derbynet:10.15.1.3
     \--- project :database (*)

In another thread, it was suggested to run with -i flag, for more logging. The rule indicated by “selected by rule” might be from a plugin that is applied in your script. Check the additional logs to find which plugin it is and see if you can change it’s configuration.

Anyway, you can also try just using dependency substitution for the relevant dependency.