Gradle for Beginners
Coding Serbia, 18.10.2013
Joachim Baumann
Gradle for Beginners

• 

Build-Management
–  Needs
–  Wishes

• 

Gradle - Basics

• 

Configuration and Execution Phase

• 

Groovy – Short Overview

• 

Plug-ins – Basics

• 

Our
– 
– 
– 
– 
– 
– 

First Project
Directory Structure
Dependencies
Manipulating the Jar
Tests
Quality Assurance
Publishing the Artefacts
What do we need from a Build-Management System?
• 
• 
• 
• 
• 

• 
• 
• 
• 
• 

Translating the Source Code (using a compiler)
Linking the Results
Check out the source code from a repository (optional)
Creating Tags (optional)
Execution of different types of tests: Examples:
–  Unit Tests for single Classes
–  Module or Component Tests
–  Integration Tests
–  Functional and Non-Functional System Tests
–  Automated Acceptance Tests
Detailed Test Reports combining all Test Results (optional)
Packing the Result (e.g., into a Jar, War or Ear)
Transfer the Results to the different Stages / Test Systems and Execution of
the respective Tests (optional)
Support for multi-language Projects
Creation of Documentation and Release Notes
What do we wish for in our Build-Management System?
•  Explicit Support of the Workflow implemented by the BuildManagement-System
•  Simple Modifiability and Extensibility of the Workflow to adapt to
local processes
•  Readability and self-documentation of the notation in the build
script
•  Use of sensible conventions (e.g., where to find the sources)
•  Simple change of the conventions to adap to local environment
•  Incremental Build that can identify artefacts that have already
been built
•  Parallelisation of independent steps in the workflow to minimize
waiting
•  Programmatic access to all artefacts being created by the build
•  Status reports that summarize the current state of the build
Gradle - Basics
• 

Gradle uses build scripts which are named build.gradle

• 

Every build script is a Groovy script

• 

Two very important Principles
–  Convention over Configuration
–  Don’t Repeat Yourself

• 

Gradle creates a dynamic model of the workflow as a Directed Acyclic Graph
(DAG)

• 

(Nearly) Everything is convention and can be changed

tset

tseTelipmoc

dliub

elipmoc
elbmessa
Configuration Phase
• 
• 

• 
• 

Executes the build script
The contained Groovy- and DSL-commands configure the underlying
object tree
The root of the object tree is the Project object
–  Is directly available in the script (methods and properties)
Creation of new Tasks that can be used
Manipulation of the DAG

• 

Our first script build.gradle

• 

println ”Hello from the configuration phase"
Execution Phase
• 

Executes all tasks that have been called (normally on the command line)

• 

For a task that is executed every task it depends on is executed beforehand

• 

Gradle uses the DAG to identify all task relationships

tset

tseTelipmoc

dliub

elipmoc
elbmessa
Task Definition
• 
• 

Takes an (optional) configuration closure
Alternatively: can be configured directly

• 
• 

The operator << (left-shift) appends an action (a closure) to this task’s list of actions
Equivalent to doLast()

• 

Insert at the beginning of the list with doFirst()
task halloTask
halloTask.doLast { print "from the " }
halloTask << { println "execution phase" }
halloTask.doFirst { print "Hello " }
task postHallo (dependsOn: halloTask) << {
println "End"
}
postHallo { // configuration closure
dependsOn halloTask
}
Groovy – Short Overview
• 

Simplified Java Syntax
–  Semicolon optional
–  GString
–  Everything is an Object
–  Simplification e.g., “println”

• 

Scripts

• 

Operator Overloading
–  Predefined
•  Example <<
•  Operator for secure navigation a.?b
–  You can provide your own implementations

• 

Named Parameters

• 

Closures

• 

Collection Iterators
Plug-ins - Basics
• 

Plug-ins encapsulate functionality

• 

Can be written in any VM-language
–  Groovy is a good choice

• 

Possible Plug-in Sources
–  Plug-ins packed with Gradle
–  Plug-ins included using URLs (don’t do it)
–  Plug-ins provided by repositories (use your own repository)
–  Self-written Plug-ins (normally in the directory buildSrc)

• 

Plug-ins
–  Extend objects
–  Provide new objects and / or abstractions
–  Configure existing objects

• 

Plug-ins are load with the command apply plugin
apply plugin: ‘java’
Our first Project

• 

We use the Java Plug-in

• 

Default paths used by the
Java Plug-in
–  Derived from Maven
Conventions
The Class HelloWorld

package de.gradleworkshop;
import java.util.ArrayList;
import java.util.List;
public class HelloWorld {
public static void main(String[] args) {
HelloWorld hw = new HelloWorld();
for(String greeting : hw.generateGreetingsData())
System.out.println(greeting);
}
public List<String> generateGreetingsData() {
List <String> greetings = new ArrayList <String>();
greetings.add("Hallo Welt");
return greetings;
}
}
Manipulation of the Manifest
• 

Every Jar-Archive contains a file MANIFEST.MF

• 

Is generated by Gradle (see directory build/tmp/jar/MANIFEST.MF)

• 

Contains information e.g., about the main class of the jar

• 

Can be changed
jar {

manifest {
attributes 'Main-Class':
'de.gradleworkshop.HelloWorld'
}
}
• 

Alternatively
jar.manifest.attributes 'Main-Class':
'de.gradleworkshop.HelloWorld'
Tests
package de.gradleworkshop;
import java.util.List;
import org.junit.*;
import static org.junit.Assert.*;
public class HelloWorldTest {
HelloWorld oUT;
@Before
public void setUp() {
oUT = new HelloWorld();
}
@Test
public void testGenerateGreetingsData() {
List<String> res = oUT.generateGreetingsData();
assertEquals("wrong number of results", 1, res.size());
}
}
Configurations and Dependencies
• 

Gradle defines Configuration Objects. These encapsulate
–  Dependency Information
–  Paths to Sources and Targets
–  Associated Artefacts
–  Additional Configuration Information

• 

Tasks use these Configurations

• 

For most pre-defined Task a Configuration exists
–  compile, testCompile, runtime, testRuntime

• 
• 

Dependencies are defined using the key word dependencies
Maven-like notation for the dependencies
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.+’
}
Repositories
• 

Repositories provide libraries (normally jar archives)

• 

You can define Ivy or Maven Repositories, both public and private

• 

Predefined Repositories
–  JCenter
–  Maven Central
–  Local Maven Repository (~/.m2/repository)

• 

Repositories are defined using the keyword repositories
repositories {
mavenLocal()
}
repositories {
jcenter()
mavenCentral()
}

• 

Multiple Repositories can be defined
The Application Plug-in
• 

The Application-Plug-in
–  Adds a Task run
–  Creates start scripts, that can be used with the Task run
–  Creates a Task distZip, that packs all necessary files into a ziparchive
–  Definition of the Main Class
mainClassName = "de.gradleworkshop.HelloWorld"
–  Usage with
apply plugin: 'application'
Using TestNG
• 

Very Simple

dependencies {
testCompile group: 'org.testng', name: 'testng',
version: '6.+'
}
test {
useTestNG()
}
Test Class for TestNG
package de.gradleworkshop;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
public class TestHelloWorld {
HelloWorld oUT;
@BeforeTest
public void setUp() {
oUT = new HelloWorld();
}
@Test
public void testGenerateGreetingsData() {
List<String> res = oUT.generateGreetingsData();
assertEquals("Wrong Number of Entries", 1, res.size());
}
}
Quality Assurance
• 

Support for PMD, Checkstyle, Findbugs, Emma, Sonar …

• 

Example PMD
apply plugin: 'pmd'
pmdMain {
ruleSets = [ "basic", "strings" ]
ignoreFailures = true
}

• 

Another Example configuring all Tasks of Type Pmd using withType()
tasks.withType(Pmd) {
ruleSets = [ "basic", "strings" ]
ignoreFailures = true
ruleSetFiles = files('config/pmd/rulesets.xml')
reports {
xml.enabled false
html.enabled true
}
}
Publishing the Artefacts
• 

Gradle defines for every Configuration a Task upload<Configuration>
–  Builds and publishes the Artefact belonging to the Configuration

• 

The Java-Plug-in creates a Configuration archives, which contains all artefacts
created in the Task jar
–  uploadArchives is the natural choice for publishing the artefacts

• 

Use of the Maven-Plug-in with apply plugin: ‘maven’
–  Doesn’t use the normal repository (intentionally)
apply plugin: 'maven'
version = '0.1-SNAPSHOT'
group = 'de.gradleworkshop'
uploadArchives {
repositories {
flatDir { dirs "repo" }
mavenDeployer { repository
(url : "file://$projectDir/mavenRepo/") }
}
}
The whole Script (less than 20 lines)
apply plugin: 'java'
apply plugin: 'pmd'
jar.manifest.attributes 'Main-Class': 'de.gradleworkshop.HelloWorld'
pmdMain {
ruleSets = [ "basic", "strings" ]
ignoreFailures = true
}
repositories { mavenCentral() }
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.+'
}
apply plugin: ‘maven’
version = '0.1-SNAPSHOT’
group = 'de.gradleworkshop’
uploadArchives {
repositories {
flatDir { dirs "repo" }
mavenDeployer { repository (url : "file:///gradleWS/myRepo/")
} } }
Recap
• 

We have, with Gradle
–  Built an Application
–  Created Tests and executed them
–  Used an alternative Test Framework TestNG
–  Used Quality Assurance
–  Uploaded the Artefacts into two Repositories

• 

You now know everything to build normal Projects with Gradle

• 

Gradle
–  Is simple
–  Easily understood
–  Has sensible conventions
–  That can be easily changed

• 

Gradle adapts to your needs
Questions?

Dr. Joachim Baumann
codecentric AG
An der Welle 4
60322 Frankfurt
Joachim.Baumann@codecentric.de
www.codecentric.de
blog.codecentric.de

24	
  

Gradle For Beginners (Serbian Developer Conference 2013 english)

  • 1.
    Gradle for Beginners CodingSerbia, 18.10.2013 Joachim Baumann
  • 2.
    Gradle for Beginners •  Build-Management – Needs –  Wishes •  Gradle - Basics •  Configuration and Execution Phase •  Groovy – Short Overview •  Plug-ins – Basics •  Our –  –  –  –  –  –  First Project Directory Structure Dependencies Manipulating the Jar Tests Quality Assurance Publishing the Artefacts
  • 3.
    What do weneed from a Build-Management System? •  •  •  •  •  •  •  •  •  •  Translating the Source Code (using a compiler) Linking the Results Check out the source code from a repository (optional) Creating Tags (optional) Execution of different types of tests: Examples: –  Unit Tests for single Classes –  Module or Component Tests –  Integration Tests –  Functional and Non-Functional System Tests –  Automated Acceptance Tests Detailed Test Reports combining all Test Results (optional) Packing the Result (e.g., into a Jar, War or Ear) Transfer the Results to the different Stages / Test Systems and Execution of the respective Tests (optional) Support for multi-language Projects Creation of Documentation and Release Notes
  • 4.
    What do wewish for in our Build-Management System? •  Explicit Support of the Workflow implemented by the BuildManagement-System •  Simple Modifiability and Extensibility of the Workflow to adapt to local processes •  Readability and self-documentation of the notation in the build script •  Use of sensible conventions (e.g., where to find the sources) •  Simple change of the conventions to adap to local environment •  Incremental Build that can identify artefacts that have already been built •  Parallelisation of independent steps in the workflow to minimize waiting •  Programmatic access to all artefacts being created by the build •  Status reports that summarize the current state of the build
  • 5.
    Gradle - Basics •  Gradleuses build scripts which are named build.gradle •  Every build script is a Groovy script •  Two very important Principles –  Convention over Configuration –  Don’t Repeat Yourself •  Gradle creates a dynamic model of the workflow as a Directed Acyclic Graph (DAG) •  (Nearly) Everything is convention and can be changed tset tseTelipmoc dliub elipmoc elbmessa
  • 6.
    Configuration Phase •  •  •  •  Executes thebuild script The contained Groovy- and DSL-commands configure the underlying object tree The root of the object tree is the Project object –  Is directly available in the script (methods and properties) Creation of new Tasks that can be used Manipulation of the DAG •  Our first script build.gradle •  println ”Hello from the configuration phase"
  • 7.
    Execution Phase •  Executes alltasks that have been called (normally on the command line) •  For a task that is executed every task it depends on is executed beforehand •  Gradle uses the DAG to identify all task relationships tset tseTelipmoc dliub elipmoc elbmessa
  • 8.
    Task Definition •  •  Takes an(optional) configuration closure Alternatively: can be configured directly •  •  The operator << (left-shift) appends an action (a closure) to this task’s list of actions Equivalent to doLast() •  Insert at the beginning of the list with doFirst() task halloTask halloTask.doLast { print "from the " } halloTask << { println "execution phase" } halloTask.doFirst { print "Hello " } task postHallo (dependsOn: halloTask) << { println "End" } postHallo { // configuration closure dependsOn halloTask }
  • 9.
    Groovy – ShortOverview •  Simplified Java Syntax –  Semicolon optional –  GString –  Everything is an Object –  Simplification e.g., “println” •  Scripts •  Operator Overloading –  Predefined •  Example << •  Operator for secure navigation a.?b –  You can provide your own implementations •  Named Parameters •  Closures •  Collection Iterators
  • 10.
    Plug-ins - Basics •  Plug-insencapsulate functionality •  Can be written in any VM-language –  Groovy is a good choice •  Possible Plug-in Sources –  Plug-ins packed with Gradle –  Plug-ins included using URLs (don’t do it) –  Plug-ins provided by repositories (use your own repository) –  Self-written Plug-ins (normally in the directory buildSrc) •  Plug-ins –  Extend objects –  Provide new objects and / or abstractions –  Configure existing objects •  Plug-ins are load with the command apply plugin apply plugin: ‘java’
  • 11.
    Our first Project •  Weuse the Java Plug-in •  Default paths used by the Java Plug-in –  Derived from Maven Conventions
  • 12.
    The Class HelloWorld packagede.gradleworkshop; import java.util.ArrayList; import java.util.List; public class HelloWorld { public static void main(String[] args) { HelloWorld hw = new HelloWorld(); for(String greeting : hw.generateGreetingsData()) System.out.println(greeting); } public List<String> generateGreetingsData() { List <String> greetings = new ArrayList <String>(); greetings.add("Hallo Welt"); return greetings; } }
  • 13.
    Manipulation of theManifest •  Every Jar-Archive contains a file MANIFEST.MF •  Is generated by Gradle (see directory build/tmp/jar/MANIFEST.MF) •  Contains information e.g., about the main class of the jar •  Can be changed jar { manifest { attributes 'Main-Class': 'de.gradleworkshop.HelloWorld' } } •  Alternatively jar.manifest.attributes 'Main-Class': 'de.gradleworkshop.HelloWorld'
  • 14.
    Tests package de.gradleworkshop; import java.util.List; importorg.junit.*; import static org.junit.Assert.*; public class HelloWorldTest { HelloWorld oUT; @Before public void setUp() { oUT = new HelloWorld(); } @Test public void testGenerateGreetingsData() { List<String> res = oUT.generateGreetingsData(); assertEquals("wrong number of results", 1, res.size()); } }
  • 15.
    Configurations and Dependencies •  Gradledefines Configuration Objects. These encapsulate –  Dependency Information –  Paths to Sources and Targets –  Associated Artefacts –  Additional Configuration Information •  Tasks use these Configurations •  For most pre-defined Task a Configuration exists –  compile, testCompile, runtime, testRuntime •  •  Dependencies are defined using the key word dependencies Maven-like notation for the dependencies dependencies { testCompile group: 'junit', name: 'junit', version: '4.+’ }
  • 16.
    Repositories •  Repositories provide libraries(normally jar archives) •  You can define Ivy or Maven Repositories, both public and private •  Predefined Repositories –  JCenter –  Maven Central –  Local Maven Repository (~/.m2/repository) •  Repositories are defined using the keyword repositories repositories { mavenLocal() } repositories { jcenter() mavenCentral() } •  Multiple Repositories can be defined
  • 17.
    The Application Plug-in •  TheApplication-Plug-in –  Adds a Task run –  Creates start scripts, that can be used with the Task run –  Creates a Task distZip, that packs all necessary files into a ziparchive –  Definition of the Main Class mainClassName = "de.gradleworkshop.HelloWorld" –  Usage with apply plugin: 'application'
  • 18.
    Using TestNG •  Very Simple dependencies{ testCompile group: 'org.testng', name: 'testng', version: '6.+' } test { useTestNG() }
  • 19.
    Test Class forTestNG package de.gradleworkshop; import java.util.List; import static org.junit.Assert.assertEquals; import static org.testng.AssertJUnit.*; import org.testng.annotations.*; public class TestHelloWorld { HelloWorld oUT; @BeforeTest public void setUp() { oUT = new HelloWorld(); } @Test public void testGenerateGreetingsData() { List<String> res = oUT.generateGreetingsData(); assertEquals("Wrong Number of Entries", 1, res.size()); } }
  • 20.
    Quality Assurance •  Support forPMD, Checkstyle, Findbugs, Emma, Sonar … •  Example PMD apply plugin: 'pmd' pmdMain { ruleSets = [ "basic", "strings" ] ignoreFailures = true } •  Another Example configuring all Tasks of Type Pmd using withType() tasks.withType(Pmd) { ruleSets = [ "basic", "strings" ] ignoreFailures = true ruleSetFiles = files('config/pmd/rulesets.xml') reports { xml.enabled false html.enabled true } }
  • 21.
    Publishing the Artefacts •  Gradledefines for every Configuration a Task upload<Configuration> –  Builds and publishes the Artefact belonging to the Configuration •  The Java-Plug-in creates a Configuration archives, which contains all artefacts created in the Task jar –  uploadArchives is the natural choice for publishing the artefacts •  Use of the Maven-Plug-in with apply plugin: ‘maven’ –  Doesn’t use the normal repository (intentionally) apply plugin: 'maven' version = '0.1-SNAPSHOT' group = 'de.gradleworkshop' uploadArchives { repositories { flatDir { dirs "repo" } mavenDeployer { repository (url : "file://$projectDir/mavenRepo/") } } }
  • 22.
    The whole Script(less than 20 lines) apply plugin: 'java' apply plugin: 'pmd' jar.manifest.attributes 'Main-Class': 'de.gradleworkshop.HelloWorld' pmdMain { ruleSets = [ "basic", "strings" ] ignoreFailures = true } repositories { mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.+' } apply plugin: ‘maven’ version = '0.1-SNAPSHOT’ group = 'de.gradleworkshop’ uploadArchives { repositories { flatDir { dirs "repo" } mavenDeployer { repository (url : "file:///gradleWS/myRepo/") } } }
  • 23.
    Recap •  We have, withGradle –  Built an Application –  Created Tests and executed them –  Used an alternative Test Framework TestNG –  Used Quality Assurance –  Uploaded the Artefacts into two Repositories •  You now know everything to build normal Projects with Gradle •  Gradle –  Is simple –  Easily understood –  Has sensible conventions –  That can be easily changed •  Gradle adapts to your needs
  • 24.
    Questions? Dr. Joachim Baumann codecentricAG An der Welle 4 60322 Frankfurt Joachim.Baumann@codecentric.de www.codecentric.de blog.codecentric.de 24