SlideShare a Scribd company logo
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

More Related Content

PDF
Idiomatic Gradle Plugin Writing - GradleSummit 2016
PDF
Gradle in 45min - JBCN2-16 version
PDF
Gradle build tool that rocks with DSL JavaOne India 4th May 2012
PPTX
Js tacktalk team dev js testing performance
PDF
Using the Groovy Ecosystem for Rapid JVM Development
PDF
CodeWay 2019 - Gandalf: Bad code shall not pass
PPTX
Android presentation - Gradle ++
ODP
Gradle: The Build System you have been waiting for!
Idiomatic Gradle Plugin Writing - GradleSummit 2016
Gradle in 45min - JBCN2-16 version
Gradle build tool that rocks with DSL JavaOne India 4th May 2012
Js tacktalk team dev js testing performance
Using the Groovy Ecosystem for Rapid JVM Development
CodeWay 2019 - Gandalf: Bad code shall not pass
Android presentation - Gradle ++
Gradle: The Build System you have been waiting for!

What's hot (20)

KEY
うさぎ組 in G* WorkShop -うさみみの日常-
PPTX
Exploring the power of Gradle in android studio - Basics & Beyond
PDF
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
PDF
Gradle For Beginners (Serbian Developer Conference 2013 english)
PPT
Padroes Projeto
PDF
Gradle by Example
PDF
Anatomy of a Gradle plugin
PDF
Architecting your GWT applications with GWT-Platform - Lesson 02
PDF
react.pdf
PDF
Scala, Functional Programming and Team Productivity
PDF
0900 learning-react
PDF
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
PDF
Hyper-pragmatic Pure FP testing with distage-testkit
PPTX
The essential tools for test code quality improvement latest
PDF
ScalaUA - distage: Staged Dependency Injection
PPTX
The Gradle in Ratpack: Dissected
PDF
Izumi 1.0: Your Next Scala Stack
PPTX
Kotlin で android アプリを作ってみた
PDF
Build microservice with gRPC in golang
PDF
JavaFX8 TestFX - CDI
うさぎ組 in G* WorkShop -うさみみの日常-
Exploring the power of Gradle in android studio - Basics & Beyond
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Gradle For Beginners (Serbian Developer Conference 2013 english)
Padroes Projeto
Gradle by Example
Anatomy of a Gradle plugin
Architecting your GWT applications with GWT-Platform - Lesson 02
react.pdf
Scala, Functional Programming and Team Productivity
0900 learning-react
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
Hyper-pragmatic Pure FP testing with distage-testkit
The essential tools for test code quality improvement latest
ScalaUA - distage: Staged Dependency Injection
The Gradle in Ratpack: Dissected
Izumi 1.0: Your Next Scala Stack
Kotlin で android アプリを作ってみた
Build microservice with gRPC in golang
JavaFX8 TestFX - CDI
Ad

Viewers also liked (6)

PDF
Javaone 2013 moscow gradle
PDF
Google советы успешного поиска
PDF
Стратегии выполнения тестов в Gradle
PDF
Bash scripting
PDF
Linux commands
PDF
Gradle
Javaone 2013 moscow gradle
Google советы успешного поиска
Стратегии выполнения тестов в Gradle
Bash scripting
Linux commands
Gradle
Ad

Similar to Enter the gradle (20)

PDF
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
PDF
Gradle - time for a new build
PDF
Level Up Your Android Build -Droidcon Berlin 2015
PDF
Why Gradle?
PDF
Gradle in 45min
PDF
OpenCms Days 2012 - Developing OpenCms with Gradle
PDF
Improving your Gradle builds
PPTX
Faster Java EE Builds with Gradle
PPTX
Faster Java EE Builds with Gradle
PDF
In the Brain of Hans Dockter: Gradle
PDF
GR8Conf 2009: Industrial Strength Groovy by Paul King
PDF
Why gradle
PDF
Gradle - the Enterprise Automation Tool
ODP
Gradle - time for another build
PDF
Hands on the Gradle
PDF
HTML5 for the Silverlight Guy
PDF
Grails 101
PDF
Gradle(the innovation continues)
PPT
Gradle: The Build system you have been waiting for
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Gradle - time for a new build
Level Up Your Android Build -Droidcon Berlin 2015
Why Gradle?
Gradle in 45min
OpenCms Days 2012 - Developing OpenCms with Gradle
Improving your Gradle builds
Faster Java EE Builds with Gradle
Faster Java EE Builds with Gradle
In the Brain of Hans Dockter: Gradle
GR8Conf 2009: Industrial Strength Groovy by Paul King
Why gradle
Gradle - the Enterprise Automation Tool
Gradle - time for another build
Hands on the Gradle
HTML5 for the Silverlight Guy
Grails 101
Gradle(the innovation continues)
Gradle: The Build system you have been waiting for

Recently uploaded (20)

PDF
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
PDF
GENETICS IN BIOLOGY IN SECONDARY LEVEL FORM 3
PPTX
GDM (1) (1).pptx small presentation for students
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PDF
Module 4: Burden of Disease Tutorial Slides S2 2025
PPTX
Cell Types and Its function , kingdom of life
PDF
STATICS OF THE RIGID BODIES Hibbelers.pdf
PDF
Weekly quiz Compilation Jan -July 25.pdf
PDF
Computing-Curriculum for Schools in Ghana
PDF
Complications of Minimal Access Surgery at WLH
PDF
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
PPTX
202450812 BayCHI UCSC-SV 20250812 v17.pptx
PPTX
Pharma ospi slides which help in ospi learning
DOC
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PPTX
Introduction-to-Literarature-and-Literary-Studies-week-Prelim-coverage.pptx
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PPTX
Lesson notes of climatology university.
PDF
VCE English Exam - Section C Student Revision Booklet
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
GENETICS IN BIOLOGY IN SECONDARY LEVEL FORM 3
GDM (1) (1).pptx small presentation for students
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
O5-L3 Freight Transport Ops (International) V1.pdf
Module 4: Burden of Disease Tutorial Slides S2 2025
Cell Types and Its function , kingdom of life
STATICS OF THE RIGID BODIES Hibbelers.pdf
Weekly quiz Compilation Jan -July 25.pdf
Computing-Curriculum for Schools in Ghana
Complications of Minimal Access Surgery at WLH
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
202450812 BayCHI UCSC-SV 20250812 v17.pptx
Pharma ospi slides which help in ospi learning
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Introduction-to-Literarature-and-Literary-Studies-week-Prelim-coverage.pptx
Microbial diseases, their pathogenesis and prophylaxis
Lesson notes of climatology university.
VCE English Exam - Section C Student Revision Booklet

Enter the gradle

  • 1. NFJS Software Symposium Series 2011 Ken Sipe - CTO, Gradleware Enter The Gradle
  • 2. 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
  • 3. Enter the Gradle Java Build Tools javac IDE ANT Maven ANT + Ivy Gradle
  • 4. 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
  • 5. Enter the Gradle ANT nCross Platform Builds nIDE Independent nXML “script” files ¨build.xml
  • 6. Enter the Gradle Maven nDefined Lifecycle 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 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
  • 9. 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, …
  • 10. Enter the Gradle What is Gradle? Gradle is Declarative Specify what... ...not how
  • 11. Enter the Gradle What is Gradle? Gradle is Declarative ... without being Rigid
  • 12. 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
  • 13. Enter the Gradle Getting Started http://gradle.org/ ~$ gradle -t :reportTask ------------------------------------------------------------ Root Project ------------------------------------------------------------ No tasks BUILD SUCCESSFUL
  • 14. 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.
  • 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 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'} }
  • 17. Enter the Gradle Sample Simple Build File apply plugin:'war' version = 0.1 repositories { mavenCentral() } dependencies { compile "commons-lang:commons-lang:2.4" }
  • 18. Enter the Gradle Defaults apply plugin:'war' version = 0.1 defaultTasks ‘clean’, ‘build’ repositories { mavenCentral() } dependencies { compile "commons-lang:commons-lang:2.4" }
  • 19. Enter the Gradle Beyond the Basics 19
  • 20. 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?
  • 21. 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” ! } }
  • 22. Enter the Gradle Extensible Object Model tasks.withType(Jar).allObjects { jarTask -> ! jarTask.osgi = new DefaultOsgiManifest() ! jarTask.doFirst { task -> ! ! importOsgiManifestIntoManifest(task) } }
  • 23. 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) }
  • 24. 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
  • 25. Enter the Gradle Gradle Lifecycle 25
  • 26. 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
  • 27. 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
  • 28. 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’ }
  • 29. 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' } }
  • 30. Enter the Gradle Gradle Dependencies 30
  • 31. 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 }
  • 32. 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' }
  • 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 File Dependencies dependencies { runtime files('libs/a.jar', 'libs/b.jar') runtime fileTree(dir: 'libs', includes: ['*.jar']) }
  • 35. 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 }
  • 36. 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
  • 37. Enter the Gradle Flat File Repo repositories { flatDir name: 'localRepository', dirs: 'lib' flatDir dirs: ['lib1', 'lib2'] }
  • 38. Enter the Gradle Custom Gradle custom tasks and plugins 38
  • 39. 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 } }
  • 40. 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)
  • 41. 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'
  • 42. 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
  • 43. Enter the Gradle Jetty Plugin Demo with CamelCase 43
  • 44. 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
  • 45. Enter the Gradle Common Interests 45
  • 46. 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') } }
  • 47. Enter the Gradle Explode the WAR war.doLast { ant.unzip(src: war.archivePath, dest: "$buildDir/exploded") }
  • 48. 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:
  • 49. 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
  • 50. Enter the Gradle Running Processes 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 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
  • 54. 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:
  • 55. Enter the Gradle •Gradle is 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