SlideShare a Scribd company logo
What makes
Groovy groovy?
Guillaume Laforge
@glaforge
© 2013 Guillaume Laforge. All rights reserved. Do not distribute without permission.
Guillaume
Laforge
Groovy project lead
at
.
@glaforge
http://glaforge.appspot.com
Les Cast
Codeurs
What makes groovy groovy   codeurs en seine - 2013 - light size
1
t
r
a
P

The Groovy
vision
What makes groovy groovy   codeurs en seine - 2013 - light size
Simplify the life of
(Java) developers
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
Great for
scripting
Great for
scripting

Fit for DomainSpecific Languages
Great for
scripting

Fit for DomainSpecific Languages

Most seamless integration &
interoperability wih java!
What makes groovy groovy   codeurs en seine - 2013 - light size
It’s so easy
to learn!
Groovy as a
Java superset

It’s so easy
to learn!
What makes groovy groovy   codeurs en seine - 2013 - light size
class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
What makes groovy groovy   codeurs en seine - 2013 - light size
As safe and fast as Java with
static type checking & compilation
As safe and fast as Java with
static type checking & compilation
What makes groovy groovy   codeurs en seine - 2013 - light size
new!MarkupBuilder().html!{
!!!!head!{
!!!!!!!!title!"The!Script!Bowl"
!!!!}
!!!!body!{
!!!!!!!!div(class:!"banner")!{
!!!!!!!!!!!!p!"Groovy!rocks!"
!!!!!!!!}
!!!!}
}
What makes groovy groovy   codeurs en seine - 2013 - light size
move!forward!at!3.km/h
Expressive,
Concise,
Readable
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
Speaking of conciseness...
A full Spring app in the span of a tweet!
@RestController
class!App!{
!!!!@RequestMapping("/")
!!!!String!home()!{!"Hello!World!"!}
}
• SmartThings
• Carriots

Services

• European Patent
Office
• Amadeus
IoT

Financial

• Crédit Suisse
• JPMorgan
• Fanny Mae
• Mutual of Omaha
• Hypoport
20

• Energy Transfer
• National Cancer Inst.
• IRSN

Internet

• Netflix
• LinkedIn
• Google

Technology

Who’s using Groovy?
2
t
r
a
P

Cool Groovy
gems
What makes groovy groovy   codeurs en seine - 2013 - light size
Most Java code is also
valid Groovy code!
Most Java code is also
valid Groovy code!

Any Java developer is a
Groovy developer!
What makes groovy groovy   codeurs en seine - 2013 - light size
Flat learning
curve
Flat learning
curve

Easy to learn
Scripts versus Classes
public!class!Main!{
!!!!public!static!void!main(String[]!args)!{
!!!!!!!!System.out.println("Hello");
!!!!}
}

vs
24
Scripts versus Classes
public!class!Main!{
!!!!public!static!void!main(String[]!args)!{
!!!!!!!!System.out.println("Hello");
!!!!}
}

vs
println!"Hello"
24
Optional
Semicolons

Optional
Semicolons
Parentheses

Optional
Semicolons
Parentheses

Optional
return keyword
Semicolons
Parentheses

Optional
return keyword

public keyword
Semicolons
Parentheses

Optional
Typing!
return keyword

public keyword
Optional...
public!class!Greeter!{
!!!!private!String!owner;
!!!!public!String!getOwner()!{
!!!!!!!!return!owner;
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner;
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner;
!!!!}
}
Greeter!greeter!=!new!Greeter();
greeter.setOwner("Guillaume");
System.out.println(greeter.greet("Marion"));
26
Optional...

Semicolons

public!class!Greeter!{
!!!!private!String!owner;
!!!!public!String!getOwner()!{
!!!!!!!!return!owner;
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner;
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner;
!!!!}
}
Greeter!greeter!=!new!Greeter();
greeter.setOwner("Guillaume");
System.out.println(greeter.greet("Marion"));
26
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!return!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner("Guillaume")
System.out.println(greeter.greet("Marion"))
27
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!return!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner("Guillaume")
System.out.println(greeter.greet("Marion"))
28
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!return!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}

Parentheses

Greeter!greeter!=!new!Greeter()
greeter.setOwner("Guillaume")
System.out.println(greeter.greet("Marion"))
28
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!return!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
29
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!return!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}

return keyword

!!!!public*String!greet(String!name)!{
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
29
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
30
Optional...
public!class!Greeter!{
!!!!private!String!owner
!!!!public!String!getOwner()!{
!!!!!!!!******!owner
!!!!}

public keyword

!!!!public!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!public*String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
30
Optional...
******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
31
Optional...
******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}

optional typing

Greeter!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
31
Optional...
******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
32
Optional...
******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}

handy println shortcut

def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
System.out.println!greeter.greet("Marion")
32
Optional...
******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
33
Optional...

verbose Java properties!

******!class!Greeter!{
!!!!private!String!owner
!!!!******!String!getOwner()!{
!!!!!!!!******!owner
!!!!}
!!!!******!void!setOwner(String!owner)!{
!!!!!!!!this.owner!=!owner
!!!!}
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
33
Optional...
******!class!Greeter!{
!!!!*******!String!owner

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
34
Optional...
******!class!Greeter!{
!!!!*******!String!owner

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}

Property notation

def!!!!!greeter!=!new!Greeter()
greeter.setOwner!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
34
Optional...
******!class!Greeter!{
!!!!*******!String!owner

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.owner!!!!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
35
Optional...
******!class!Greeter!{
!!!!*******!String!owner

Named argument
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
constructor
!!!!}
}
def!!!!!greeter!=!new!Greeter()
greeter.owner!!!!"Guillaume"
!!!!!!!!!!!println!greeter.greet("Marion")
35
Optional...
******!class!Greeter!{
!!!!*******!String!owner

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter(owner:!"Guillaume")
!!!!!!!!!!!println!greeter.greet("Marion")
36
Optional...
******!class!Greeter!{
!!!!*******!String!owner

Interpolated strings!
(aka GStrings)
!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!"!+!name!+!",!I!am!"!+!owner
!!!!}
}
def!!!!!greeter!=!new!Greeter(owner:!"Guillaume")
!!!!!!!!!!!println!greeter.greet("Marion")
36
Optional...
******!class!Greeter!{
!!!!*******!String!owner

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!${name},!I!am!${owner}"
!!!!}
}
def!!!!!greeter!=!new!Greeter(owner:!"Guillaume")
!!!!!!!!!!!println!greeter.greet("Marion")
37
Optional...
******!class!Greeter!{
!!!!*******!String!owner

Let’s reformat that
mess of whitespace!

!!!!*******String!greet(String!name)!{
!!!!!!!!******!"Hello!${name},!I!am!${owner}"
!!!!}
}
def!!!!!greeter!=!new!Greeter(owner:!"Guillaume")
!!!!!!!!!!!println!greeter.greet("Marion")
37
Optional...
class!Greeter!{
***!String!owner
****String!greet(String!name)!{
******!"Hello!${name},!I!am!${owner}"
!!!!}
}
def!greeter!=!new!Greeter(owner:!"Guillaume")
println!greeter.greet("Marion")

38
Optional...
public!class!Greeter!{
!!!!private!String!owner;
!!!!public!String!getOwner()!{
class!Greeter!{
!!!!!!!!return!owner;
***!String!owner
!!!!}
****String!greet(String!name)!{
!!!!public!void!setOwner(String!owner)!{
******!"Hello!${name},!I!am!${owner}"
!!!!!!!!this.owner!=!owner;
!!!!}
!!!!}}
!!!!public*String!greet(String!name)!{
def!greeter!=!new!Greeter(owner:!"Guillaume")
!!!!!!!!return!"Hello!"!+!name!+!",!I!am!"!+!owner;
!!!!}println!greeter.greet("Marion")
}
Greeter!greeter!=!new!Greeter();
greeter.setOwner("Guillaume");
System.out.println(greeter.greet("Marion"));
38
Optional...
class!Greeter!{
***!String!owner
****String!greet(String!name)!{
******!"Hello!${name},!I!am!${owner}"
!!!!}
}
def!greeter!=!new!Greeter(owner:!"Guillaume")
println!greeter.greet("Marion")

38
Native syntax constructs
• Closures
• Lists
• Maps
• Regular expressions
• Ranges
39
Closures
• Functions as first-class citizen of the language

40
Lists
def!list!=!['a',!'b',!'c']
list!<<!'d'
assert!list.contains('d')
assert!list.findAll!{!it.startsWith!'a'!}.size()!==!1
assert!list.collect!{!it.toUpperCase()!}!==!['A',!'B',!'C',!'D']
assert!list.inject('')!{!a,!b!c>!a!+!b!}!==!'abcd'

41
Lists

List definition

def!list!=!['a',!'b',!'c']
list!<<!'d'
assert!list.contains('d')
assert!list.findAll!{!it.startsWith!'a'!}.size()!==!1
assert!list.collect!{!it.toUpperCase()!}!==!['A',!'B',!'C',!'D']
assert!list.inject('')!{!a,!b!c>!a!+!b!}!==!'abcd'

41
Lists

List definition

def!list!=!['a',!'b',!'c']

Append an element
(operator overloading)

list!<<!'d'
assert!list.contains('d')
assert!list.findAll!{!it.startsWith!'a'!}.size()!==!1
assert!list.collect!{!it.toUpperCase()!}!==!['A',!'B',!'C',!'D']
assert!list.inject('')!{!a,!b!c>!a!+!b!}!==!'abcd'

41
Lists

List definition

def!list!=!['a',!'b',!'c']

Append an element
(operator overloading)

list!<<!'d'
assert!list.contains('d')
assert!list.findAll!{!it.startsWith!'a'!}.size()!==!1
assert!list.collect!{!it.toUpperCase()!}!==!['A',!'B',!'C',!'D']
assert!list.inject('')!{!a,!b!c>!a!+!b!}!==!'abcd'

Functional-style
map / filter / reduce
with closures
41
Maps
def!map!=![name:!'Guillaume',!age:!36]
map.daughters!=!['Marion',!'Erine']
assert!map['daughters'].contains('Marion')

42
Maps

Map definition

def!map!=![name:!'Guillaume',!age:!36]
map.daughters!=!['Marion',!'Erine']
assert!map['daughters'].contains('Marion')

42
Maps

Map definition

def!map!=![name:!'Guillaume',!age:!36]
map.daughters!=!['Marion',!'Erine']
assert!map['daughters'].contains('Marion')

Indexed access

42
Maps

Map definition

def!map!=![name:!'Guillaume',!age:!36]
map.daughters!=!['Marion',!'Erine']
assert!map['daughters'].contains('Marion')

Property
notation access

42

Indexed access
Regular expressions
def!pattern!=!~/.*foo.*/
assert!"Alibaba"!==~!/.*(ba){2}/
def!matcher!=!"Superman"!=~!/([AcZ][acz]+)man/
assert!matcher[0][0]!==!'Superman'
assert!matcher[0][1]!==!'Super'
'75001!Paris'.find(/(d{5})s(w)+/)!{!match,!cp,!town!c>
!!!!println!"The!Zip!code!of!${town}!is!${cp}"
}

43
Regular expressions
Pattern
def!pattern!=!~/.*foo.*/
assert!"Alibaba"!==~!/.*(ba){2}/
def!matcher!=!"Superman"!=~!/([AcZ][acz]+)man/
assert!matcher[0][0]!==!'Superman'
assert!matcher[0][1]!==!'Super'
'75001!Paris'.find(/(d{5})s(w)+/)!{!match,!cp,!town!c>
!!!!println!"The!Zip!code!of!${town}!is!${cp}"
}

43
Regular expressions
Pattern

Match

def!pattern!=!~/.*foo.*/
assert!"Alibaba"!==~!/.*(ba){2}/
def!matcher!=!"Superman"!=~!/([AcZ][acz]+)man/
assert!matcher[0][0]!==!'Superman'
assert!matcher[0][1]!==!'Super'
'75001!Paris'.find(/(d{5})s(w)+/)!{!match,!cp,!town!c>
!!!!println!"The!Zip!code!of!${town}!is!${cp}"
}

43
Regular expressions
Pattern

Match

def!pattern!=!~/.*foo.*/
assert!"Alibaba"!==~!/.*(ba){2}/

Find

def!matcher!=!"Superman"!=~!/([AcZ][acz]+)man/
assert!matcher[0][0]!==!'Superman'
assert!matcher[0][1]!==!'Super'
'75001!Paris'.find(/(d{5})s(w)+/)!{!match,!cp,!town!c>
!!!!println!"The!Zip!code!of!${town}!is!${cp}"
}

43
Regular expressions
Pattern

Match

def!pattern!=!~/.*foo.*/
assert!"Alibaba"!==~!/.*(ba){2}/

Find

def!matcher!=!"Superman"!=~!/([AcZ][acz]+)man/
assert!matcher[0][0]!==!'Superman'
assert!matcher[0][1]!==!'Super'
'75001!Paris'.find(/(d{5})s(w)+/)!{!match,!cp,!town!c>
!!!!println!"The!Zip!code!of!${town}!is!${cp}"
}

Nice way to decompose the matched regions
43
Ranges
def!range!=!'a'..'z'
assert!range.contains('m')
assert!range.contains('z')
def!exclusive!=!1..<10
assert!!exclusive.contains(10)
def!reverse!=!10..0
assert!reverse[0]!==!10
assert!reverse[c1]!==!0
44
Ranges

Range

def!range!=!'a'..'z'
assert!range.contains('m')
assert!range.contains('z')
def!exclusive!=!1..<10
assert!!exclusive.contains(10)
def!reverse!=!10..0
assert!reverse[0]!==!10
assert!reverse[c1]!==!0
44
Ranges

Range

def!range!=!'a'..'z'
assert!range.contains('m')
assert!range.contains('z')
def!exclusive!=!1..<10

Excluded upper bound

assert!!exclusive.contains(10)
def!reverse!=!10..0
assert!reverse[0]!==!10
assert!reverse[c1]!==!0
44
Ranges

Range

def!range!=!'a'..'z'
assert!range.contains('m')
assert!range.contains('z')
def!exclusive!=!1..<10

Excluded upper bound

assert!!exclusive.contains(10)
def!reverse!=!10..0
assert!reverse[0]!==!10
assert!reverse[c1]!==!0
44

Reverse range
Ranges

Range

def!range!=!'a'..'z'
assert!range.contains('m')
assert!range.contains('z')
def!exclusive!=!1..<10

Excluded upper bound

assert!!exclusive.contains(10)
def!reverse!=!10..0
assert!reverse[0]!==!10
assert!reverse[c1]!==!0
44

Reverse range
Negative index count
from the end
Strings, GStrings, multiline strings

def!name!=!'Groovy'
def!tmpl!=!"""
!!!!Dear!Mr!${name},
!!!!You're!the!winner!of!the!lottery!
!!!!Yours!sincerly,
!!!!Dave
"""
assert!tmpl.toString().contains('Groovy')

45
Strings, GStrings, multiline strings
Plain java.lang.String
def!name!=!'Groovy'
def!tmpl!=!"""
!!!!Dear!Mr!${name},
!!!!You're!the!winner!of!the!lottery!
!!!!Yours!sincerly,
!!!!Dave
"""
assert!tmpl.toString().contains('Groovy')

45
Strings, GStrings, multiline strings
Plain java.lang.String
def!name!=!'Groovy'
Multiline string with
def!tmpl!=!"""
expression interpolation
!!!!Dear!Mr!${name},
!!!!You're!the!winner!of!the!lottery!
!!!!Yours!sincerly,
!!!!Dave
"""
assert!tmpl.toString().contains('Groovy')

45
Surprising numbers...

System.out.println(!2.0!c!1.1!);

46
Surprising numbers...

System.out.println(!2.0!c!1.1!);
0.8999999999999999

46
Surprising numbers...

System.out.println(!2.0!c!1.1!);
0.8999999999999999

46
Surprising numbers...

System.out.println(!3!/!2!);

47
Surprising numbers...

System.out.println(!3!/!2!);
1

47
Surprising numbers...

System.out.println(!3!/!2!);
1

47
BigDecimal by default!

assert!2.0!c!1.1!==!0.9
assert!3!/!2!==!1.5

48
BigDecimal by default!

assert!2.0!c!1.1!==!0.9
assert!3!/!2!==!1.5
One of the reasons why microbenchmarks sometimes showed
Groovy to be slow...
48
BigDecimal by default!

assert!2.0!c!1.1!==!0.9
assert!3!/!2!==!1.5
One of the reasons why microbenchmarks sometimes showed
Groovy to be slow...
48

But you can use doubles & floats
for performance, with ‘d’ or ‘f ’
suffixes or with explicit type
What makes groovy groovy   codeurs en seine - 2013 - light size
Powerful
switch / case
on steroids
Powerful
switch / case
on steroids

switch(obj)!{
!!!!case!123:!!!!!!!!!!!!!!!!!!"number!123";!!!!!!!!break
!!!!case!"abc":!!!!!!!!!!!!!!!!"string!abc";!!!!!!!!break
!!!!case!String:!!!!!!!!!!!!!!!"is!a!string";!!!!!!!break
!!!!case![1,!2,!3]:!!!!!!!!!!!!"contained!in!list";!break
!!!!case!~/.*o+.*/:!!!!!!!!!!!!"match!the!regex";!!!break
!!!!case!{!it.isUpperCase()!}:!"closure!criteria";!!break
****default:!"unknown"
}
Named arguments

move!obj,!x:!3,!y:!4

50
Named arguments

move!obj,!x:!3,!y:!4
Normal argument

50
Named arguments

move!obj,!x:!3,!y:!4
Normal argument

50

Named argument
Named arguments

move!obj,!x:!3,!y:!4
Normal argument
Calls:
move(Map m, Object)

50

Named argument
Command chains
• Ability to chain method calls
without parentheses and dots

51
Command chains
• Ability to chain method calls
without parentheses and dots

move!forward!at!3.km/h

51
Command chains
• Ability to chain method calls
without parentheses and dots

move!forward!at!3.km/h
Actually equivalent to:
move(forward).at(3.getKm().div(h))

51
Named arguments and command chains

check!that:!vodka!tastes!good

52
Named arguments and command chains

check!that:!vodka!tastes!good
Will call:
check(that: vodka).tastes(good)

52
Multiple assignment and destructuring
def!(a,!b)!=!['A',!'B']
(a,!b)!=![b,!a]
def!(int!i,!int!j)!=![1,!2]
def!geocode(String!place)!{
!!!!return![45.4,!2.3]
}
def!(la,!lo)!=!geocode("Paris")
assert!la!==!45.4!&&!lo!==!2.3
53
Multiple assignment and destructuring
def!(a,!b)!=!['A',!'B']
(a,!b)!=![b,!a]

Classic « swap »

def!(int!i,!int!j)!=![1,!2]
def!geocode(String!place)!{
!!!!return![45.4,!2.3]
}
def!(la,!lo)!=!geocode("Paris")
assert!la!==!45.4!&&!lo!==!2.3
53
Multiple assignment and destructuring
def!(a,!b)!=!['A',!'B']

With types

(a,!b)!=![b,!a]

Classic « swap »

def!(int!i,!int!j)!=![1,!2]
def!geocode(String!place)!{
!!!!return![45.4,!2.3]
}
def!(la,!lo)!=!geocode("Paris")
assert!la!==!45.4!&&!lo!==!2.3
53
Multiple assignment and destructuring
def!(a,!b)!=!['A',!'B']

With types

(a,!b)!=![b,!a]

Classic « swap »

def!(int!i,!int!j)!=![1,!2]

Method
returning a list

def!geocode(String!place)!{
!!!!return![45.4,!2.3]
}
def!(la,!lo)!=!geocode("Paris")
assert!la!==!45.4!&&!lo!==!2.3

53
Multiple assignment and destructuring
def!(a,!b)!=!['A',!'B']

With types

(a,!b)!=![b,!a]

Classic « swap »

def!(int!i,!int!j)!=![1,!2]

Method
returning a list

def!geocode(String!place)!{
!!!!return![45.4,!2.3]
}
Destructuring
def!(la,!lo)!=!geocode("Paris")
assert!la!==!45.4!&&!lo!==!2.3

53
Multiple assignment and destructuring
class!Point!{
!!!!double!x,!y
!!!!double!getAt(int!idx)!{
!!!!!!!!if!(idx!==!0)!x
!!!!!!!!else!if!(idx!==!1)!y
!!!!!!!!else!throw!new!Exception("Wrong!index")
!!!!}
}
def!(x,!y)!=!new!Point(x:!48.3,!y:!3.5)
assert!x!==!48.3!&&!y!==!3.5
54
Multiple assignment and destructuring
class!Point!{
!!!!double!x,!y

Method signature
convention: getAt(int)

!!!!double!getAt(int!idx)!{
!!!!!!!!if!(idx!==!0)!x
!!!!!!!!else!if!(idx!==!1)!y
!!!!!!!!else!throw!new!Exception("Wrong!index")
!!!!}
}
def!(x,!y)!=!new!Point(x:!48.3,!y:!3.5)
assert!x!==!48.3!&&!y!==!3.5
54
Multiple assignment and destructuring
class!Point!{
!!!!double!x,!y

Method signature
convention: getAt(int)

!!!!double!getAt(int!idx)!{
!!!!!!!!if!(idx!==!0)!x
!!!!!!!!else!if!(idx!==!1)!y
!!!!!!!!else!throw!new!Exception("Wrong!index")
!!!!}
}
Transparent destructuring
def!(x,!y)!=!new!Point(x:!48.3,!y:!3.5)
assert!x!==!48.3!&&!y!==!3.5
54
Builders and GPath expressions
import!groovy.xml.*
new!MarkupBuilder().html!{
!!!!head!{
!!!!!!!!title!"The!Script!Bowl"
!!!!}
!!!!body!{
!!!!!!!!div(class:!"banner")!{
!!!!!!!!!!!!p!"Groovy!won!"
!!!!!!!!}
!!!!}
}
55
Builders and GPath expressions
import!groovy.xml.*

Hierarchical data
representation

new!MarkupBuilder().html!{
!!!!head!{
!!!!!!!!title!"The!Script!Bowl"
!!!!}
!!!!body!{
!!!!!!!!div(class:!"banner")!{
!!!!!!!!!!!!p!"Groovy!won!"
!!!!!!!!}
!!!!}
}
55
Builders and GPath expressions
import!groovy.xml.*

Hierarchical data
representation

new!MarkupBuilder().html!{
!!!!head!{
!!!!!!!!title!"The!Script!Bowl"
!!!!}
!!!!body!{
!!!!!!!!div(class:!"banner")!{
!!!!!!!!!!!!p!"Groovy!won!"
!!!!!!!!}
Closure blocks delimiting
!!!!}
the structure
}
55
Builders and GPath expressions
import!groovy.xml.*

Hierarchical data
representation

new!MarkupBuilder().html!{
!!!!head!{
!!!!!!!!title!"The!Script!Bowl"
!!!!}
Attributes
!!!!body!{
!!!!!!!!div(class:!"banner")!{
!!!!!!!!!!!!p!"Groovy!won!"
!!!!!!!!}
Closure blocks delimiting
!!!!}
the structure
}
55
Power asserts
def!(a,!b,!c)!=![20,!30,!40]
assert!a!*!(b!c!1)!/!10!==!3!*!c!/!2!+!1

56
Power asserts
def!(a,!b,!c)!=![20,!30,!40]
assert!a!*!(b!c!1)!/!10!==!3!*!c!/!2!+!1
Assertion!failed:!
assert!a!*!(b!c!1)!/!10!==!3!*!c!/!2!+!1
!!!!!!!|!|!!|!|!!!!|!!!!|!!!!|!|!|!!!|
!!!!!!!|!580|!29!!!58!!!false|!|!60!!61
!!!!!!!20!!!30!!!!!!!!!!!!!!!|!40
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!120
! at!script1.run(script1t.groovy:4)
56
Null handling
• Groovy provides a more descriptive
NullPointerException than Java
• Safe navigation with ?.

57
What makes groovy groovy   codeurs en seine - 2013 - light size
The Truth,
the Groovy Truth!
The Truth,
the Groovy Truth!
And what if I could
customize the truth?
?:
?:
The Elvis
operator!
Towards Elvis...

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y
x!?!x!:!y

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y
x!?!x!:!y
x!?:!y

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y
x!?!x!:!y
x!?:!y

Null, empty, zerosized... false,
otherwise true!

60
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y
x!?!x!:!y
x!?:!y

Good old ternary
operator

60

Null, empty, zerosized... false,
otherwise true!
Towards Elvis...
def!(x,!y)!=!['MacBook!Pro',!'unknown']
if*(x!!=!null!&&!x.size()!>!0)!x!else!y
if*(x!&&!x.size())!x!else!y
if*(x)!x!else!y
x!?!x!:!y
x!?:!y

Elvis!

60

Good old ternary
operator

Null, empty, zerosized... false,
otherwise true!
AST transformations
• Abstract Syntax Tree
– in memory representation of your program
before being compiled into bytecode

• AST transformation == process of transforming
the AST of a program before it’s compiled
• Macro-like compiler hook!

61
Lots of AST transformations...
• Code generation
– @ToString, @EqualsAndHashCode, @Canonical,
@TupleConstructor, @InheritConstructors,
@Category, @IndexedProperty, @Lazy, @Newify

• Class design
– @Delegate, @Immutable, @Memoized,
@Singleton, @Mixin

• Logging
– @Log, @Log4j, @Log4j2, @Slf4j
62
Lots of AST transformations...
• Safer scripting
– @ConditionalInterrupt, @ThreadInterrupt,
@TimedInterupt

• Compiler directives
– @Field, @PackageScope, @AnnotationCollector,
@DelegatesTo, @TypeChecked,
@CompileStatic, @CompileDynamic

• Swing patterns
– @Bindable, @ListenerList, @Vetoable
63
Lots of AST transformations...
• Dependencies handling
– @Grab, @GrabConfig, @GrabExclude,
@GrabResolver

• Test assistance
– @NotYetImplemented, @ASTTest

64
Immutability
• Implement immutability
by the book
– final class
– tuple-style constructor
– private final backing fields
– defensive copying of collections
– equals() and hashCode() methods
– toString() method
– ...
65
Immutability
• Implement immutability
by the book
– final class
Can be error-prone to
– tuple-style constructor
write immutable
– private final backing fields
classes oneself!
– defensive copying of collections
– equals() and hashCode() methods
– toString() method
– ...
65
Immutability
• A Person class with

public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}

– a String name
– an int age

public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
return age + 31 * name.hashCode();
}
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (this == other) {
return true;
}
if (Person.class != other.getClass()) {
return false;
}
Person otherPerson = (Person)other;
if (!name.equals(otherPerson.getName()) {
return false;
}
if (age != otherPerson.getAge()) {
return false;
}
return true;
}
public String toString() {
return "Person(" + name + ", " + age + ")";
}
}

66
Immutability
• A Person class with

Damn
verbose
Java!

public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}

– a String name
– an int age

public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
return age + 31 * name.hashCode();
}
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (this == other) {
return true;
}
if (Person.class != other.getClass()) {
return false;
}
Person otherPerson = (Person)other;
if (!name.equals(otherPerson.getName()) {
return false;
}
if (age != otherPerson.getAge()) {
return false;
}
return true;
}
public String toString() {
return "Person(" + name + ", " + age + ")";
}
}

66
Immutability
• A Person class with

Damn
verbose
Java!

public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}

– a String name
– an int age

public String getName() {
return name;
}
public int getAge() {
return age;
}
public int hashCode() {
return age + 31 * name.hashCode();
}
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (this == other) {
return true;
}
if (Person.class != other.getClass()) {
return false;
}
Person otherPerson = (Person)other;
if (!name.equals(otherPerson.getName()) {
return false;
}
if (age != otherPerson.getAge()) {
return false;
}
return true;
}

Although it’s also a valid
Groovy program!

public String toString() {
return "Person(" + name + ", " + age + ")";
}
}

66
@Immutable

import!groovy.transform.*
@Immutable
class!Person!{
!!!!String!name
!!!!int!age
}
67
Memoization
• Cache the result of previous invocations
of closures or methods with the same set
of argument values
import!groovy.transform.*
@Memoized
long!fib(long!n)!{
!!!!if!(n!==!0)!0
!!!!else!if!(n!==!1)!1
!!!!else!fib(n!c!1)!+!fib(n!c!2)
}
println!fib(40)
68
Memoization
• Cache the result of previous invocations
of closures or methods with the same set
of argument values
import!groovy.transform.*

Best applied to
side-effect free
functions

@Memoized
long!fib(long!n)!{
!!!!if!(n!==!0)!0
!!!!else!if!(n!==!1)!1
!!!!else!fib(n!c!1)!+!fib(n!c!2)
}
println!fib(40)

68
What makes groovy groovy   codeurs en seine - 2013 - light size
Groovy allows you
to be lazy
Groovy allows you
to be lazy

The compiler will do
the job for you
Groovy allows you
to be lazy

More concise, more
readable code

The compiler will do
the job for you
Groovy allows you
to be lazy

More concise, more
readable code

The compiler will do
the job for you

Less stuff to maintain
and worry about
@TypeChecked and @CompileStatic
• Static type checking with @TypeChecked,
throws compilation errors on...
– typos in method and variable names
– incompatible return types
– wrong type assignments

• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »

70
@TypeChecked and @CompileStatic
• Static type checking with @TypeChecked,
throws compilation errors on...
– typos in method and variable names
– incompatible return types
You can even extend the
– wrong type assignments
static type checker!

• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »

70
@TypeChecked and @CompileStatic
• Static type checking with @TypeChecked,
throws compilation errors on...
– typos in method and variable names
– incompatible return types
You can even extend the
– wrong type assignments
static type checker!

• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »

70

Type check DSLs or
dynamic features!
@TypeChecked and @CompileStatic
• What is type checked can also be compiled
statically with @CompileStatic
– generate the same bytecode as javac
– same performance as Java

71
Pi (π)
Fibonacci
quadrature
Java

191 ms

97 ms

3.6 s

2.x

Static
compilation

197 ms

101 ms

4.3 s

1.8
72

Binary
trees

Primitive
optimizations

360 ms

111 ms

23.7 s

1.7

Static compilation performance

No prim.
optimizations

2590 ms 3220 ms

50.0 s
3
t
r
a
P

Superb
community!
A blossoming
Ecosystem
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
What makes groovy groovy   codeurs en seine - 2013 - light size
M
V
G
What makes groovy groovy   codeurs en seine - 2013 - light size
GVM
GVM
GROOVY
ENVIRONMENT

MANAGER
GVM: Groovy enVironment Manager
• The new kid on the block
– http://gvmtool.net/ — @gvmtool

• Manage parallel versions
of the various ecosystem projects
• Supports...
– Groovy, Grails, Griffon, Gradle,Vert.x, Spring Boot

• On Linux, MacOS, Cygwin, Solaris, FreeBSD
81
What makes groovy groovy   codeurs en seine - 2013 - light size
I’m Spock...
I’m Spock...
...the Spock testing
framework
I’m Spock...
...the Spock testing
framework
Spock example
@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*
class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83
Spock example

@Grab a dependency

@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*
class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83
Spock example

@Grab a dependency

@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*
class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83

Meaningful test
method names
Spock example

@Grab a dependency

@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*

Meaningful test
method names

class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
Clever use of labels
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83

for BDD style
Spock example

@Grab a dependency

@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*

Meaningful test
method names

class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
Clever use of labels
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83

for BDD style
Expression to
be asserted
Spock example

@Grab a dependency

@Grab('org.spockframework:spockccore:0.7cgroovyc2.0')
import!spock.lang.*

Meaningful test
method names

class!MathSpec!extends!Specification!{
!!!!def!"maximum!of!two!numbers"()!{
******expect:
!!!!!!!!Math.max(a,!b)!==!c
Clever use of labels
******where:
!!!!!!!!a!|!b!||!c
!!!!!!!!1!|!3!||!3
!!!!!!!!7!|!4!||!4
!!!!!!!!0!|!0!||!0
!!!!}
}
83

for BDD style
Cute datadriven tests!

Expression to
be asserted
What makes groovy groovy   codeurs en seine - 2013 - light size
@GrabResolver("https://oss.jfrog.org/artifactory/repo")
@Grab("org.ratpackcframework:ratpackcgroovy:0.9.0cSNAPSHOT")
import!static!org.ratpackframework.groovy.RatpackScript.ratpack
import!static!org.ratpackframework.groovy.Template.groovyTemplate
ratpack!{
!!!!handlers!{
!!!!!!!!get!{
!!!!!!!!!!!!response.send!"Welcome!"
!!!!!!!!}
!!!!!!!!get("date")!{
!!!!!!!!!!!!render!groovyTemplate("date.html")
!!!!!!!!}
!!!!!!!!assets!"public"
!!!!}
}
@GrabResolver("https://oss.jfrog.org/artifactory/repo")
@Grab("org.ratpackcframework:ratpackcgroovy:0.9.0cSNAPSHOT")
import!static!org.ratpackframework.groovy.RatpackScript.ratpack
import!static!org.ratpackframework.groovy.Template.groovyTemplate
ratpack!{
!!!!handlers!{
!!!!!!!!get!{
!!!!!!!!!!!!response.send!"Welcome!"
!!!!!!!!}

Lightweight Netty-based
web app toolkit

!!!!!!!!get("date")!{
!!!!!!!!!!!!render!groovyTemplate("date.html")
!!!!!!!!}
!!!!!!!!assets!"public"
!!!!}
}
Geb
• Browser automation solution
• WebDriver + jQuery selectors + Groovy
• Handy for
– scripting, scraping, automation...
– functional / web / acceptance testing
• when integrated with JUnit, TestNG or Spock

85
Geb — Example
import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"
!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

86
Geb — Example

Drive the browser
to this site

import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"
!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

86
Geb — Example

Drive the browser
to this site

import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"

Check the content
of the title

!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

86
Geb — Example

Drive the browser
to this site

import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"

Check the content
of the title

!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

86

Find & fill in
the form
Geb — Example

Drive the browser
to this site

import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"

Check the content
of the title

!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

86

Find & fill in
the form
Submit the
form
Geb — Example

Drive the browser
to this site

import!geb.Browser
Browser.drive!{
!!!!go!"http://myapp.com/login"

Check the content
of the title

!!!!assert!$("h1").text()!==!"Please!Login"
!!!!$("form.login").with!{
!!!!!!!!username!=!"admin"
!!!!!!!!password!=!"password"
!!!!!!!!login().click()
!!!!}
!!!!assert!$("h1").text()!==!
!!!!!!!!"Admin!Section"
}

Find & fill in
the form
Submit the
form

In the admin section, yeah!
86
Geb — With page objects and Spock
import!geb.spock.GebSpec
class!GoogleWikipediaSpec!extends!GebSpec!{
!!!!def!"first!result!for!wikipedia!search!should!be!wikipedia"()!{
********given:
!!!!!!!!to!GoogleHomePage
********expect:
!!!!!!!!at!GoogleHomePage
********when:
!!!!!!!!search.field.value("wikipedia")
********then:
!!!!!!!!waitFor!{!at!GoogleResultsPage!}
********and:
!!!!!!!!firstResultLink.text()!==!"Wikipedia"
********when:
!!!!!!!!firstResultLink.click()
********then:
!!!!!!!!waitFor!{!at!WikipediaPage!}
!!!!}
}

87
Geb — With page objects and Spock
import!geb.spock.GebSpec
class!GoogleWikipediaSpec!extends!GebSpec!{

With page objects
!!!!def!"first!result!for!wikipedia!search!should!be!wikipedia"()!{
********given:
!!!!!!!!to!GoogleHomePage
********expect:
!!!!!!!!at!GoogleHomePage
********when:
!!!!!!!!search.field.value("wikipedia")
********then:
!!!!!!!!waitFor!{!at!GoogleResultsPage!}
********and:
!!!!!!!!firstResultLink.text()!==!"Wikipedia"
********when:
!!!!!!!!firstResultLink.click()
********then:
!!!!!!!!waitFor!{!at!WikipediaPage!}
!!!!}
}

87
Geb — With page objects and Spock
import!geb.spock.GebSpec
class!GoogleWikipediaSpec!extends!GebSpec!{

With page objects
!!!!def!"first!result!for!wikipedia!search!should!be!wikipedia"()!{
********given:
!!!!!!!!to!GoogleHomePage
********expect:
!!!!!!!!at!GoogleHomePage

BDD style: given/when/then

********when:
!!!!!!!!search.field.value("wikipedia")
********then:
!!!!!!!!waitFor!{!at!GoogleResultsPage!}
********and:
!!!!!!!!firstResultLink.text()!==!"Wikipedia"
********when:
!!!!!!!!firstResultLink.click()
********then:
!!!!!!!!waitFor!{!at!WikipediaPage!}
!!!!}
}

87
Geb — With page objects and Spock
import!geb.spock.GebSpec
class!GoogleWikipediaSpec!extends!GebSpec!{

With page objects
!!!!def!"first!result!for!wikipedia!search!should!be!wikipedia"()!{
********given:
!!!!!!!!to!GoogleHomePage
********expect:
!!!!!!!!at!GoogleHomePage
********when:
!!!!!!!!search.field.value("wikipedia")

BDD style: given/when/then
Wait for slow loading pages

********then:
!!!!!!!!waitFor!{!at!GoogleResultsPage!}
********and:
!!!!!!!!firstResultLink.text()!==!"Wikipedia"
********when:
!!!!!!!!firstResultLink.click()
********then:
!!!!!!!!waitFor!{!at!WikipediaPage!}
!!!!}
}

87
4
t
r
a
P

Summary
Java’s best friend
• Java derived syntax
– Flat learning curve
– Easy to learn

• But goes beyond Java
– Concise, expressive, readable
– Fit for Domain-Specific Languages

• Seamless & transparent Java integration
– Mix and match Groovy and Java classes (joint compil.)
– No language barrier to cross
89
Groovy’s nature
• Object oriented dynamic language...
• But...
– as type safe as you want it — static type checking
– as fast as you need it — static compilation
– as functional as you make it — closures...

90
Groovy use cases
• Scripting tasks, build automation
• Extension points for customizing/configuring apps
• Business languages & Domain-Specific Languages
• Full blown apps
– for desktop with Griffon
– for the web with Grails, Ratpack, Gaelyk
– for web reactive programming with reactor
91

More Related Content

PDF
Functional IoT: Hardware and Platform
PDF
Functional IoT: Introduction
PDF
Infrastructure as code might be literally impossible / Joe Domato (packageclo...
PDF
Metasepi team meeting #16: Safety on ATS language + MCU
PDF
Start! ATS programming
PDF
ATS language overview'
PDF
Real-time OS system state captured by ATS language
PDF
Static typing and proof in ATS language
Functional IoT: Hardware and Platform
Functional IoT: Introduction
Infrastructure as code might be literally impossible / Joe Domato (packageclo...
Metasepi team meeting #16: Safety on ATS language + MCU
Start! ATS programming
ATS language overview'
Real-time OS system state captured by ATS language
Static typing and proof in ATS language

Viewers also liked (8)

PDF
Soirée Ceylon avec Stéphane Epardaud
PPTX
Gatling : Faites tomber la foudre sur votre serveur ! (Stéphane Landelle)
PPTX
HTML5 en projet
PDF
[Codeurs en seine] management & monitoring cloud
PDF
Découvrez les bases de l’ergonomie web : donnez à vos utilisateurs le meilleu...
PDF
Codeurs En Seine - Lean startup - Matthieu Garde-Lebreton
PDF
Capacity Planning : Pratiques et outils pour regarder la foudre tomber sans p...
PDF
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Soirée Ceylon avec Stéphane Epardaud
Gatling : Faites tomber la foudre sur votre serveur ! (Stéphane Landelle)
HTML5 en projet
[Codeurs en seine] management & monitoring cloud
Découvrez les bases de l’ergonomie web : donnez à vos utilisateurs le meilleu...
Codeurs En Seine - Lean startup - Matthieu Garde-Lebreton
Capacity Planning : Pratiques et outils pour regarder la foudre tomber sans p...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Ad

Similar to What makes groovy groovy codeurs en seine - 2013 - light size (20)

PDF
Desert Code Camp 2014: C#, the best programming language
PDF
JavaCro 2016 - From Java to Groovy: Adventure Time!
PDF
Gr8Conf US 2017 - From Java to Groovy: Adventure Time!
PDF
Spring, CDI, Jakarta EE good parts
PDF
Go language presentation
PDF
Why don't you Groovy?
PPT
Groovy And Grails
PPTX
Groovy best pratices at EWAY
PDF
An Introduction to Groovy for Java Developers
PPTX
Groovy And Grails Introduction
PDF
Groovy AST Demyistified - 33degree
KEY
Plataforma java
PDF
Machine vision and device integration with the Ruby programming language (2008)
PDF
New adventures in 3D
PDF
Groovy Up Your Code
PDF
Дмитрий Щадей "Что помогает нам писать качественный JavaScript-код?"
PDF
Clojure at ardoq
PDF
Fast Web Applications with Go
ZIP
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
PDF
Imola informatica - cloud computing and software development
Desert Code Camp 2014: C#, the best programming language
JavaCro 2016 - From Java to Groovy: Adventure Time!
Gr8Conf US 2017 - From Java to Groovy: Adventure Time!
Spring, CDI, Jakarta EE good parts
Go language presentation
Why don't you Groovy?
Groovy And Grails
Groovy best pratices at EWAY
An Introduction to Groovy for Java Developers
Groovy And Grails Introduction
Groovy AST Demyistified - 33degree
Plataforma java
Machine vision and device integration with the Ruby programming language (2008)
New adventures in 3D
Groovy Up Your Code
Дмитрий Щадей "Что помогает нам писать качественный JavaScript-код?"
Clojure at ardoq
Fast Web Applications with Go
Groovy and Grails in Action - Devoxx 2008 - University - Guillaume Laforge
Imola informatica - cloud computing and software development
Ad

More from Normandy JUG (20)

PPTX
Soirée Guava et Lombok avec Thierry Leriche
PDF
Couche Base par Tugdual Grall
PDF
Java7 normandyjug
KEY
Apache, osgi and karaf par Guillaume Nodet
PDF
Mockito - Design + tests par Brice Duteil
PDF
Annotations Java par Olivier Croisier
KEY
Spring Batch 17-05-2011
PDF
ATR2011 - Planning poker
PDF
ATR2011 - Scrum dans les tranchées Normandes
PDF
Hibernate vs le_cloud_computing
PDF
PDF
Soirée BPM - Introduction Logica
PDF
Soirée BPM - Bonita Soft
PPTX
AT2010 Keynote de cloture
ODP
AT2010 Kanban au secours des équipes sysadmin et support
PPT
AT2010 Introduction à scrum
PPT
AT2010 Dojo TDD
PDF
AT2010 Keynote
PDF
AT2010 Principes Integration Continue
PPTX
AT2010 Optimisez le retour sur investissement de votre produit avec une bonne...
Soirée Guava et Lombok avec Thierry Leriche
Couche Base par Tugdual Grall
Java7 normandyjug
Apache, osgi and karaf par Guillaume Nodet
Mockito - Design + tests par Brice Duteil
Annotations Java par Olivier Croisier
Spring Batch 17-05-2011
ATR2011 - Planning poker
ATR2011 - Scrum dans les tranchées Normandes
Hibernate vs le_cloud_computing
Soirée BPM - Introduction Logica
Soirée BPM - Bonita Soft
AT2010 Keynote de cloture
AT2010 Kanban au secours des équipes sysadmin et support
AT2010 Introduction à scrum
AT2010 Dojo TDD
AT2010 Keynote
AT2010 Principes Integration Continue
AT2010 Optimisez le retour sur investissement de votre produit avec une bonne...

Recently uploaded (20)

PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
NewMind AI Monthly Chronicles - July 2025
PPT
Teaching material agriculture food technology
PPTX
A Presentation on Artificial Intelligence
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Encapsulation theory and applications.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Approach and Philosophy of On baking technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Big Data Technologies - Introduction.pptx
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Encapsulation_ Review paper, used for researhc scholars
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
NewMind AI Monthly Chronicles - July 2025
Teaching material agriculture food technology
A Presentation on Artificial Intelligence
“AI and Expert System Decision Support & Business Intelligence Systems”
Encapsulation theory and applications.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Network Security Unit 5.pdf for BCA BBA.
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Approach and Philosophy of On baking technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
Advanced methodologies resolving dimensionality complications for autism neur...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Big Data Technologies - Introduction.pptx
MYSQL Presentation for SQL database connectivity
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Encapsulation_ Review paper, used for researhc scholars

What makes groovy groovy codeurs en seine - 2013 - light size