make builds groovy

67
© ASERT 2008-2010 Make Your Builds More Groovy Dr Paul King [email protected] @paulk_asert ASERT, Australia ESDC 2010 - 1

description

ant, groovy, maven and gradle

Transcript of make builds groovy

© A

SE

RT

20

08

-20

10

Make Your Builds More Groovy

Dr Paul King

[email protected]

@paulk_asert

ASERT, Australia

ESDC 2010 - 1

Topics

Build Pain Points

• Build Tool Landscape

• Groovy Intro

• Ant & friends

• Maven & friends

• Gradle

• Other Tools

• More Info

ESDC 2010 - 2

© A

SE

RT

20

08

-20

10

Build Pain Points...

• Has anyone seen?

– Large monolithic balls of mud

– Complex usage, assumptions, conventions

– Impossible to bend in desired ways

– Never been (can't be) refactored/tested

– Many manual steps

– Environment fragile

• different machines, CI vs IDE, dev vs prod vs test

ESDC 2010 - 3

© A

SE

RT

20

08

-20

10

...Build Pain Points...

• Require powerful features– Dependency management

– Version management

– Polyglot compilation

– Artifact production and manipulation (jar, war, ...)

– Templating (generation of boilerplate text files)

– Multifacted testing

– Reporting

– Quality control (Metrics, code quality, static analysis)

– Property management

– Infinitely(?) extensible

ESDC 2010 - 4

© A

SE

RT

20

08

-20

10

...Build Pain Points

• Useful characteristics– Tool friendly

– Cross platform

– IDE support, CI support

– Refactorable

– Testable

– Minimal noise (DSL like)

– Easy to extend

– Conventions

– Good documentation

– Polyglot friendly

ESDC 2010 - 5

© A

SE

RT

20

08

-20

10

Topics

• Build Pain Points

Build Tool Landscape

• Groovy Intro

• Ant & friends

• Maven & friends

• Gradle

• Other Tools

• More Info

ESDC 2010 - 6

© A

SE

RT

20

08

-20

10

Build Tools

• Non-exhaustive list– Ant, Maven, EasyAnt

– Gant, GMaven, Gradle, Graven (uptake?),

Groovy Frontend for Ant (emerge from sandbox?)

– Rake, Raven, Buildr

– Make, SCons, Waf

– MSBuild, Nant

• Used by– Developers: NetBeans, Eclipse, Intellij, Command-line

– CI: Hudson (Groovy support and console), Team City,

CruiseControl, AnthillPro (Groovy support), Bamboo

– Deployment Management: Tableaux (Groovy support)

– Ad-hoc: batch processing, production applications

ESDC 2010 - 7

© A

SE

RT

20

08

-20

10

Pros/Cons of Traditional Tools• Ant

– Flexible (supports any

convention)

– Easy to extend

– Wealth of useful tasks

– Well documented

– Partially declarative but

some scope for

procedural instructions

• XML != prog. language

– Lifecycle is hand-crafted

in your build file

– Can use Ivy or Maven Ant

tasks for dependency

management

• Maven

– Opinionated about

conventions

• Mostly a good thing

– Mostly declarative

• XML != concise DSL

– Numerous plugins

– Some easy extension

points but some more

difficult options

• Some things beyond

some teams

– Structured lifecycle

ESDC 2010 - 8

© A

SE

RT

20

08

-20

10

Enhancing Traditional Tools• Ant + Groovy

– Easy to write the

procedural pieces

– Easier to refactor

– Easier to test

– Ease of creating a build

DSL

– More concise

– Better interaction with

Java

– No impedence

mismatch with

developers

• Maven + Groovy

– Easier to extend

– More concise syntax

– Some scope for

refactoring

• Gradle

– Take the best of both

worlds and combine

them

ESDC 2010 - 9

© A

SE

RT

20

08

-20

10

A Preview Example...

ESDC 2010 - 10

© A

SE

RT

20

08

-20

10

...A Preview Example...

ESDC 2010 - 11

© A

SE

RT

20

08

-20

10

<project name="StringUtilsBuild" default="package"xmlns:ivy="antlib:org.apache.ivy.ant" xmlns="antlib:org.apache.tools.ant">

<target name="clean"><delete dir="target"/><delete dir="lib"/>

</target>

<target name="compile" depends="-init-ivy"><mkdir dir="target/classes"/><javac srcdir="src/main"

destdir="target/classes"/></target>

<target name="compileTest" depends="compile"><mkdir dir="target/test-classes"/><javac srcdir="src/test"

destdir="target/test-classes"><classpath>

<pathelement location="target/classes"/><fileset dir="lib" includes="*.jar"/>

</classpath></javac>

</target>

<target name="test" depends="compileTest"><mkdir dir="target/test-reports"/><junit printsummary="yes" fork="yes" haltonfailure="yes">

<classpath><pathelement location="target/classes"/><pathelement location="target/test-classes"/><fileset dir="lib" includes="*.jar"/>

</classpath><formatter type="plain"/><formatter type="xml"/><batchtest fork="yes" todir="target/test-reports">

<fileset dir="target/test-classes"/></batchtest>

</junit></target>

<target name="package" depends="test"><jar destfile="target/stringutils-1.0-SNAPSHOT.jar"

basedir="target/classes"/></target>

<target name="-init-ivy" depends="-download-ivy"><taskdef resource="org/apache/ivy/ant/antlib.xml"

uri="antlib:org.apache.ivy.ant" classpath="lib/ivy.jar"/><ivy:settings file="ivysettings.xml"/><ivy:retrieve/>

</target>

<target name="-download-ivy"><property name="ivy.version" value="2.1.0-rc2"/><mkdir dir="lib"/><get

src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.version}/ivy-${ivy.version}.jar"

dest="lib/ivy.jar" usetimestamp="true"/></target>

</project>

<?xml version="1.0" encoding="ISO-8859-1"?><ivy-module version="1.0">

<info organisation="org" module="groovycookbook" /><dependencies>

<dependency name="junit" rev="4.7" /></dependencies>

</ivy-module>

<ivysettings><settings defaultResolver="chained"/><resolvers><chain name="chained" returnFirst="true">

<ibiblio name="ibiblio" /><url name="ibiblio-mirror"><artifact

pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/[module]/[branch]/[revision]/[branch]-[revision].[ext]" />

</url></chain>

</resolvers></ivysettings>

StringUtils: Vanilla Ant + Ivy

...A Preview Example...

ESDC 2010 - 12

© A

SE

RT

20

08

-20

10

import static groovy.xml.NamespaceBuilder.newInstance as namespace

ant = new AntBuilder()clean()doPackage()

def doPackage() {test()ant.jar destfile: 'target/stringutils-1.0-SNAPSHOT.jar',

basedir: 'target/classes'}

private dependencies() {def ivy_version = '2.1.0-rc2'def repo = 'http://repo2.maven.org/maven2'ant.mkdir dir: 'lib'ant.get dest: 'lib/ivy.jar',

usetimestamp: 'true',src: "$repo/org/apache/ivy/ivy/$ivy_version/ivy-${ivy_version}.jar"

ant.taskdef classpath: 'lib/ivy.jar',uri: 'antlib:org.apache.ivy.ant',resource: 'org/apache/ivy/ant/antlib.xml'

def ivy = namespace(ant, 'antlib:org.apache.ivy.ant')ivy.settings file: 'ivysettings.xml'ivy.retrieve()

}

def clean() {ant.delete dir: 'target'ant.delete dir: 'lib'

}

def compile() {dependencies()ant.mkdir dir: 'target/classes'ant.javac destdir: 'target/classes', srcdir: 'src/main',

includeantruntime: false}

def compileTest() {compile()ant.mkdir dir: 'target/test-classes'ant.javac(destdir: 'target/test-classes', srcdir: 'src/test',

includeantruntime: false) {classpath {

pathelement location: 'target/classes'fileset dir: 'lib', includes: '*.jar'

}}

}...

<?xml version="1.0" encoding="ISO-8859-1"?><ivy-module version="1.0">

<info organisation="org" module="groovycookbook" /><dependencies>

<dependency name="junit" rev="4.7" /></dependencies>

</ivy-module>

<ivysettings><settings defaultResolver="chained"/><resolvers><chain name="chained" returnFirst="true">

<ibiblio name="ibiblio" /><url name="ibiblio-mirror"><artifact

pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/[module]/[branch]/[revision]/[branch]-[revision].[ext]" />

</url></chain>

</resolvers></ivysettings>

StringUtils: Groovy's AntBuilder...

def test() {compileTest()ant.mkdir dir: 'target/test-reports'ant.junit(printsummary: 'yes', haltonfailure: 'yes', fork: 'yes') {

classpath {pathelement location: 'target/classes'pathelement location: 'target/test-classes'fileset dir: 'lib', includes: '*.jar'

}formatter type: 'plain'formatter type: 'xml'batchtest(todir: 'target/test-reports', fork: 'yes') {

fileset dir: 'target/test-classes'}

}}

...A Preview Example...

ESDC 2010 - 13

© A

SE

RT

20

08

-20

10

import static groovy.xml.NamespaceBuilder.newInstance as namespace

target('package': '') {depends 'test'jar destfile: 'target/stringutils-1.0-SNAPSHOT.jar',

basedir: 'target/classes'}

target('-download-ivy': '') {def ivy_version = '2.1.0-rc2'def repo = 'http://repo2.maven.org/maven2'mkdir dir: 'lib'get dest: 'lib/ivy.jar',

usetimestamp: 'true',src: "$repo/org/apache/ivy/ivy/$ivy_version/ivy-${ivy_version}.jar"

}

target(clean: '') {delete dir: 'target'delete dir: 'lib'

}

target(compile: '') {depends '-init-ivy'mkdir dir: 'target/classes'javac destdir: 'target/classes', srcdir: 'src/main'

}

target('-init-ivy': '') {depends '-download-ivy'taskdef classpath: 'lib/ivy.jar',

uri: 'antlib:org.apache.ivy.ant',resource: 'org/apache/ivy/ant/antlib.xml'

def ivy = namespace(ant, 'antlib:org.apache.ivy.ant')ivy.settings file: 'ivysettings.xml'ivy.retrieve()

}

target(compileTest: '') {depends 'compile'mkdir dir: 'target/test-classes'javac(destdir: 'target/test-classes', srcdir: 'src/test') {

classpath {pathelement location: 'target/classes'fileset dir: 'lib', includes: '*.jar'

}}

}...

<?xml version="1.0" encoding="ISO-8859-1"?><ivy-module version="1.0">

<info organisation="org" module="groovycookbook" /><dependencies>

<dependency name="junit" rev="4.7" /></dependencies>

</ivy-module>

<ivysettings><settings defaultResolver="chained"/><resolvers><chain name="chained" returnFirst="true">

<ibiblio name="ibiblio" /><url name="ibiblio-mirror"><artifact

pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/[module]/[branch]/[revision]/[branch]-[revision].[ext]" />

</url></chain>

</resolvers></ivysettings>

StringUtils: Gant...

target(test: '') {depends 'compileTest'mkdir dir: 'target/test-reports'junit(printsummary: 'yes', haltonfailure: 'yes', fork: 'yes') {

classpath {pathelement location: 'target/classes'pathelement location: 'target/test-classes'fileset dir: 'lib', includes: '*.jar'

}formatter type: 'plain'formatter type: 'xml'batchtest(todir: 'target/test-reports', fork: 'yes') {

fileset dir: 'target/test-classes'}

}}

setDefaultTarget 'package'

...A Preview Example...

ESDC 2010 - 14

© A

SE

RT

20

08

-20

10

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.groovycookbook.builds</groupId><artifactId>stringutils</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><name>stringutils</name><url>http://maven.apache.org</url><dependencies>

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.7</version><scope>test</scope>

</dependency></dependencies><build>

<plugins><!-- this is a java 1.5 project --><plugin>

<groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration>

<source>1.5</source><target>1.5</target>

</configuration></plugin>

</plugins></build>

</project>

StringUtils: Maven

...A Preview Example

ESDC 2010 - 15

© A

SE

RT

20

08

-20

10

usePlugin 'java'

sourceCompatibility = 1.5version = '1.0-SNAPSHOT'

repositories {mavenCentral()

}

dependencies {testCompile 'junit:junit:4.7'

}

StringUtils: Gradle

Topics

• Build Pain Points

• Build Tool Landscape

Groovy Intro

• Ant & friends

• Maven & friends

• Gradle

• Other Tools

• More Info

ESDC 2010 - 16

© A

SE

RT

20

08

-20

10

ESDC 2010 - 17

© A

SE

RT

20

08

-20

10

What is Groovy?

• “Groovy is like a super version

of Java. It can leverage Java's

enterprise capabilities but also

has cool productivity features like closures,

DSL support, builders and dynamic typing.”

Groovy = Java – boiler plate code+ optional dynamic typing+ closures+ domain specific languages+ builders+ metaprogramming+ GDK library

ESDC 2010 - 18

© A

SE

RT

20

08

-20

10

Groovy Goodies Overview• Fully object oriented

• Closures: reusable

and assignable

pieces of code

• Operators can be

overloaded

• Multimethods

• Literal declaration for

lists (arrays), maps,

ranges and regular

expressions

• GPath: efficient

object navigation

• GroovyBeans

• grep and switch

• Templates, builder,

swing, Ant, markup,

XML, SQL, XML-RPC,

Scriptom, Grails,

tests, Mocks

Growing Acceptance …

A slow and steady start but now gaining in

momentum, maturity and mindshare

Now free

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 20

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 21

Groovy and Grails downloads:70-90K per month and growing

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 22

Source: http://www.grailspodcast.com/

Source: http://www.micropoll.com/akira/mpresult/501697-116746

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 23http://www.java.net

http://www.jroller.com/scolebourne/entry/devoxx_2008_whiteboard_votes

… Growing Acceptance

© A

SE

RT

20

06

-20

10

ESDC 2010 - 24

http://pollpigeon.com/jsf-grails-wicket/r/25665/

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 25http://www.leonardoborges.com/writings

What alternative JVM language are you using or intending to use

… Growing Acceptance …

© A

SE

RT

20

08

-20

10

ESDC 2010 - 26

http://it-republik.de/jaxenter/quickvote/results/1/poll/44 (translated using http://babelfish.yahoo.com)

… Growing Acceptance

ESDC 2010 - 27

© A

SE

RT

20

08

-20

10

ESDC 2010 - 28

© A

SE

RT

20

08

-20

10

The Landscape of JVM Languages

Java bytecode calls

for static types

Dynamic features call

for dynamic types

mostly

dynamic

typing

The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ platform.

ESDC 2010 - 29

© A

SE

RT

20

08

-20

10

Groovy StarterSystem.out.println("Hello, World!"); // optional semicolon,println 'Hello, World!' // System.out, brackets,

// main() method, class defn

def name = 'Guillaume' // dynamic typingprintln "$name, I'll get the car." // GString

String longer = """${name}, the caris in the next row.""" // multi-line string

// with static typing

assert 0.5 == 1/2 // BigDecimal equals()

def printSize(obj) { // optional duck typingprint obj?.size() // safe dereferencing

}

def pets = ['ant', 'bee', 'cat'] // native list syntaxpets.each { pet -> // closure support

assert pet < 'dog' // overloading '<' on String} // or: for (pet in pets)...

A Better Java...

ESDC 2010 - 30

© A

SE

RT

20

08

-20

10

import java.util.List;import java.util.ArrayList;

class Erase {private List removeLongerThan(List strings, int length) {

List result = new ArrayList();for (int i = 0; i < strings.size(); i++) {

String s = (String) strings.get(i);if (s.length() <= length) {

result.add(s);}

}return result;

}public static void main(String[] args) {

List names = new ArrayList();names.add("Ted"); names.add("Fred");names.add("Jed"); names.add("Ned");System.out.println(names);Erase e = new Erase();List shortNames = e.removeLongerThan(names, 3);System.out.println(shortNames.size());for (int i = 0; i < shortNames.size(); i++) {

String s = (String) shortNames.get(i);System.out.println(s);

}}

}

This codeis validJava andvalid Groovy

Based on anexample byJim Weirich& Ted Leung

...A Better Java...

ESDC 2010 - 31

© A

SE

RT

20

08

-20

10

import java.util.List;import java.util.ArrayList;

class Erase {private List removeLongerThan(List strings, int length) {

List result = new ArrayList();for (int i = 0; i < strings.size(); i++) {

String s = (String) strings.get(i);if (s.length() <= length) {

result.add(s);}

}return result;

}public static void main(String[] args) {

List names = new ArrayList();names.add("Ted"); names.add("Fred");names.add("Jed"); names.add("Ned");System.out.println(names);Erase e = new Erase();List shortNames = e.removeLongerThan(names, 3);System.out.println(shortNames.size());for (int i = 0; i < shortNames.size(); i++) {

String s = (String) shortNames.get(i);System.out.println(s);

}}

}

Do thesemicolonsadd anything?And shouldn‟twe us moremodern listnotation?Why notimport commonlibraries?

...A Better Java...

ESDC 2010 - 32

© A

SE

RT

20

08

-20

10

class Erase {private List removeLongerThan(List strings, int length) {

List result = new ArrayList()for (String s in strings) {

if (s.length() <= length) {result.add(s)

}}return result

}

public static void main(String[] args) {List names = new ArrayList()names.add("Ted"); names.add("Fred")names.add("Jed"); names.add("Ned")System.out.println(names)Erase e = new Erase()List shortNames = e.removeLongerThan(names, 3)System.out.println(shortNames.size())for (String s in shortNames) {

System.out.println(s)}

}}

...A Better Java...

ESDC 2010 - 33

© A

SE

RT

20

08

-20

10

class Erase {private List removeLongerThan(List strings, int length) {

List result = new ArrayList()for (String s in strings) {

if (s.length() <= length) {result.add(s)

}}return result

}

public static void main(String[] args) {List names = new ArrayList()names.add("Ted"); names.add("Fred")names.add("Jed"); names.add("Ned")System.out.println(names)Erase e = new Erase()List shortNames = e.removeLongerThan(names, 3)System.out.println(shortNames.size())for (String s in shortNames) {

System.out.println(s)}

}}

Do we needthe static types?Must we alwayshave a mainmethod andclass definition?How aboutimprovedconsistency?

...A Better Java...

ESDC 2010 - 34

© A

SE

RT

20

08

-20

10

def removeLongerThan(strings, length) {def result = new ArrayList()for (s in strings) {

if (s.size() <= length) {result.add(s)

}}return result

}

names = new ArrayList()names.add("Ted")names.add("Fred")names.add("Jed")names.add("Ned")System.out.println(names)shortNames = removeLongerThan(names, 3)System.out.println(shortNames.size())for (s in shortNames) {

System.out.println(s)}

...A Better Java...

ESDC 2010 - 35

© A

SE

RT

20

08

-20

10

def removeLongerThan(strings, length) {def result = new ArrayList()for (s in strings) {

if (s.size() <= length) {result.add(s)

}}return result

}

names = new ArrayList()names.add("Ted")names.add("Fred")names.add("Jed")names.add("Ned")System.out.println(names)shortNames = removeLongerThan(names, 3)System.out.println(shortNames.size())for (s in shortNames) {

System.out.println(s)}

Shouldn‟t wehave specialnotation for lists? And specialfacilities forlist processing?Is „return‟needed at end?

...A Better Java...

ESDC 2010 - 36

© A

SE

RT

20

08

-20

10

def removeLongerThan(strings, length) {strings.findAll{ it.size() <= length }

}

names = ["Ted", "Fred", "Jed", "Ned"]System.out.println(names)shortNames = removeLongerThan(names, 3)System.out.println(shortNames.size())shortNames.each{ System.out.println(s) }

...A Better Java...

ESDC 2010 - 37

© A

SE

RT

20

08

-20

10

def removeLongerThan(strings, length) {strings.findAll{ it.size() <= length }

}

names = ["Ted", "Fred", "Jed", "Ned"]System.out.println(names)shortNames = removeLongerThan(names, 3)System.out.println(shortNames.size())shortNames.each{ System.out.println(s) }

Is the methodnow needed?Easier ways touse commonmethods?Are bracketsrequired here?

...A Better Java...

ESDC 2010 - 38

© A

SE

RT

20

08

-20

10

names = ["Ted", "Fred", "Jed", "Ned"]println namesshortNames = names.findAll{ it.size() <= 3 }println shortNames.size()shortNames.each{ println it }

...A Better Java

ESDC 2010 - 39

© A

SE

RT

20

08

-20

10

names = ["Ted", "Fred", "Jed", "Ned"]println namesshortNames = names.findAll{ it.size() <= 3 }println shortNames.size()shortNames.each{ println it }

[Ted, Fred, Jed, Ned]3TedJedNed

Topics

• Build Pain Points

• Build Tool Landscape

• Groovy Intro

Ant & friendsCalling Groovy from Ant

Calling Ant from Groovy

Gant

• Maven & friends

• Gradle

• Other Tools

• More InfoESDC 2010 - 40

© A

SE

RT

20

08

-20

10

What is Ant?

• Tool to assist automating (build) steps

ESDC 2010 - 41

© A

SE

RT

20

08

-20

10

<project name="MyProject" default="dist" basedir="."><property name="src" location="src"/><property name="build" location="build"/>

<target name="init"><mkdir dir="${build}"/>

</target>

<target name="compile" depends="init"description="compile the source">

<javac srcdir="${src}" destdir="${build}"/></target>

</project>

Groovy from Ant

• Need groovy jar on your Ant classpath

<taskdef name="groovy"classname="org.codehaus.groovy.ant.Groovy"classpathref="my.classpath"/>

<target name="printXmlFileNamesFromJar"><zipfileset id="found" src="foobar.jar"

includes="**/*.xml"/><groovy>

project.references.found.each {println it.name

} </groovy>

</target>

ESDC 2010 - 42

© A

SE

RT

20

06

-20

10

Groovyc from Ant

• Need groovy jar on your Ant classpath

<taskdef name="groovyc"

classname="org.codehaus.groovy.ant.Groovyc"

classpathref="my.classpath"/>

<groovyc srcdir="${testSourceDirectory}"

destdir="${testClassesDirectory}">

<classpath>

<pathelement path="${mainClassesDirectory}"/>

<pathelement path="${testClassesDirectory}"/>

<path refid="testPath"/>

</classpath>

<javac source="1.5" target="1.5" debug="on" />

</groovyc>

ESDC 2010 - 43

© A

SE

RT

20

06

-20

10

ESDC 2010 - 44

© A

SE

RT

20

06

-20

10

AntBuilder...def ant = new AntBuilder()

ant.echo("hello") // let's just call one task

// create a block of Ant using the builder patternant.with {

myDir = "target/AntTest/"mkdir(dir: myDir)copy(todir: myDir) {

fileset(dir: "src/test") {include(name: "**/*.groovy")

}}echo("done")

}

// now let's do some normal Groovy againfile = new File("target/test/AntTest.groovy")assert file.exists()

Needs ant.jar on your Groovy classpath

...AntBuilder

• Built-in

new AntBuilder().with {echo(file:'Temp.java', '''class Temp {public static void main(String[] args) {

System.out.println("Hello");}

}''')javac(srcdir:'.', includes:'Temp.java', fork:'true')java(classpath:'.', classname:'Temp', fork:'true')echo('Done')

}// =>// [javac] Compiling 1 source file// [java] Hello// [echo] Done

© A

SE

RT

20

06

-20

10

ESDC 2010 - 45

ESDC 2010 - 46

© A

SE

RT

20

06

-20

10

Using AntLibs: Maven Ant Tasks & AntUnitimport static groovy.xml.NamespaceBuilder.newInstance as namespacedef ant = new AntBuilder()def mvn = namespace(ant, 'antlib:org.apache.maven.artifact.ant')def antunit = namespace(ant, 'antlib:org.apache.ant.antunit')

direct = [groupId:'jfree', artifactId:'jfreechart', version:'1.0.9']indirect = [groupId:'jfree', artifactId:'jcommon', version:'1.0.12']

// download artifactsmvn.dependencies(filesetId:'artifacts') { dependency(direct) }

// print out what we downloadedant.fileScanner { fileset(refid:'artifacts') }.each { println it }

// use AntUnit to confirm expected files were downloadeddef prefix = System.properties.'user.home' + '/.m2/repository'[direct, indirect].each { item ->

def (g, a, v) = [item.groupId, item.artifactId, item.version]antunit.assertFileExists(file:"$prefix/$g/$a/$v/$a-${v}.jar")

}

C:\Users\paulk\.m2\repository\jfree\jcommon\1.0.12\jcommon-1.0.12.jarC:\Users\paulk\.m2\repository\jfree\jfreechart\1.0.9\jfreechart-1.0.9.jar

Builds: Gant• lightweight façade on Groovy's AntBuilder

• target def’ns, pre-defined ‘ant’, operations on

predefined objects

includeTargets << gant.targets.CleancleanPattern << [ '**/*~' , '**/*.bak' ]cleanDirectory << 'build'

target ( stuff : 'A target to do some stuff.' ) {println ( 'Stuff' )depends ( clean )echo ( message : 'A default message from Ant.' )otherStuff ( )

}

target ( otherStuff : 'A target to do some other stuff' ) {println ( 'OtherStuff' )echo ( message : 'Another message from Ant.' )clean ( )

}

ESDC 2010 - 47

© A

SE

RT

20

06

-20

10

Topics

• Build Pain Points

• Build Tool Landscape

• Groovy Intro

• Ant & friends

Maven & friendsWriting plugins in Groovy

Building your Groovy project

• Gradle

• Other Tools

• More Info

ESDC 2010 - 48

© A

SE

RT

20

08

-20

10

What is Maven?

• Tool to assist automating (build) steps

ESDC 2010 - 49

© A

SE

RT

20

08

-20

10

Builds: GMaven...• Implementing Maven plugins has

never been Groovier!

• Groovy Mojos

– A Simple Groovy Mojo

• Building Plugins

– Project Definition

– Mojo Parameters

• Putting More Groove into your Mojo

– Using ant, Using fail()

• gmaven-archetype-mojo Archetype

• gmaven-plugin Packaging

ESDC 2010 - 50

© A

SE

RT

20

06

-20

10

...Builds: GMaven...

<plugin><groupId>org.codehaus.groovy.maven</groupId><artifactId>gmaven-plugin</artifactId><executions>

<execution><phase>generate-resources</phase><goals>

<goal>execute</goal></goals><configuration>

<source>if (project.packaging != 'pom') {

log.info('Copying some stuff...')def dir = new File(project.basedir, 'target/classes/META-INF'ant.mkdir(dir: dir)ant.copy(todir: dir) {

fileset(dir: project.basedir) {include(name: 'LICENSE.txt')include(name: 'NOTICE.txt')

}}

}</source>

</configuration></execution>

</executions></plugin> ESDC 2010 - 51

© A

SE

RT

20

06

-20

10

...Builds: GMaven...

<plugin><groupId>org.codehaus.mojo.groovy</groupId><artifactId>groovy-maven-plugin</artifactId><executions>

<execution><id>restart-weblogic</id><phase>pre-integration-test</phase><goals>

<goal>execute</goal></goals><configuration>

<source>${pom.basedir}/src/main/script/restartWeblogic.groovy</source>

</configuration></execution>

...

ESDC 2010 - 52

© A

SE

RT

20

06

-20

10

...Builds: GMaven...

def domainDir =project.properties['weblogic.domain.easyimage.dir']

stopWebLogic()copyFiles(domainDir)startWebLogic(domainDir)waitForWebLogicStartup()

def stopWebLogic() {weblogicServerDir = project.properties['weblogic.server.dir']adminUrl = project.properties['easyimage.weblogic.admin.t3']userName = 'weblogic'password = 'weblogic'ant.exec(executable: 'cmd', failonerror: 'false') {

arg(line: "/C ${wlsDir}/bin/setWLSEnv.cmd && java ..." ...}

...

ESDC 2010 - 53

© A

SE

RT

20

06

-20

10

...Builds: GMaven

ESDC 2010 - 54

© A

SE

RT

20

06

-20

10

Topics

• Build Pain Points

• Build Tool Landscape

• Groovy Intro

• Ant & friends

• Maven & friends

Gradle

• Other Tools

• More Info

ESDC 2010 - 55

© A

SE

RT

20

08

-20

10

What is Gradle?

• Tool to assist automating (build) steps

ESDC 2010 - 56

© A

SE

RT

20

08

-20

10

task hello << {println 'Hello world!'

}

task intro(dependsOn: hello) << {println "I'm Gradle"

}

> gradle -q intro

Hello world!

I'm Gradle

Gradle Features• A very flexible general purpose build tool like Ant

• Switchable, build-by-convention frameworks a la Maven. But

we never lock you in!

• Very powerful support for multi-project builds

• Very powerful dependency management (based on Apache

Ivy)

• Full support for your existing Maven or Ivy repository

infrastructure

• Support for transitive dependency management without the

need for remote repositories or pom.xml and ivy.xml files

• Ant tasks as first class citizens

• Groovy build scripts

• A rich domain model for describing your build

ESDC 2010 - 57

© A

SE

RT

20

06

-20

10

Gradle Examples

ESDC 2010 - 58

© A

SE

RT

20

06

-20

10

Revisiting our Preview Example

ESDC 2010 - 59

© A

SE

RT

20

08

-20

10

Switchingto IDE

Topics

• Build Pain Points

• Build Tool Landscape

• Groovy Intro

• Ant & friends

• Maven & friends

• Gradle

Other Tools

• More Info

ESDC 2010 - 60

© A

SE

RT

20

08

-20

10

Hudson• Gant Plugin — This plugin allows Hudson to invoke

Gant build script as the main build step

• Gradle Plugin — This plugin allows Hudson to invoke

Gradle build script as the main build step

• Grails Plugin — This plugin allows Hudson to invoke

Grails tasks as build steps

• Hudson CLI and GroovyShell

Source: http://weblogs.java.net/blog/kohsuke/archive/2009/05/hudson_cli_and.htmlESDC 2010 - 61

© A

SE

RT

20

06

-20

10

Hudson: Groovy Postbuild Plugin...

Source: http://wiki.hudson-ci.org/display/HUDSON/Groovy+Postbuild+Plugin

if (manager.logContains(".*uses or overrides a deprecated API.*")) {manager.addWarningBadge("Thou shalt not use deprecated methods.")manager.createSummary("warning.gif").appendText(

"<h1>You have been warned!</h1>", false, false, false, "red")manager.buildUnstable()

}

© A

SE

RT

20

06

-20

10

...Hudson: Groovy Postbuild Plugin

Adapted from: http://wiki.hudson-ci.org/display/HUDSON/Groovy+Postbuild+Plugin

regex = 'src/main/java/(.*).java:[^ ]* (.*) is Sun proprietary API and may be removed in a future release'map = [:]manager.build.logFile.eachMatch(regex) { full, ownClass, sunClass ->

map[ownClass.replaceAll("/", ".")] = sunClass}if (map) {

manager.createSummary("warning.gif").with {appendText("Classes using Sun proprietary API:<ul>", false)map.each { k, v ->

appendText("<li><b>$k</b> - uses $v</li>", false) }appendText("</ul>", false)

}}

© A

SE

RT

20

06

-20

10

Topics

• Build Pain Points

• Build Tool Landscape

• Groovy Intro

• Ant & friends

• Maven & friends

• Gradle

• Other Tools

More Info

ESDC 2010 - 64

© A

SE

RT

20

08

-20

10

More Information...

ESDC 2010 - 65

© A

SE

RT

20

08

-20

10

• Ant– http://ant.apache.org

– http://groovy.codehaus.org/The+groovy+Ant+Task

– http://groovy.codehaus.org/Using+Ant+from+Groovy

– http://groovy.codehaus.org/Using+Ant+Libraries+with

+AntBuilder

– http://gant.codehaus.org/

• Maven– http://maven.apache.org

– http://gmaven.codehaus.org

• Gradle– http://gradle.org

...More Information...

• Groovy Web sites– http://groovy.codehaus.org

– http://grails.codehaus.org

– http://pleac.sourceforge.net/pleac_groovy (many examples)

– http://www.asert.com.au/training/java/GV110.htm (workshop)

• Groovy User Mailing list– [email protected]

• Groovy Information portals– http://www.aboutgroovy.org

– http://www.groovyblogs.org

• Groovy Documentation (1000+ pages)– Getting Started Guide, User Guide, Developer Guide, Testing Guide,

Cookbook Examples, Advanced Usage Guide

© A

SE

RT

20

06

-20

10

ESDC 2010 - 66

GinA 2ed “ReGinA” is coming ...

© A

SE

RT

20

06

-20

10