Groovy Update, Groovy Ecosystem, and Gaelyk -- Devoxx 2010 -- Guillaume Laforge
make builds groovy
-
Upload
guest88884d -
Category
Technology
-
view
2.467 -
download
2
description
Transcript of make builds groovy
© A
SE
RT
20
08
-20
10
Make Your Builds More Groovy
Dr Paul King
@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 - 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 - 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)
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
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
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
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