Mais conteúdo relacionado
Semelhante a Make Your Builds More Groovy (20)
Make Your Builds More Groovy
- 1. © ASERT 2008-2010
Make Your Builds More Groovy
Dr Paul King
paulk@asert.com.au
@paulk_asert
ASERT, Australia
ESDC 2010 - 1
- 2. Topics
Build Pain Points
• Build Tool Landscape
• Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
• Gradle
• Other Tools
• More Info
ESDC 2010 - 2
- 3. 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
–
© ASERT 2008-2010
Many manual steps
– Environment fragile
• different machines, CI vs IDE, dev vs prod vs test
ESDC 2010 - 3
- 4. ...Build Pain Points...
• Require powerful features
– Dependency management
– Version management
– Polyglot compilation
– Artifact production and manipulation (jar, war, ...)
– Templating (generation of boilerplate text files)
© ASERT 2008-2010
– Multifacted testing
– Reporting
– Quality control (Metrics, code quality, static analysis)
– Property management
– Infinitely(?) extensible
ESDC 2010 - 4
- 5. ...Build Pain Points
• Useful characteristics
– Tool friendly
– Cross platform
– IDE support, CI support
– Refactorable
– Testable
© ASERT 2008-2010
– Minimal noise (DSL like)
– Easy to extend
– Conventions
– Good documentation
– Polyglot friendly
ESDC 2010 - 5
- 6. Topics
• Build Pain Points
Build Tool Landscape
• Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
• Gradle
• Other Tools
• More Info
ESDC 2010 - 6
- 7. 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
© ASERT 2008-2010
– 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
- 8. Pros/Cons of Traditional Tools
• Ant • Maven
– Flexible (supports any – Opinionated about
convention) conventions
– Easy to extend • Mostly a good thing
– Wealth of useful tasks – Mostly declarative
– Well documented • XML != concise DSL
– Numerous plugins
© ASERT 2008-2010
– Partially declarative but
some scope for – Some easy extension
procedural instructions points but some more
• XML != prog. language difficult options
– Lifecycle is hand-crafted • Some things beyond
some teams
in your build file
– Structured lifecycle
– Can use Ivy or Maven Ant
tasks for dependency
management
ESDC 2010 - 8
- 9. Enhancing Traditional Tools
• Ant + Groovy • Maven + Groovy
– Easy to write the – Easier to extend
procedural pieces – More concise syntax
– Easier to refactor – Some scope for
– Easier to test refactoring
– Ease of creating a build
© ASERT 2008-2010
DSL
– More concise
– Better interaction with • Gradle
Java – Take the best of both
– No impedence worlds and combine
mismatch with them
developers
ESDC 2010 - 9
- 11. ...A Preview Example...
StringUtils: Vanilla Ant + Ivy
<project name="StringUtilsBuild" default="package" <?xml version="1.0" encoding="ISO-8859-1"?>
xmlns:ivy="antlib:org.apache.ivy.ant" xmlns="antlib:org.apache.tools.ant">
<target name="clean">
<ivy-module version="1.0">
<delete dir="target"/> <info organisation="org" module="groovycookbook" />
<delete dir="lib"/> <dependencies>
</target> <dependency name="junit" rev="4.7" />
<target name="compile" depends="-init-ivy"> </dependencies>
<mkdir dir="target/classes"/> </ivy-module>
<javac srcdir="src/main"
destdir="target/classes"/>
</target>
<target name="compileTest" depends="compile">
<mkdir dir="target/test-classes"/> <ivysettings>
<javac srcdir="src/test" <settings defaultResolver="chained"/>
destdir="target/test-classes"> <resolvers>
<classpath> <chain name="chained" returnFirst="true">
<pathelement location="target/classes"/> <ibiblio name="ibiblio" />
<fileset dir="lib" includes="*.jar"/>
<url name="ibiblio-mirror">
</classpath>
</javac> <artifact
</target> pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/
© ASERT 2008-2010
[module]/[branch]/[revision]/[branch]-[revision].[ext]" />
<target name="test" depends="compileTest"> </url>
<mkdir dir="target/test-reports"/> </chain>
<junit printsummary="yes" fork="yes" haltonfailure="yes"> </resolvers>
<classpath>
</ivysettings>
<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>
ESDC 2010 - 11
- 12. ...A Preview Example...
StringUtils: Groovy's AntBuilder
...
import static groovy.xml.NamespaceBuilder.newInstance as namespace
def test() {
ant = new AntBuilder() compileTest()
clean() ant.mkdir dir: 'target/test-reports'
doPackage() ant.junit(printsummary: 'yes', haltonfailure: 'yes', fork: 'yes') {
classpath {
def doPackage() { pathelement location: 'target/classes'
test() pathelement location: 'target/test-classes'
ant.jar destfile: 'target/stringutils-1.0-SNAPSHOT.jar', fileset dir: 'lib', includes: '*.jar'
basedir: 'target/classes' }
} formatter type: 'plain'
formatter type: 'xml'
private dependencies() { batchtest(todir: 'target/test-reports', fork: 'yes') {
def ivy_version = '2.1.0-rc2' fileset dir: 'target/test-classes'
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',
© ASERT 2008-2010
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() <?xml version="1.0" encoding="ISO-8859-1"?>
} <ivy-module version="1.0">
<info organisation="org" module="groovycookbook" />
def clean() { <dependencies>
ant.delete dir: 'target'
ant.delete dir: 'lib'
<dependency name="junit" rev="4.7" />
} </dependencies>
</ivy-module>
def compile() {
dependencies()
ant.mkdir dir: 'target/classes'
ant.javac destdir: 'target/classes', srcdir: 'src/main', <ivysettings>
includeantruntime: false <settings defaultResolver="chained"/>
} <resolvers>
<chain name="chained" returnFirst="true">
def compileTest() { <ibiblio name="ibiblio" />
compile() <url name="ibiblio-mirror">
ant.mkdir dir: 'target/test-classes' <artifact
ant.javac(destdir: 'target/test-classes', srcdir: 'src/test', pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/
includeantruntime: false) { [module]/[branch]/[revision]/[branch]-[revision].[ext]" />
classpath { </url>
pathelement location: 'target/classes' </chain>
fileset dir: 'lib', includes: '*.jar' </resolvers>
} </ivysettings>
}
}
...
ESDC 2010 - 12
- 13. ...A Preview Example...
StringUtils: Gant
...
import static groovy.xml.NamespaceBuilder.newInstance as namespace
target(test: '') {
target('package': '') { depends 'compileTest'
depends 'test' mkdir dir: 'target/test-reports'
jar destfile: 'target/stringutils-1.0-SNAPSHOT.jar', junit(printsummary: 'yes', haltonfailure: 'yes', fork: 'yes') {
basedir: 'target/classes' classpath {
} pathelement location: 'target/classes'
pathelement location: 'target/test-classes'
target('-download-ivy': '') { fileset dir: 'lib', includes: '*.jar'
def ivy_version = '2.1.0-rc2' }
def repo = 'http://repo2.maven.org/maven2' formatter type: 'plain'
mkdir dir: 'lib' formatter type: 'xml'
get dest: 'lib/ivy.jar', batchtest(todir: 'target/test-reports', fork: 'yes') {
usetimestamp: 'true', fileset dir: 'target/test-classes'
src: "$repo/org/apache/ivy/ivy/$ivy_version/ivy-${ivy_version}.jar" }
} }
}
target(clean: '') {
delete dir: 'target' setDefaultTarget 'package'
delete dir: 'lib'
© ASERT 2008-2010
}
target(compile: '') {
depends '-init-ivy'
mkdir dir: 'target/classes' <?xml version="1.0" encoding="ISO-8859-1"?>
javac destdir: 'target/classes', srcdir: 'src/main' <ivy-module version="1.0">
} <info organisation="org" module="groovycookbook" />
<dependencies>
target('-init-ivy': '') {
depends '-download-ivy'
<dependency name="junit" rev="4.7" />
taskdef classpath: 'lib/ivy.jar', </dependencies>
uri: 'antlib:org.apache.ivy.ant', </ivy-module>
resource: 'org/apache/ivy/ant/antlib.xml'
def ivy = namespace(ant, 'antlib:org.apache.ivy.ant')
ivy.settings file: 'ivysettings.xml'
ivy.retrieve() <ivysettings>
} <settings defaultResolver="chained"/>
<resolvers>
target(compileTest: '') { <chain name="chained" returnFirst="true">
depends 'compile' <ibiblio name="ibiblio" />
mkdir dir: 'target/test-classes' <url name="ibiblio-mirror">
javac(destdir: 'target/test-classes', srcdir: 'src/test') { <artifact
classpath { pattern="http://mirrors.ibiblio.org/pub/mirrors/maven2/[organisation]/
pathelement location: 'target/classes' [module]/[branch]/[revision]/[branch]-[revision].[ext]" />
fileset dir: 'lib', includes: '*.jar' </url>
} </chain>
} </resolvers>
} </ivysettings>
...
ESDC 2010 - 13
- 14. ...A Preview Example...
StringUtils: Maven
<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>
© ASERT 2008-2010
<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>
ESDC 2010 - 14
- 15. ...A Preview Example...
StringUtils: Maven 3 Groovy Dialect
project {
modelVersion '4.0.0'
groupId 'org.groovycookbook.builds'
artifactId 'stringutils'
packaging 'jar'
version '1.0-SNAPSHOT'
name 'stringutils'
url 'http://maven.apache.org'
dependencies {
dependency 'junit:junit:4.7:test'
© ASERT 2008-2010
}
build {
plugins {
/* this is a java 1.5 project */
plugin {
groupId 'org.apache.maven.plugins'
artifactId 'maven-compiler-plugin'
configuration {
source '1.5'
target '1.5'
}
}
}
}
} ESDC 2010 - 15
- 16. ...A Preview Example
StringUtils: Gradle
usePlugin 'java'
sourceCompatibility = 1.5
version = '1.0-SNAPSHOT'
repositories {
© ASERT 2008-2010
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.7'
}
ESDC 2010 - 16
- 17. Topics
• Build Pain Points
• Build Tool Landscape
Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
• Gradle
• Other Tools
• More Info
ESDC 2010 - 17
- 18. 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.”
© ASERT 2008-2010
Groovy = Java – boiler plate code
+ optional dynamic typing
+ closures
+ domain specific languages
+ builders
+ metaprogramming
+ GDK library
ESDC 2010 - 18
- 19. Groovy Goodies Overview
• Fully object oriented
• Closures: reusable
and assignable
pieces of code
• Operators can be • GPath: efficient
overloaded
© ASERT 2008-2010
object navigation
• Multimethods • GroovyBeans
• Literal declaration for • grep and switch
lists (arrays), maps,
ranges and regular • Templates, builder,
expressions swing, Ant, markup,
XML, SQL, XML-RPC,
Scriptom, Grails,
tests, Mocks ESDC 2010 - 19
- 20. Growing Acceptance …
A slow and steady start but now gaining in
momentum, maturity and mindshare
Now free
- 22. … Growing Acceptance …
© ASERT 2008-2010
Groovy and Grails downloads:
70-90K per month and growing
ESDC 2010 - 22
- 23. … Growing Acceptance …
© ASERT 2008-2010
Source: http://www.micropoll.com/akira/mpresult/501697-116746
Source: http://www.grailspodcast.co
ESDC 2010 - 23
- 24. … Growing Acceptance …
© ASERT 2008-2010
http://www.jroller.com/scolebourne/entry/devoxx_2008_whitebo
http://www.java.net ESDC 2010 - 24
- 26. … Growing Acceptance …
What alternative JVM language are you using or intending to use
© ASERT 2008-2010
http://www.leonardoborges.com/writings
ESDC 2010 - 26
- 27. … Growing Acceptance …
© ASERT 2008-2010
http://it-republik.de/jaxenter/quickvote/results/1/poll/44 (translated using http://babelfish.yahoo
ESDC 2010 - 27
- 29. The Landscape of JVM Languages
mostly
dynamic
typing
© ASERT 2008-2010
Dynamic features call
for dynamic types Java bytecode calls
for static types
The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ platform.
ESDC 2010 - 29
- 30. Groovy Starter
System.out.println("Hello, World!"); // optional semicolon,
println 'Hello, World!' // System.out, brackets,
// main() method, class defn
def name = 'Guillaume' // dynamic typing
println "$name, I'll get the car." // GString
String longer = """${name}, the car
is in the next row.""" // multi-line string
// with static typing
© ASERT 2008-2010
assert 0.5 == 1/2 // BigDecimal equals()
def printSize(obj) { // optional duck typing
print obj?.size() // safe dereferencing
}
def pets = ['ant', 'bee', 'cat'] // native list syntax
pets.each { pet -> // closure support
assert pet < 'dog' // overloading '<' on String
} // or: for (pet in pets)...
ESDC 2010 - 30
- 31. A Better Java...
import java.util.List;
import java.util.ArrayList;
class Erase {
private List removeLongerThan(List strings, int length) { This code
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) { is valid
String s = (String) strings.get(i);
if (s.length() <= length) { Java and
}
result.add(s); valid Groovy
}
return result;
© ASERT 2008-2010
}
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(); Based on an
List shortNames = e.removeLongerThan(names, 3);
System.out.println(shortNames.size()); example by
for (int i = 0; i < shortNames.size(); i++) { Jim Weirich
String s = (String) shortNames.get(i);
System.out.println(s); & Ted Leung
}
}
}
ESDC 2010 - 31
- 32. ...A Better Java...
import java.util.List;
import java.util.ArrayList;
class Erase {
private List removeLongerThan(List strings, int length) { Do the
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) { semicolons
String s = (String) strings.get(i);
if (s.length() <= length) { add anything?
}
result.add(s); And shouldn‟t
} we us more
return result;
© ASERT 2008-2010
} modern list
public static void main(String[] args) {
List names = new ArrayList(); notation?
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
Why not
System.out.println(names); import common
Erase e = new Erase();
List shortNames = e.removeLongerThan(names, 3); libraries?
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
ESDC 2010 - 32
- 33. ...A Better Java...
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()
© ASERT 2008-2010
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)
}
}
}
ESDC 2010 - 33
- 34. ...A Better Java...
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) Do we need
}
} the static types?
}
return result Must we always
have a main
public static void main(String[] args) {
List names = new ArrayList() method and
© ASERT 2008-2010
names.add("Ted"); names.add("Fred")
names.add("Jed"); names.add("Ned") class definition?
System.out.println(names)
Erase e = new Erase()
How about
List shortNames = e.removeLongerThan(names, 3) improved
System.out.println(shortNames.size())
for (String s in shortNames) { consistency?
System.out.println(s)
}
}
}
ESDC 2010 - 34
- 35. ...A Better Java...
def removeLongerThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() <= length) {
result.add(s)
}
}
return result
}
© ASERT 2008-2010
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)
}
ESDC 2010 - 35
- 36. ...A Better Java...
def removeLongerThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() <= length) {
result.add(s) Shouldn‟t we
}
} have special
return result notation for lists?
}
And special
© ASERT 2008-2010
names = new ArrayList() facilities for
names.add("Ted")
names.add("Fred")
list processing?
names.add("Jed") Is „return‟
names.add("Ned") needed at end?
System.out.println(names)
shortNames = removeLongerThan(names, 3)
System.out.println(shortNames.size())
for (s in shortNames) {
System.out.println(s)
}
ESDC 2010 - 36
- 37. ...A Better Java...
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) }
© ASERT 2008-2010
ESDC 2010 - 37
- 38. ...A Better Java...
def removeLongerThan(strings, length) {
strings.findAll{ it.size() <= length }
}
Is the method
names = ["Ted", "Fred", "Jed", "Ned"] now needed?
System.out.println(names)
shortNames = removeLongerThan(names, 3) Easier ways to
System.out.println(shortNames.size()) use common
shortNames.each{ System.out.println(s) }
methods?
© ASERT 2008-2010
Are brackets
required here?
ESDC 2010 - 38
- 39. ...A Better Java...
names = ["Ted", "Fred", "Jed", "Ned"]
println names
shortNames = names.findAll{ it.size() <= 3 }
println shortNames.size()
shortNames.each{ println it }
© ASERT 2008-2010
ESDC 2010 - 39
- 40. ...A Better Java
names = ["Ted", "Fred", "Jed", "Ned"]
println names
shortNames = names.findAll{ it.size() <= 3 }
println shortNames.size()
shortNames.each{ println it }
© ASERT 2008-2010
[Ted, Fred, Jed, Ned]
3
Ted
Jed
Ned
ESDC 2010 - 40
- 41. Topics
• Build Pain Points
• Build Tool Landscape
• Groovy Intro
Ant & friends
Calling Groovy from Ant
© ASERT 2008-2010
Calling Ant from Groovy
Gant
• Maven & friends
• Gradle
• Other Tools
• More Info
ESDC 2010 - 41
- 42. What is Ant?
• Tool to assist automating (build) steps
<project name="MyProject" default="dist" basedir=".">
<property name="src" location="src"/>
<property name="build" location="build"/>
© ASERT 2008-2010
<target name="init">
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init"
description="compile the source">
<javac srcdir="${src}" destdir="${build}"/>
</target>
</project>
ESDC 2010 - 42
- 43. Groovy from Ant
• Need groovy jar on your Ant classpath
<taskdef name="groovy"
classname="org.codehaus.groovy.ant.Groovy"
classpathref="my.classpath"/>
© ASERT 2006-2010
<target name="printXmlFileNamesFromJar">
<zipfileset id="found" src="foobar.jar"
includes="**/*.xml"/>
<groovy>
project.references.found.each {
println it.name
}
</groovy>
</target>
ESDC 2010 - 43
- 44. 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}"
© ASERT 2006-2010
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 - 44
- 45. AntBuilder...
def ant = new AntBuilder()
ant.echo("hello") // let's just call one task
// create a block of Ant using the builder pattern
ant.with {
myDir = "target/AntTest/"
mkdir(dir: myDir)
© ASERT 2006-2010
copy(todir: myDir) {
fileset(dir: "src/test") {
include(name: "**/*.groovy")
}
}
echo("done")
}
// now let's do some normal Groovy again
file = new File("target/test/AntTest.groovy")
assert file.exists()
Needs ant.jar on your Groovy classpath ESDC 2010 - 45
- 46. ...AntBuilder
• Built-in
new AntBuilder().with {
echo(file:'Temp.java', '''
class Temp {
public static void main(String[] args) {
System.out.println("Hello");
}
© ASERT 2006-2010
}
''')
javac(srcdir:'.', includes:'Temp.java', fork:'true')
java(classpath:'.', classname:'Temp', fork:'true')
echo('Done')
}
// =>
// [javac] Compiling 1 source file
// [java] Hello
// [echo] Done
ESDC 2010 - 46
- 47. Using AntLibs: Maven Ant Tasks & AntUnit
import static groovy.xml.NamespaceBuilder.newInstance as namespace
def 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 artifacts
mvn.dependencies(filesetId:'artifacts') { dependency(direct) }
© ASERT 2006-2010
// print out what we downloaded
ant.fileScanner { fileset(refid:'artifacts') }.each { println it }
// use AntUnit to confirm expected files were downloaded
def 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:Userspaulk.m2repositoryjfreejcommon1.0.12jcommon-1.0.12.jar
C:Userspaulk.m2repositoryjfreejfreechart1.0.9jfreechart-1.0.9.jar
ESDC 2010 - 47
- 48. Builds: Gant
• lightweight façade on Groovy's AntBuilder
• target def’ns, pre-defined ‘ant’, operations on
predefined objects
includeTargets << gant.targets.Clean
cleanPattern << [ '**/*~' , '**/*.bak' ]
cleanDirectory << 'build'
© ASERT 2006-2010
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 - 48
- 49. Topics
• Build Pain Points
• Build Tool Landscape
• Groovy Intro
• Ant & friends
Maven & friends
© ASERT 2008-2010
Writing plugins in Groovy
Building your Groovy project
• Gradle
• Other Tools
• More Info
ESDC 2010 - 49
- 50. What is Maven?
• Tool to assist automating (build) steps
© ASERT 2008-2010
ESDC 2010 - 50
- 51. Builds: GMaven...
• Implementing Maven plugins has
never been Groovier!
• Groovy Mojos
– A Simple Groovy Mojo
• Building Plugins
– Project Definition
© ASERT 2006-2010
– Mojo Parameters
• Putting More Groove into your Mojo
– Using ant, Using fail()
• gmaven-archetype-mojo Archetype
• gmaven-plugin Packaging
ESDC 2010 - 51
- 52. ...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>
© ASERT 2006-2010
<source>
if (project.packaging != 'pom') {
log.info('Copying some stuff...')
def dir = new File(project.basedir, 'target/classes/META-IN
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 - 52
- 53. ...Builds: GMaven...
<plugin>
<groupId>org.codehaus.mojo.groovy</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<executions>
<execution>
<id>restart-weblogic</id>
© ASERT 2006-2010
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
${pom.basedir}/src/main/script/restartWeblogic.groovy
</source>
</configuration>
</execution>
...
ESDC 2010 - 53
- 54. ...Builds: GMaven...
def domainDir =
project.properties['weblogic.domain.easyimage.dir']
stopWebLogic()
copyFiles(domainDir)
startWebLogic(domainDir)
© ASERT 2006-2010
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 - 54
- 56. Topics
• Build Pain Points
• Build Tool Landscape
• Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
Gradle
• Other Tools
• More Info
ESDC 2010 - 56
- 57. What is Gradle?
• Tool to assist automating (build) steps
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
© ASERT 2008-2010
println "I'm Gradle"
}
> gradle -q intro
Hello world!
I'm Gradle
ESDC 2010 - 57
- 58. 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
© ASERT 2006-2010
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 - 58
- 61. Topics
• Build Pain Points
• Build Tool Landscape
• Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
• Gradle
Other Tools
• More Info
ESDC 2010 - 61
- 62. 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
© ASERT 2006-2010
• Hudson CLI and GroovyShell
Source: http://weblogs.java.net/blog/kohsuke/archive/2009/05/hudson_cli_and.html ESDC 2010 - 62
- 63. 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()
}
© ASERT 2006-2010
Source: http://wiki.hudson-ci.org/display/HUDSON/Groovy+Postbuild+Plugin
- 64. ...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)
© ASERT 2006-2010
}
appendText("</ul>", false)
}
}
Adapted from: http://wiki.hudson-ci.org/display/HUDSON/Groovy+Postbuild+Plugin
- 65. Topics
• Build Pain Points
• Build Tool Landscape
• Groovy Intro
• Ant & friends
• Maven & friends
© ASERT 2008-2010
• Gradle
• Other Tools
More Info
ESDC 2010 - 65
- 66. More Information...
• 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
© ASERT 2008-2010
– http://gant.codehaus.org/
• Maven
– http://maven.apache.org
– http://gmaven.codehaus.org
• Gradle
– http://gradle.org
ESDC 2010 - 66
- 67. ...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
– user@groovy.codehaus.org
© ASERT 2006-2010
• 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
ESDC 2010 - 67