4.7.6 Snapshots and Other Changing Dependencies - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 2.3.8
4.7.6 Snapshots and Other Changing Dependencies
Configuration Changing dependencies
Typically, dependencies are constant. That is, for a given combination ofgroup
, name
and version
the jar (or plugin) that it refers to will never change. The Grails dependency management system uses this fact to cache dependencies in order to avoid having to download them from the source repository each time. Sometimes this is not desirable. For example, many developers use the convention of a snapshot (i.e. a dependency with a version number ending in “-SNAPSHOT”) that can change from time to time while still retaining the same version number. We call this a "changing dependency".Whenever you have a changing dependency, Grails will always check the remote repository for a new version. More specifically, when a changing dependency is encountered during dependency resolution its last modified timestamp in the local cache is compared against the last modified timestamp in the dependency repositories. If the version on the remote server is deemed to be newer than the version in the local cache, the new version will be downloaded and used.Be sure to read the next section on "Dependency Resolution Caching" in addition to this one as it affects changing dependencies.All dependencies (jars and plugins) with a version number ending in
-SNAPSHOT
are implicitly considered to be changing by Grails. You can also explicitly specify that a dependency is changing by setting the changing flag in the dependency DSL (This is only required for Ivy, Aether does not support the 'changing' flag and treats dependencies that end with -SNAPSHOT as changing):runtime ('org.my:lib:1.2.3') {
changing = true
}
Aether and SNAPSHOT dependencies
The semantics for handling snapshots when using Aether in Grails are the same as those when using the Maven build tool. The default snapshot check policy is to check once a day for a new version of the dependency. This means that if a new snapshot is published during the day to a remote repository you may not see that change unless you manually clear out your local snapshot.If you wish to change the snapshot update policy you can do so by configuring anupdatePolicy
for the repository where the snapshot was resolved from, for example:repositories {
mavenCentral {
updatePolicy "interval:1"
}
}
updatePolicy
like the above will seriously impact performance of dependency resolution. The possibly configuration values for updatePolicy
are as follows:
never
- Never check for new snapshotsalways
- Always check for new snapshotsdaily
- Check once a day for new snapshots (the default)interval:x
- Check once every x minutes for new snapshots
Ivy and Changing dependencies
For those used to Maven snapshot handling, if you use Aether dependency management you can expect the same semantics as Maven. If you choose to use Ivy there is a caveat to the support for changing dependencies that you should be aware of. Ivy will stop looking for newer versions of a dependency once it finds a remote repository that has the dependency.Consider the following setup:grails.project.dependency.resolution = { repositories { mavenLocal() mavenRepo "http://my.org/repo" } dependencies { compile "myorg:mylib:1.0-SNAPSHOT" }
- maven local repository is searched, dependency not found
- maven network repository is searched, dependency is downloaded to the cache and used
BuildConfig.groovy
file.If we perform dependency resolution again without the dependency changing on the remote server, the following will happen:
- maven local repository is searched, dependency not found
- maven network repository is searched, dependency is found to be the same "age" as the version in the cache so will not be updated (i.e. downloaded)
mylib 1.0-SNAPSHOT
is published changing the version on the server. The next time we perform dependency resolution, the following will happen:
- maven local repository is searched, dependency not found
- maven network repository is searched, dependency is found to newer than version in the cache so will be updated (i.e. downloaded to the cache)
mylib
library. To do this we build it locally and install it to the local Maven cache (how doesn't particularly matter). The next time we perform a dependency resolution, the following will occur:
- maven local repository is searched, dependency is found to newer than version in the cache so will be updated (i.e. downloaded to the cache)
- maven network repository is NOT searched as we've already found the dependency
mylib 1.0-SNAPSHOT
is published changing the version on the server. The next time we perform dependency resolution, the following will happen:
- maven local repository is searched, dependency is found to be the same "age" as the version in the cache so will not be updated (i.e. downloaded)
- maven network repository is NOT searched as we've already found the dependency
mylib 1.0-SNAPSHOT
in the remote repository), you can either:
- Delete the version from the local maven repository, or
- Reorder the repositories in the
BuildConfig.groovy
file
This changing dependency behaviour is an unmodifiable characteristic of the underlying dependency management system Apache Ivy. It is currently not possible to have Ivy search all repositories to look for newer versions (in terms of modification date) of the same dependency (i.e. the same combination ofgroup
,name
andversion
). If you want this behavior consider switching to Aether as the dependency manager.