Thursday, May 21, 2015

Gradle war overlay

The standard way to extend a war artifact using Maven is to use Maven's Overlay Plugin.

Naturally, Gradle users wanted to adopt the same approach. And there are some solutions, including a gradle overlay plugin.

These all could be used. However, Gradle's powerful dependency management enables you to emulate the overlay plugin ad-hoc, and have a much more precise control on what you want to happen to your war.

Basically, what you need is to include a war as a non-transitive dependency, and copy all its contents to resulting war, preserving the changes you made.

apply plugin: 'war'

repositories {
 mavenCentral()
}

configurations {
 overlay {
  transitive = false
 }
}

dependencies {
 overlay('your:dependency1:version')
 overlay('your:dependency2:version')
}

war {
 duplicatesStrategy = 'exclude'
 
 configurations.overlay.filter({it.name.endsWith(".war")}).each {
  from zipTree(it)
 }
}
Of course, you may want to use other options of gradle war plugin together with this (e.g., include some configuration files into your WEB-INF), you may want to also include some zip dependencies into your resulting war, and exclude some problematic jars from your overlays in case you import a newer version of them.

apply plugin: 'war'

repositories {
 mavenCentral()
}

configurations {
 overlay {
  transitive = false
 }
}

dependencies {
 compile('org.problematic:problematic:newer_version')
 overlay('your:dependency1:version')
 overlay('your:dependency2:version')
}

war {
 duplicatesStrategy = 'exclude'

 webInf {
  from "$projectDir/config"
 }
 
 configurations.overlay.filter({it.name.endsWith(".war") || it.name.endsWith(".zip")}).each {
  from zipTree(it).matching { exclude '**/*problematic*.jar' }
 }
}
In case you want to use the imported war's dependencies at compile time, it is also easy.

apply plugin: 'war'

repositories {
 mavenCentral()
}

configurations {
 overlay
 compile.extendsFrom(overlay)
}

dependencies {
 overlay('your:dependency1:version')
 overlay('your:dependency2:version')
}

war {
 duplicatesStrategy = 'exclude'
 
 configurations.overlay.filter({it.name.endsWith(".war") || it.name.endsWith(".zip")}).each {
  from zipTree(it).matching { exclude '**/*.jar' }
 }
}
TL;DR
Turn off your plugins, RTFM, and

 use the force

of Gradle, Luke.

No comments: