NFJS Software Symposium Series 2011
Ken Sipe - CTO, Gradleware
Enter The Gradle
Enter the Gradle
About Speaker
Developer: Embedded, C++, Java, Groovy, Grails, C#, Objective C
Speaker: JavaOne 2009 Rock Star, NFJS, JAX
Microsoft MCP
Sun Certified Java 2 Architect
Master of Scrums
Agile Coach
Instructor: VisiBroker CORBA
Rational Rose, OOAD
http://kensipe.blogspot.com/
http://del.icio.us/kensipe
twitter: @kensipe
ken.sipe@gradleware.com
Enter the Gradle
Java Build Tools
javac
IDE
ANT
Maven
ANT + Ivy
Gradle
Enter the Gradle
Desired Functionality of a Build System
n Dependency management
n Versioning
n Compile Java code, build jars
¨ + Other JVM Languages
n Execute tests and report results, fail build on failed tests
n Run quality-check tools (PMD, Findbugs, Checkstyles)
n File generation (XmlBeans, Xsl, Velocity, AspectJ)
n Property expansion / token substitution
n Build vs. deploy vs. release
n Full control when needed
n Cross-platform
n IDE Support
n Documentation / Support
Enter the Gradle
ANT
nCross Platform Builds
nIDE Independent
nXML “script” files
¨build.xml
Enter the Gradle
Maven
nDefined Lifecycle
nConvention for Project Structure
nPlugins
nDependency Management
nXML based
¨pom.xml
Enter the Gradle
ANT + Ivy
nBuild steps defined and executed with Ant
nDependencies managed with Ivy
nAnt targets to install, retrieve artifacts from
Ivy repository
Enter the Gradle
Ant and Maven Short Comings
nhard to implement an algorithm in the build file;
¨simple if or for constructs are hard to achieve, and
very unnatural
nhard to go beyond the foresight of the Ant/
Maven developers
n"build by convention" is not supported (Ant), or
ties your hands because the configuration is
hard (Maven),
nsupport for multi-module builds is limited
nboilerplate of XML is annoying
Enter the Gradle
What is Gradle?
nBuilt on top of Ant + Ivy
nBuild DSL written in Groovy
nUses Groovy AntBuilder
¨ant.compile, ant.jar
nPlugins define common tasks to build
different types of projects
¨java, groovy, war, …
Enter the Gradle
What is Gradle?
Gradle is Declarative
Specify what...
...not how
Enter the Gradle
What is Gradle?
Gradle is Declarative
... without being Rigid
Enter the Gradle
Example Scenarios
nMany source dirs per project
nDependencies per source dir
nJDK per source dir
nMany artifacts per project
Enter the Gradle
Getting Started
http://gradle.org/
~$ gradle -t
:reportTask
------------------------------------------------------------
Root Project
------------------------------------------------------------
No tasks
BUILD SUCCESSFUL
Enter the Gradle
Simple Build File
file:build.gradle
apply plugin: 'java'
~/projects/playground/gradle-nfjs$ gradle -t
:reportTask
------------------------------------------------------------
Root Project
------------------------------------------------------------
:assemble - Builds all Jar, War, Zip, and Tar archives.
-> :jar
:build - Assembles and tests this project.
-> :assemble, :check
:buildDependents - Assembles and tests this project and all projects that depend on it.
-> :build
:buildNeeded - Assembles and tests this project and all projects it depends on.
-> :build
:check - Runs all checks.
-> :test
:classes - Assembles the main classes.
-> :compileJava, :processResources
:clean - Deletes the build directory.
:compileJava - Compiles the main Java source.
:compileTestJava - Compiles the test Java source.
-> :classes
:jar - Generates a jar archive with all the compiled classes.
Gradle
Create a task
createTask('hello') { // depreciated
println 'Hello World'
}
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {  
println "I'm Gradle" 
} 
project.tasks.add('someTask').doFirst {
// do something
}
Gradle
DSL Syntax And Tasks
task hello << { println 'Hello' }
// direct API access is fine for single statements
hello.dependsOn otherTask
// for multiple access we prefer closure syntax
hello {
onlyIf { day == 'monday' }
dependsOn otherTask
}
// combining Configuration and Actions
task hello {
onlyIf {
day == 'monday'
}
doFirst {println 'Hello'}
}
Enter the Gradle
Sample Simple Build File
apply plugin:'war'
version = 0.1
repositories {
mavenCentral()
}
dependencies {
compile "commons-lang:commons-lang:2.4"
}
Enter the Gradle
Defaults
apply plugin:'war'
version = 0.1
defaultTasks ‘clean’, ‘build’
repositories {
mavenCentral()
}
dependencies {
compile "commons-lang:commons-lang:2.4"
}
Enter the Gradle
Beyond the Basics
19
Enter the Gradle
Does it really matter if your build
system uses XML or Groovy?
Can there be aspects of the
build that are difficult from a
declarative perspective?
Enter the Gradle
Non Declarative Examples
version = "1.0-${new Date().format('yyyyMMdd')}"
task sources {
! sourceSets.test.allGroovy
! ! .matching {include '**/*Demo*.groovy' }
! ! .files.each {
! ! ! println “$it.absolutePath”
! }
}
Enter the Gradle
Extensible Object Model
tasks.withType(Jar).allObjects { jarTask ->
! jarTask.osgi = new DefaultOsgiManifest()
! jarTask.doFirst { task ->
! ! importOsgiManifestIntoManifest(task) }
}
Enter the Gradle
Rich and Extensible API
tasks.withType(Jar).allObjects { jarTask ->
jarTask.manifest.mainAttributes(Provider: "CodeMentor Inc.")
}
tasks.withType(Compile).allObjects { compile ->
compile.options.fork.executable = “$pathToJavac”
}
dependencies.allObjects { dependency ->
throwExceptionIfDependencyIsGPL(dependency)
}
Enter the Gradle
Task Rules
tasks.addRule("Pattern: ping<ID>") { String taskName ->
if (taskName.startsWith("ping")) {
task(taskName) << { // add task
println "Pinging: " + (taskName - 'ping')
}
}
}
task groupPing(dependsOn: [pingServer1, pingServer2])
~/projects/playground$ gradle gP
:pingServer1
Pinging: Server1
:pingServer2
Pinging: Server2
:groupPing
Enter the Gradle
Gradle Lifecycle
25
Enter the Gradle
Build Phases
nInitialization
¨supports single and multi-project builds
¨creates project instances for all that are taking
part in the build
nConfiguration
¨DAG (dependency acyclic graph) of tasks is
created
nExecution
Enter the Gradle
setting.gradle file
nexecuted during initialization phase
nrequired for multi-project builds
¨in root project
ndefines participating projects for builds
noptional for single-project build
Enter the Gradle
Order of Execution
settings.gradle
println ‘executed during the init phase’
build.gradle
println ‘executed during the config phase’
task test << {
println ‘executed during the execution phase’
}
Enter the Gradle
Jump Between Phases
task release(dependsOn: assemble) << {
println 'We release now'
}
build.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(':release')) {
version = '1.0'
} else {
version = '1.0-SNAPSHOT'
}
}
Enter the Gradle
Gradle Dependencies
30
Enter the Gradle
Runtime Dependencies
dependencies {
runtime group: 'org.springframework', name: 'spring-core', version: '2.5'
runtime 'org.springframework:spring-core:2.5', 'org.springframework:spring-aop:2.5
}
Enter the Gradle
Separate Compiles from Tests
dependencies {
compile 'org.springframework:spring-webmvc:3.0.0.RELEASE'
testCompile 'org.springframework:spring-test:3.0.0.RELEASE'
testCompile 'junit:junit:4.7'
}
Enter the Gradle
Transitive
configurations.compile.transitive = true
dependencies {
compile 'org.springframework:spring-webmvc:3.0.0.RC2'
testCompile 'org.springframework:spring-test:3.0.0.RC2'
testCompile 'junit:junit:4.7'
}
Options 1: Everything
runtime('org.hibernate:hibernate:3.0.5') {
transitive = true
}
runtime group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true
runtime(group: 'org.hibernate', name: 'hibernate', version: '3.0.5') {
transitive = true
}
Options 2: Selective
Enter the Gradle
File Dependencies
dependencies {
runtime files('libs/a.jar', 'libs/b.jar') runtime
fileTree(dir: 'libs', includes: ['*.jar'])
}
Enter the Gradle
Giving Names to Dependencies
List groovy = ["org.codehaus.groovy:groovy-all:1.5.4@jar",
"commons-cli:commons-cli:1.0@jar",
"org.apache.ant:ant:1.7.0@jar"]
List hibernate = ['org.hibernate:hibernate:3.0.5@jar',
'somegroup:someorg:1.0@jar']
dependencies {
runtime groovy, hibernate
}
Enter the Gradle
Maven Repos
repositories {
mavenCentral()
}
Or
repositories {
mavenCentral name: 'single-jar-repo',
urls: "http://repo.mycompany.com/jars"
mavenCentral name: 'multi-jar-repos',
urls: ["http://repo.mycompany.com/jars1", "http://repo.mycompany.com/jars1"]
}
repositories {
mavenRepo urls: "http://repo.mycompany.com/maven2"
}
Or
Enter the Gradle
Flat File Repo
repositories {
flatDir name: 'localRepository',
dirs: 'lib' flatDir dirs: ['lib1', 'lib2']
}
Enter the Gradle
Custom Gradle
custom tasks and plugins
38
Enter the Gradle
Custom Task
task hello(type: HelloTask)
task greeting(type: HelloTask) {
greeting = 'greetings from new Task'
}
class HelloTask extends DefaultTask {
def greeting = 'hello from HelloTask'
@org.gradle.api.tasks.TaskAction
def printGreeting() {
println greeting
}
}
Gradle
Plugins
nPlugins == Build Scripts
nTwo Flavors:
¨ Another build script (local or remote) (Script
Plugin)
¨ A class implementing org.gradle.api.Plugin
(Binary Plugin)
Gradle
Applying Plugins
n Any gradle script can be a plugin.
n Binary plugins must be in the build script classpath
¨can have id's (meta properties in the jar).
¨will learn later how to add elements to the build script
classpath.
¨The build-in plugins are by default in the build script classpath.
apply from: 'otherScript.gradle'
apply from: 'http://mycomp.com/otherScript.gradle'
apply plugin: org.gradle.api.plugins.JavaPlugin
apply plugin: 'java'
Gradle
Standard Gradle Plugins
Plugin-Id applies
base
java-base base
groovy-base java-base
groovy groovy-base
scala-base java-base
scala scala-base
war java
osgi
code-quality
maven
eclipse
Enter the Gradle
Jetty Plugin Demo
with CamelCase
43
Enter the Gradle
Custom Plugin
apply plugin: (GreetingPlugin)
class GreetingPlugin implements Plugin {
def void use(Project project, ProjectPluginsContainer projectPluginsHandler) {
project.task('hello') << {
println "Hello from the greetingPlugin"
}
}
}
** All projects using this plugin will now
have the ‘hello’ task added and all its functionality
Enter the Gradle
Common Interests
45
Gradle
Jar
n Jars can be added to the buildscript classpath
¨Custom build logic
¨Plugins
¨Helper classes (e.g. commons-math)
buildscript {
repositories { mavenCentral() }
dependencies {
classpath "commons-lang:commons-lang:3.1"
classpath files('lib/foo.jar')
}
}
Enter the Gradle
Explode the WAR
war.doLast {
ant.unzip(src: war.archivePath,
dest: "$buildDir/exploded")
}
Enter the Gradle
Integration with ANT
<project> <target name="hello" depends="intro">
<echo>Hello, from Ant</echo> </target>
</project>
build.xml
ant.importBuild 'build.xml'
hello.doFirst { println 'Here comes Ant' }
task intro << { println 'Hello, from Gradle'}
build.gradle
~/projects/playground/gradle/ant$ gradle hello
:intro
Hello, from Gradle
:hello
Here comes Ant
[ant:echo] Hello, from Ant
output:
Enter the Gradle
Integration with Maven
nIntegration with Maven repositories
¨autogeneration of pom.xml
¨install to local Maven repo
¨deploy to any remote Repo
¨full maven metadata generation
nIntegration of Maven builds in the future
Enter the Gradle
Running Processes from Gradle
ant.java(classname: 'com.my.classname', fork: true,
classpath: "${sourceSets.main.runtimeClasspath.asPath}")
Enter the Gradle
Cobertura (1/2)
apply plugin:'java'
def cobSerFile="${project.buildDir}/cobertura.ser"
def srcOriginal="${sourceSets.main.classesDir}"
def srcCopy="${srcOriginal}-copy"
repositories {
mavenCentral()
}
dependencies {
testRuntime 'net.sourceforge.cobertura:cobertura:1.9.3'
testCompile 'junit:junit:4.5'
}
test.doFirst {
ant {
delete(file:cobSerFile, failonerror:false)
delete(dir: srcCopy, failonerror:false)
taskdef(resource:'tasks.properties', classpath: configurations.testRuntime.asPath)
copy(todir: srcCopy) {
fileset(dir: srcOriginal)
}
'cobertura-instrument'(datafile:cobSerFile) {
fileset(dir: srcOriginal,
includes:"my/classes/**/*.class",
excludes:"**/*Test.class")
}
}
}
Enter the Gradle
Cobertura (2/2)
test {
// pass information on cobertura datafile to your testing framework
// see information below this code snippet
}
test.doLast {
if (new File(srcCopy).exists()) {
// replace instrumented classes with backup copy again
ant {
delete(file: srcOriginal)
move(file: srcCopy,
tofile: srcOriginal)
}
// create cobertura reports
ant.'cobertura-report'(destdir:"${project.buildDirName}/test-results",
format:'html', srcdir:"src/main/java", datafile:cobSerFile)
}
}
Enter the Gradle
Special Environments
// File: build.gradle
loadConfiguration()
task printProps << {
println "serverName: $config.serverName"
println "mail.server: $config.mail.server"
println "mail.port: $config.mail.port"
}
def loadConfiguration() {
def environment = hasProperty('env') ? env : 'dev'
setProperty 'environment', environment
println "Environment is set to $environment"
def configFile = file('config.groovy')
def config = new ConfigSlurper(environment).parse(configFile.toURL())
setProperty 'config', config
}
// File: config.groovy
mail {
server = 'localhost'
port = 25
}
environments {
dev {
serverName = 'http://localhost:9090'
}
test {
serverName = 'http://testserver'
mail {
server = 'mail.testserver'
}
}
prod {
serverName = 'http://www.nfjs.com'
mail {
port = 552
server = 'mail.host.com'
}
}
}
thanks to mrhaki for the tip!
~/projects/playground/gradle/env$ gradle -q -Penv=test pP
Environment is set to test
serverName: http://testserver
mail.server: mail.testserver
mail.port: 25
Enter the Gradle
wrapper
task wrapper(type: Wrapper) {
gradleVersion = '0.8'
}
build
build.gradle
gradle-wrapper.jar
gradle-wrapper.properties
gradlew.bat
gradlew
task execution results:
Enter the Gradle
•Gradle is version 1.0-Milestone2a!
but
•It is very powerful!
Summary
Enter the Gradle
n Closing and Q&A
¨Please fill out the session evaluation
¨Ken Sipe
n ken.sipe@gradleware.com
n kensipe.blogspot.com
n twitter: @kensipe
Summary

Enter the gradle

  • 1.
    NFJS Software SymposiumSeries 2011 Ken Sipe - CTO, Gradleware Enter The Gradle
  • 2.
    Enter the Gradle AboutSpeaker Developer: Embedded, C++, Java, Groovy, Grails, C#, Objective C Speaker: JavaOne 2009 Rock Star, NFJS, JAX Microsoft MCP Sun Certified Java 2 Architect Master of Scrums Agile Coach Instructor: VisiBroker CORBA Rational Rose, OOAD http://kensipe.blogspot.com/ http://del.icio.us/kensipe twitter: @kensipe ken.sipe@gradleware.com
  • 3.
    Enter the Gradle JavaBuild Tools javac IDE ANT Maven ANT + Ivy Gradle
  • 4.
    Enter the Gradle DesiredFunctionality of a Build System n Dependency management n Versioning n Compile Java code, build jars ¨ + Other JVM Languages n Execute tests and report results, fail build on failed tests n Run quality-check tools (PMD, Findbugs, Checkstyles) n File generation (XmlBeans, Xsl, Velocity, AspectJ) n Property expansion / token substitution n Build vs. deploy vs. release n Full control when needed n Cross-platform n IDE Support n Documentation / Support
  • 5.
    Enter the Gradle ANT nCrossPlatform Builds nIDE Independent nXML “script” files ¨build.xml
  • 6.
    Enter the Gradle Maven nDefinedLifecycle nConvention for Project Structure nPlugins nDependency Management nXML based ¨pom.xml
  • 7.
    Enter the Gradle ANT+ Ivy nBuild steps defined and executed with Ant nDependencies managed with Ivy nAnt targets to install, retrieve artifacts from Ivy repository
  • 8.
    Enter the Gradle Antand Maven Short Comings nhard to implement an algorithm in the build file; ¨simple if or for constructs are hard to achieve, and very unnatural nhard to go beyond the foresight of the Ant/ Maven developers n"build by convention" is not supported (Ant), or ties your hands because the configuration is hard (Maven), nsupport for multi-module builds is limited nboilerplate of XML is annoying
  • 9.
    Enter the Gradle Whatis Gradle? nBuilt on top of Ant + Ivy nBuild DSL written in Groovy nUses Groovy AntBuilder ¨ant.compile, ant.jar nPlugins define common tasks to build different types of projects ¨java, groovy, war, …
  • 10.
    Enter the Gradle Whatis Gradle? Gradle is Declarative Specify what... ...not how
  • 11.
    Enter the Gradle Whatis Gradle? Gradle is Declarative ... without being Rigid
  • 12.
    Enter the Gradle ExampleScenarios nMany source dirs per project nDependencies per source dir nJDK per source dir nMany artifacts per project
  • 13.
    Enter the Gradle GettingStarted http://gradle.org/ ~$ gradle -t :reportTask ------------------------------------------------------------ Root Project ------------------------------------------------------------ No tasks BUILD SUCCESSFUL
  • 14.
    Enter the Gradle SimpleBuild File file:build.gradle apply plugin: 'java' ~/projects/playground/gradle-nfjs$ gradle -t :reportTask ------------------------------------------------------------ Root Project ------------------------------------------------------------ :assemble - Builds all Jar, War, Zip, and Tar archives. -> :jar :build - Assembles and tests this project. -> :assemble, :check :buildDependents - Assembles and tests this project and all projects that depend on it. -> :build :buildNeeded - Assembles and tests this project and all projects it depends on. -> :build :check - Runs all checks. -> :test :classes - Assembles the main classes. -> :compileJava, :processResources :clean - Deletes the build directory. :compileJava - Compiles the main Java source. :compileTestJava - Compiles the test Java source. -> :classes :jar - Generates a jar archive with all the compiled classes.
  • 15.
    Gradle Create a task createTask('hello'){ // depreciated println 'Hello World' } task hello << { println 'Hello world!' } task intro(dependsOn: hello) << {   println "I'm Gradle"  }  project.tasks.add('someTask').doFirst { // do something }
  • 16.
    Gradle DSL Syntax AndTasks task hello << { println 'Hello' } // direct API access is fine for single statements hello.dependsOn otherTask // for multiple access we prefer closure syntax hello { onlyIf { day == 'monday' } dependsOn otherTask } // combining Configuration and Actions task hello { onlyIf { day == 'monday' } doFirst {println 'Hello'} }
  • 17.
    Enter the Gradle SampleSimple Build File apply plugin:'war' version = 0.1 repositories { mavenCentral() } dependencies { compile "commons-lang:commons-lang:2.4" }
  • 18.
    Enter the Gradle Defaults applyplugin:'war' version = 0.1 defaultTasks ‘clean’, ‘build’ repositories { mavenCentral() } dependencies { compile "commons-lang:commons-lang:2.4" }
  • 19.
  • 20.
    Enter the Gradle Doesit really matter if your build system uses XML or Groovy? Can there be aspects of the build that are difficult from a declarative perspective?
  • 21.
    Enter the Gradle NonDeclarative Examples version = "1.0-${new Date().format('yyyyMMdd')}" task sources { ! sourceSets.test.allGroovy ! ! .matching {include '**/*Demo*.groovy' } ! ! .files.each { ! ! ! println “$it.absolutePath” ! } }
  • 22.
    Enter the Gradle ExtensibleObject Model tasks.withType(Jar).allObjects { jarTask -> ! jarTask.osgi = new DefaultOsgiManifest() ! jarTask.doFirst { task -> ! ! importOsgiManifestIntoManifest(task) } }
  • 23.
    Enter the Gradle Richand Extensible API tasks.withType(Jar).allObjects { jarTask -> jarTask.manifest.mainAttributes(Provider: "CodeMentor Inc.") } tasks.withType(Compile).allObjects { compile -> compile.options.fork.executable = “$pathToJavac” } dependencies.allObjects { dependency -> throwExceptionIfDependencyIsGPL(dependency) }
  • 24.
    Enter the Gradle TaskRules tasks.addRule("Pattern: ping<ID>") { String taskName -> if (taskName.startsWith("ping")) { task(taskName) << { // add task println "Pinging: " + (taskName - 'ping') } } } task groupPing(dependsOn: [pingServer1, pingServer2]) ~/projects/playground$ gradle gP :pingServer1 Pinging: Server1 :pingServer2 Pinging: Server2 :groupPing
  • 25.
  • 26.
    Enter the Gradle BuildPhases nInitialization ¨supports single and multi-project builds ¨creates project instances for all that are taking part in the build nConfiguration ¨DAG (dependency acyclic graph) of tasks is created nExecution
  • 27.
    Enter the Gradle setting.gradlefile nexecuted during initialization phase nrequired for multi-project builds ¨in root project ndefines participating projects for builds noptional for single-project build
  • 28.
    Enter the Gradle Orderof Execution settings.gradle println ‘executed during the init phase’ build.gradle println ‘executed during the config phase’ task test << { println ‘executed during the execution phase’ }
  • 29.
    Enter the Gradle JumpBetween Phases task release(dependsOn: assemble) << { println 'We release now' } build.taskGraph.whenReady { taskGraph -> if (taskGraph.hasTask(':release')) { version = '1.0' } else { version = '1.0-SNAPSHOT' } }
  • 30.
    Enter the Gradle GradleDependencies 30
  • 31.
    Enter the Gradle RuntimeDependencies dependencies { runtime group: 'org.springframework', name: 'spring-core', version: '2.5' runtime 'org.springframework:spring-core:2.5', 'org.springframework:spring-aop:2.5 }
  • 32.
    Enter the Gradle SeparateCompiles from Tests dependencies { compile 'org.springframework:spring-webmvc:3.0.0.RELEASE' testCompile 'org.springframework:spring-test:3.0.0.RELEASE' testCompile 'junit:junit:4.7' }
  • 33.
    Enter the Gradle Transitive configurations.compile.transitive= true dependencies { compile 'org.springframework:spring-webmvc:3.0.0.RC2' testCompile 'org.springframework:spring-test:3.0.0.RC2' testCompile 'junit:junit:4.7' } Options 1: Everything runtime('org.hibernate:hibernate:3.0.5') { transitive = true } runtime group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true runtime(group: 'org.hibernate', name: 'hibernate', version: '3.0.5') { transitive = true } Options 2: Selective
  • 34.
    Enter the Gradle FileDependencies dependencies { runtime files('libs/a.jar', 'libs/b.jar') runtime fileTree(dir: 'libs', includes: ['*.jar']) }
  • 35.
    Enter the Gradle GivingNames to Dependencies List groovy = ["org.codehaus.groovy:groovy-all:1.5.4@jar", "commons-cli:commons-cli:1.0@jar", "org.apache.ant:ant:1.7.0@jar"] List hibernate = ['org.hibernate:hibernate:3.0.5@jar', 'somegroup:someorg:1.0@jar'] dependencies { runtime groovy, hibernate }
  • 36.
    Enter the Gradle MavenRepos repositories { mavenCentral() } Or repositories { mavenCentral name: 'single-jar-repo', urls: "http://repo.mycompany.com/jars" mavenCentral name: 'multi-jar-repos', urls: ["http://repo.mycompany.com/jars1", "http://repo.mycompany.com/jars1"] } repositories { mavenRepo urls: "http://repo.mycompany.com/maven2" } Or
  • 37.
    Enter the Gradle FlatFile Repo repositories { flatDir name: 'localRepository', dirs: 'lib' flatDir dirs: ['lib1', 'lib2'] }
  • 38.
    Enter the Gradle CustomGradle custom tasks and plugins 38
  • 39.
    Enter the Gradle CustomTask task hello(type: HelloTask) task greeting(type: HelloTask) { greeting = 'greetings from new Task' } class HelloTask extends DefaultTask { def greeting = 'hello from HelloTask' @org.gradle.api.tasks.TaskAction def printGreeting() { println greeting } }
  • 40.
    Gradle Plugins nPlugins == BuildScripts nTwo Flavors: ¨ Another build script (local or remote) (Script Plugin) ¨ A class implementing org.gradle.api.Plugin (Binary Plugin)
  • 41.
    Gradle Applying Plugins n Anygradle script can be a plugin. n Binary plugins must be in the build script classpath ¨can have id's (meta properties in the jar). ¨will learn later how to add elements to the build script classpath. ¨The build-in plugins are by default in the build script classpath. apply from: 'otherScript.gradle' apply from: 'http://mycomp.com/otherScript.gradle' apply plugin: org.gradle.api.plugins.JavaPlugin apply plugin: 'java'
  • 42.
    Gradle Standard Gradle Plugins Plugin-Idapplies base java-base base groovy-base java-base groovy groovy-base scala-base java-base scala scala-base war java osgi code-quality maven eclipse
  • 43.
    Enter the Gradle JettyPlugin Demo with CamelCase 43
  • 44.
    Enter the Gradle CustomPlugin apply plugin: (GreetingPlugin) class GreetingPlugin implements Plugin { def void use(Project project, ProjectPluginsContainer projectPluginsHandler) { project.task('hello') << { println "Hello from the greetingPlugin" } } } ** All projects using this plugin will now have the ‘hello’ task added and all its functionality
  • 45.
  • 46.
    Gradle Jar n Jars canbe added to the buildscript classpath ¨Custom build logic ¨Plugins ¨Helper classes (e.g. commons-math) buildscript { repositories { mavenCentral() } dependencies { classpath "commons-lang:commons-lang:3.1" classpath files('lib/foo.jar') } }
  • 47.
    Enter the Gradle Explodethe WAR war.doLast { ant.unzip(src: war.archivePath, dest: "$buildDir/exploded") }
  • 48.
    Enter the Gradle Integrationwith ANT <project> <target name="hello" depends="intro"> <echo>Hello, from Ant</echo> </target> </project> build.xml ant.importBuild 'build.xml' hello.doFirst { println 'Here comes Ant' } task intro << { println 'Hello, from Gradle'} build.gradle ~/projects/playground/gradle/ant$ gradle hello :intro Hello, from Gradle :hello Here comes Ant [ant:echo] Hello, from Ant output:
  • 49.
    Enter the Gradle Integrationwith Maven nIntegration with Maven repositories ¨autogeneration of pom.xml ¨install to local Maven repo ¨deploy to any remote Repo ¨full maven metadata generation nIntegration of Maven builds in the future
  • 50.
    Enter the Gradle RunningProcesses from Gradle ant.java(classname: 'com.my.classname', fork: true, classpath: "${sourceSets.main.runtimeClasspath.asPath}")
  • 51.
    Enter the Gradle Cobertura(1/2) apply plugin:'java' def cobSerFile="${project.buildDir}/cobertura.ser" def srcOriginal="${sourceSets.main.classesDir}" def srcCopy="${srcOriginal}-copy" repositories { mavenCentral() } dependencies { testRuntime 'net.sourceforge.cobertura:cobertura:1.9.3' testCompile 'junit:junit:4.5' } test.doFirst { ant { delete(file:cobSerFile, failonerror:false) delete(dir: srcCopy, failonerror:false) taskdef(resource:'tasks.properties', classpath: configurations.testRuntime.asPath) copy(todir: srcCopy) { fileset(dir: srcOriginal) } 'cobertura-instrument'(datafile:cobSerFile) { fileset(dir: srcOriginal, includes:"my/classes/**/*.class", excludes:"**/*Test.class") } } }
  • 52.
    Enter the Gradle Cobertura(2/2) test { // pass information on cobertura datafile to your testing framework // see information below this code snippet } test.doLast { if (new File(srcCopy).exists()) { // replace instrumented classes with backup copy again ant { delete(file: srcOriginal) move(file: srcCopy, tofile: srcOriginal) } // create cobertura reports ant.'cobertura-report'(destdir:"${project.buildDirName}/test-results", format:'html', srcdir:"src/main/java", datafile:cobSerFile) } }
  • 53.
    Enter the Gradle SpecialEnvironments // File: build.gradle loadConfiguration() task printProps << { println "serverName: $config.serverName" println "mail.server: $config.mail.server" println "mail.port: $config.mail.port" } def loadConfiguration() { def environment = hasProperty('env') ? env : 'dev' setProperty 'environment', environment println "Environment is set to $environment" def configFile = file('config.groovy') def config = new ConfigSlurper(environment).parse(configFile.toURL()) setProperty 'config', config } // File: config.groovy mail { server = 'localhost' port = 25 } environments { dev { serverName = 'http://localhost:9090' } test { serverName = 'http://testserver' mail { server = 'mail.testserver' } } prod { serverName = 'http://www.nfjs.com' mail { port = 552 server = 'mail.host.com' } } } thanks to mrhaki for the tip! ~/projects/playground/gradle/env$ gradle -q -Penv=test pP Environment is set to test serverName: http://testserver mail.server: mail.testserver mail.port: 25
  • 54.
    Enter the Gradle wrapper taskwrapper(type: Wrapper) { gradleVersion = '0.8' } build build.gradle gradle-wrapper.jar gradle-wrapper.properties gradlew.bat gradlew task execution results:
  • 55.
    Enter the Gradle •Gradleis version 1.0-Milestone2a! but •It is very powerful! Summary
  • 56.
    Enter the Gradle nClosing and Q&A ¨Please fill out the session evaluation ¨Ken Sipe n ken.sipe@gradleware.com n kensipe.blogspot.com n twitter: @kensipe Summary