repositories {
inherits true // Whether to inherit repository definitions from plugins
mavenRepo "file://${System.getProperty('user.home')}/.m2/repository"
...
}
10 February 2014
One of the great new features in Grails 2.3 is the ability to use Aether to resolve dependencies in place of Ivy. This is great news if
you already use Maven to build other projects, as it now means you can have predictable builds between your Grails and non-http://grails.org[Grails, window="_blank"] applications. However, like
any new feature, there are a few rough edges. I ran into one the other day when trying to determine why one of my Grails applications was not picking up dependencies from the local Maven
cache (~/.m2/repository
). After some digging around, I ran across this bug. According to it, the mavenLocal directive in the
repositories section of BuildConfig.groovy
is not honored when using the Aether resolver. So that stinks. I quickly realized that we could make the Grails dependency resolver
DSL pick up the local Maven repository by simply adding a new file-based repository:
repositories {
inherits true // Whether to inherit repository definitions from plugins
mavenRepo "file://${System.getProperty('user.home')}/.m2/repository"
...
}
This little hack will allow you to continue checking the local Maven repository when using the Grails command line tools and the Maven dependency resolution support
new to Grails 2.3. The nice thing about this is that when/if the issue is fixed so that the local Maven repository is honored, this fix should not cause any issues. Not long after I made this fix,
I went to build the application on Jenkins and notice some more funny business with dependencies. After some digging, I determined the issue was due to the fact that now that the
Grails applications were using Maven for dependency resolution and not Ivy, they were sharing one local dependency cache. When the Jenkins job is a Maven project, I typically choose
the option to create a repository per workspace, to avoid collisions between jobs. With a Grails job, you do not have this option. The option that you do have is setting the
grails.dependency.cache.dir
build property to tell Grails where to cache and look for local dependencies. I decided to conditionally set this based on whether or not the application
was being built on Jenkins or not (the reason for this is that I already have it set in my local ~/.grails/settings.groovy
to have a separate cache per application). Once again,
I modified the BuildConfig.groovy file to contain the following logic:
final String localMavenRepo = System.getenv('JENKINS_HOME') ? "${System.getenv('WORKSPACE')}/.m2/repository" :
"${System.getProperty('user.home')}/.m2/repository"
...
/**
* If the build is being executed on Jenkins, set up the ivy cache. This
* is important as Grails checks to see if this has been set before allowing
* an override of the local Maven repository.
*/
if(System.getenv('JENKINS_HOME')) {
grails.dependency.cache.dir = localMavenRepo
}
grails.project.dependency.resolver = "maven" // or ivy
grails.project.dependency.resolution = {
pom true
// inherit Grails' default dependencies
inherits("global") {
}
log "error" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
checksums false // Whether to verify checksums on resolve
legacyResolve false // whether to do a secondary resolve on plugin installation, not advised and here for backwards compatibility
localRepository = localMavenRepo
repositories {
inherits true // Whether to inherit repository definitions from plugins
mavenRepo "file://${localMavenRepo}"
...
}
}
...
It’s worth noting that in the example above, I not only set the grails.dependency.cache.dir
Grails build property, but
I also set the localRepository
property of the dependency resolution DSL to ensure that the Maven dependency resolution is using it both as a place to check
for dependencies AND a place to store the cached dependencies (see the AetherDependencyManager.groovy source
file in the grails-aether
module for more details). Now when the application builds on Jenkins, not only does it have a local Maven repository as part of
the list of repositories, but that repository is stored in the workspace for the Jenkins build job.