• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Groovy update - S2GForum London 2011 - Guillaume Laforge
 

Groovy update - S2GForum London 2011 - Guillaume Laforge

on

  • 5,238 views

Groovy Update: what's new in 1.8 and what's coming in 1.9...

Groovy Update: what's new in 1.8 and what's coming in 1.9

The Groovy Development team is releasing Groovy 1.8, and this session will cover the new features including improved support for advanced and readable Domain-Specific Languages thanks to Groovy 1.8's "Extended Command Expressions", new performance improvements in the area of integer arithmetics, built-in support for parsing and producing JSON payloads, new AST transformations and now GPars come already bundled.

Statistics

Views

Total Views
5,238
Views on SlideShare
4,767
Embed Views
471

Actions

Likes
5
Downloads
41
Comments
0

8 Embeds 471

http://blog.helyx.org 459
http://feeds.feedburner.com 4
http://twitter.com 2
http://feeds2.feedburner.com 2
https://twitter.com 1
http://us-w1.rockmelt.com 1
http://paper.li 1
url_unknown 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Groovy update - S2GForum London 2011 - Guillaume Laforge Groovy update - S2GForum London 2011 - Guillaume Laforge Presentation Transcript

  • Groovy UpdateWhat’s new in Groovy 1.8,and what’s cooking in 1.9! Guillaume Laforge Groovy Project Manager SpringSource / VMware
  • Guillaume Laforge• Groovy Project Manager• JSR-241 Spec Lead• Head of Groovy Development at SpringSource / VMWare• Initiator of the Grails framework• Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • Guillaume Laforge• Groovy Project Manager• JSR-241 Spec Lead• Head of Groovy Development at SpringSource / VMWare• Initiator of the Grails framework• Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • Groovy 1.7 3
  • Groovy 1.7185 3
  • Groovy 1.7185k 3
  • Groovy 1.7185k FIRST MONTH AFTER RELEASE 3
  • Groovy 1.7 k 3
  • Groovy 1.7177k SECOND MONTH AFTER RELEASE 3
  • Groovy 1.7 k 3
  • Groovy 1.7362k USERS? 3
  • ?TIP OFTHEICEBERG
  • Agenda 5
  • Agenda• What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous 5
  • Agenda• What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous• What’s cooking for Groovy 1.9? – Continued runtime performance improvements – Alignments with JDK 7 • Project Coin (small language changes) • InvokeDynamic 5
  • Command chains expressions 6
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println• Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 6
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println• Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 6
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println• Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course)• Let’s have a look at some examples 6
  • Command chains expressions 
turn
left

then
right
 7
  • Command chains expressions Alternation of method names 
turn
left

then
right
 7
  • Command chains expressions Alternation of method names 
turn
left

then
right
 and parameters (even named ones) 7
  • Command chains expressions 
turn
left

then
right
 7
  • Command chains expressions Equivalent to: 




(



).



(




) 
turn
left

then
right
 7
  • LookM a!N op are ns,no do ts!
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours 9
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument 9
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument Named arguments 9
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument Named arguments Woud call: def
take(Map
m,
Quantity
q) 9
  • Command chains expressions Now, even less punctuation! take
2.pills

of

chloroquinine

after

6.hours 10
  • Command chains expressions Now, even less punctuation! 



(






).


(












).





(






) take
2.pills

of

chloroquinine

after

6.hours 10
  • Command chains expressions //
environment
initialization Integer.metaClass.getPills
{
‐>
delegate
} Integer.metaClass.getHours
{
‐>
delegate
} 
 //
variable
injection def
chloroquinine
=
/*...*/ 
 { } //
implementing
the
DSL
logic def
take(n)
{ 



[of:
{
drug
‐> 







[after:
{
time
‐>
/*...*/
}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2.pills
of
chloroquinine
after
6.hours 11
  • Command chains expressions take
2.pills

of

chloroquinine

after

6.hours 12
  • Command chains expressions take
2.pills

of

chloroquinine

after

6.hours ... some dots remain ... 12
  • Command chains expressions We could cheat a bit... take
2

pills
of

chloroquinine
6

hours
after 13
  • Command chains expressions We could cheat a bit... 



(
).




(

).












(
).




(




) take
2

pills
of

chloroquinine
6

hours
after 13
  • Cheatingis playing with the language
  • Command chains expressions Still doable without cheating though take
2

pills
of

chloroquinine
after

6
hours 15
  • Command chains expressions Still doable without cheating though 



(
).




(

).












(




).
(




) take
2

pills
of

chloroquinine
after

6
hours 15
  • Command chains expressions //
variable
injection def
(of,
after,
hours)
=
/*...*/ 
 //
implementing
the
DSL
logic { } def
take(n)
{ 



[pills:
{
of
‐> 







[chloroquinine:
{
after
‐> 











[6:
{
time
‐>
}] 







}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2
pills
of
chloroquinine
after
6
hours 16
  • Command chains expressions 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 



(
). 17
  • Runtime performance improvements• Significant runtime improvements for primitive int operations – classical Fibonacci example x13 faster! – almost as fast as Java• Some direct method calls on this• But there’s more to come! – in particular for all the primitive types 18
  • GPars bundled• GPars is bundled in the Groovy distribution• GPars covers a wide range of parallel and concurrent paradigms – actors, fork/join, dataflow, agents, STM... 19
  • Closure enhancements• Closure annotation parameters• Some more functional flavor – composition – trampoline – memoization• Currying improvements 20
  • Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface
Invariant
{



 



Class
value()
//
a
closure
class } 
{ @Invariant({
number
>=
0
}) class
Distance
{



 



float
number



 



String
unit }
 
 def
d
=
new
Distance(number:
10,
unit:
"meters")
 def
anno
=
Distance.getAnnotation(Invariant) def
check
=
anno.value().newInstance(d,
d) assert
check(d) 21
  • Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface
Invariant
{



 



Class
value()
//
a
closure
class } 
{ @Invariant({
number
>=
0
}) class
Distance
{



 



float
number



 an’s G Cont racts 



String
unit P oor-m }
 
 def
d
=
new
Distance(number:
10,
unit:
"meters")
 def
anno
=
Distance.getAnnotation(Invariant) def
check
=
anno.value().newInstance(d,
d) assert
check(d) 21
  • Closure composition def
plus2

=
{
it
+
2
} def
times3
=
{
it
*
3
}
 
{ def
times3plus2
=
plus2
<<
times3 assert
times3plus2(3)
==
11 assert
times3plus2(4)
==
plus2(times3(4))
 
{ def
plus2times3
=
times3
<<
plus2 assert
plus2times3(3)
==
15 assert
plus2times3(5)
==
times3(plus2(5))
 
 //
reverse
composition{ assert
times3plus2(3)
==
(times3
>>
plus2)(3) 22
  • Closure trampoline 23
  • Closure trampolinedef
factorialfactorial
=
{
int
n,
BigInteger
accu
=
1G
‐>
 




if
(n
<
2)
return
accu








factorial.trampoline(n
‐
1,
n
*
accu)}.trampoline()
assert
factorial(1)



==
1assert
factorial(3)



==
1
*
2
*
3assert
factorial(1000)
==
402387260... 23
  • Closure memoization 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 //
between
10
and
20
invocations
cached 24
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 //
between
10
and
20
invocations
cached def
plusAtLeast
=
{
...
}.memoizeBetween(10,
20) 24
  • Currying improvements 25
  • Currying improvements //
right
currying def
divide
=
{
a,
b
‐>
a
/
b
} def
halver
=
divide.rcurry(2) assert
halver(8)
==
4

 
 25
  • Currying improvements //
right
currying def
divide
=
{
a,
b
‐>
a
/
b
} def
halver
=
divide.rcurry(2) assert
halver(8)
==
4

 
 //
currying
n‐th
parameter def
joinWithSeparator
=
 



{
one,
sep,
two
‐>
one
+
sep
+
two
} def
joinWithComma
=
 



joinWithSeparator.ncurry(1,
,
) assert
joinWithComma(a,
b)
==
a,
b 25
  • Builtin JSON support• Consuming• Producing• Pretty-printing 26
  • Builtin JSON supportimport
groovy.json.*
def
payload
=
new
URL(



"http://github.../json/commits/...").text
def
slurper
=
new
JsonSlurper()def
doc
=
slurper.parseText(payload)
doc.commits.message.each
{
println
it
} 27
  • Builtin JSON support import
groovy.json.*
 
 def
json
=
new
JsonBuilder()
 
 json.person
{



 



name
"Guillaume" 



age
33



 



pets
"Hector",
"Felix" }
 println
json.toString() 28
  • Builtin JSON support import
groovy.json.*
 
 println
JsonOutput.prettyPrint( 



{"person":{"name":"Guillaume","age":33,
+
 



"pets":["Hector","Felix"]}}) 
 29
  • Builtin JSON support import
groovy.json.*
 
 println
JsonOutput.prettyPrint( 



{"person":{"name":"Guillaume","age":33,
+
 



"pets":["Hector","Felix"]}}) 
 {



 



"person":
{







 







"name":
"Guillaume",


 
 







"age":
33,







 







"pets":
[











 











"Hector",









 
 











"Felix"







 







]



 



} } 29
  • New AST transformations• @Log • @Canonical – @ToString,• @Field – @EqualsAndHashCode, – @TupleConstructor• @AutoClone • @InheritConstructor• @AutoExternalizable • @WithReadLock• Controlling the execution of your code • @WithWriteLock – @ThreadInterrupt, – @TimedInterrupt, • @ListenerList – @ConditionalInterrupt 30
  • @Log• Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy import
groovy.util.logging.*
 
 @Log class
Car
{



 



Car()
{







 







log.info
Car
constructed

 
 



} }
 
 def
c
=
new
Car() 31
  • @Log• Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy import
groovy.util.logging.*
 
 @Log class
Car
{



Guarded 



Car()
{







w/ an if 







log.info
Car
constructed

 
 



} }
 
 def
c
=
new
Car() 31
  • @Field• Surprising scoping rules in scripts – variables are local to the run() method – variables aren’t visible in methods • although visually the variable is in a surrounding scope• @Field creates a field in the script class @Field
List
awe
=
[1,
2,
3] def
awesum()
{
awe.sum()
} assert
awesum()
==
6 32
  • Controlling code execution• Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? 33
  • Controlling code execution• Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources?• 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33
  • Controlling code execution• Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources?• 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33
  • Controlling code execution• Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources?• 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code• Also see compilation customizers later on 33
  • @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ 



//
eat
lots
of
CPU } 34
  • @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ { 



if
(Thread.currentThread.isInterrupted()) 







throw
new
InterruptedException() } 



//
eat
lots
of
CPU } 34
  • @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ { 



if
(Thread.currentThread.isInterrupted()) 







throw
new
InterruptedException() } 



//
eat
lots
of
CPU }• Two optional annotation parameters available – checkOnMethodStart (true by default) – applyToAllClasses (true by default) 34
  • @TimedInterrupt @TimedInterrupt(10) import
groovy.transform.TimedInterrupt
 
 while
(true)
{ 



//
eat
lots
of
CPU }• InterruptedException thrown when checks indicate code ran longer than desired• Optional annotation parameters available – same as @ThreadInterrupt – value: for an amount of time duration – unit: for the time duration unit (TimeUnit.SECONDS) 35
  • @ConditionalInterrupt• Specify your own condition to be inserted at the start of method and closure bodies – check for available resources, number of times run, etc.• Leverages closure annotation parameters from Groovy 1.8 @ConditionalInterrupt({
counter++
>
2
}) import
groovy.transform.ConditionalInterrupt import
groovy.transform.Field
 
 @Field
int
counter
=
0
 100.times
{



 



println
executing
script
method... } 36
  • @ToString• Provides a default toString() method to your types• Available annotation options – includeNames, includeFields, includeSuper, excludes import
groovy.transform.ToString
 
 @ToString class
Person
{



 



String
name



 



int
age }
 
 println
new
Person(name:
Pete,
age:
15) //
=>
Person(Pete,
15) 37
  • @EqualsAndHashCode• Provides default implementations for equals() and hashCode() methods import
groovy.transform.EqualsAndHashCode
 
 @EqualsAndHashCode class
Coord
{



 



int
x,
y }
 
 def
c1
=
new
Coord(x:
20,
y:
5) def
c2
=
new
Coord(x:
20,
y:
5)
 
 assert
c1
==
c2 assert
c1.hashCode()
==
c2.hashCode() 38
  • @TupleConstructor• Provides a «classical» constructor with all properties• Several annotation parameter options available import
groovy.transform.TupleConstructor
 
 @TupleConstructor
 class
Person
{



 



String
name



 



int
age }
 
 def
m
=
new
Person(Marion,
3)





 
 assert
m.name
==
Marion assert
m.age

==
3 39
  • @Canonical• One annotation to rule them all! – @Canonical mixes together • @ToString • @EqualsAndHashCode • @TupleConstructor• You can customize behavior by combining @Canonical and one of the other annotations 40
  • @InheritConstructor• Classes like Exception are painful when extended, as all the base constructors should be replicatedclass
CustomException
extends
Exception
{



CustomException()























{
super()






}



CustomException(String
msg)













{
super(msg)



}



CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
}



CustomException(Throwable
t)












{
super(t)





}} 41
  • @InheritConstructor• Classes like Exception are painful when extended, as all the base constructors should be replicatedimport
groovy.transform.*@InheritConstructorsclass
CustomException
extends
Exception
{



CustomException()























{
super()






}



CustomException(String
msg)













{
super(msg)



}



CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
}



CustomException(Throwable
t)












{
super(t)





}} 41
  • @WithReadLock, @WithWriteLock import
groovy.transform.*
 
 class
ResourceProvider
{



 



private
final
Map<String,
String>
data
=
new
HashMap<>() 
 



@WithReadLock



 



String
getResource(String
key)
{







 







return
data.get(key)



 



}




 
 



@WithWriteLock



 



void
refresh()
{







 







//reload
the
resources
into
memory



 



} } 42
  • @WithReadLock, @WithWriteLock import
groovy.transform.*
 
 class
ResourceProvider
{



 



private
final
Map<String,
String>
data
=
new
HashMap<>() 
{ 



@WithReadLock



 



String
getResource(String
key)
{







 







return
data.get(key)



 



}




 
{ 



@WithWriteLock



 



void
refresh()
{







 







//reload
the
resources
into
memory



 



} } 42
  • Miscelanous• Compilation customizers• Java 7 diamond operator• Slashy and dollar slashy strings• New GDK methods• (G)String to Enum coercion 43
  • Compilation customizers• Ability to apply some customization to the Groovy compilation process• Three available customizers – ImportCustomizer – SecureASTCustomizer – ASTTransformationCustomizer• But you can implement your own 44
  • Imports customizerdef
configuration
=
new
CompilerConfiguration()
def
custo
=
new
ImportCustomizer()custo.addStaticStar(Math.name)configuration.addCompilationCustomizers(custo)

def
result
=
new
GroovyShell(configuration)



.evaluate("
cos
PI/3
") 45
  • Applying an AST transformation def
configuration
=
new
CompilerConfiguration() configuration.addCompilationCustomizers( 



new
ASTTransformationCustomizer(Log))
 
 new
GroovyShell(configuration).evaluate(""" 



class
Car
{







 







Car()
{











 











log.info
Car
constructed







 







}



 



}




 



log.info
Constructing
a
car



 



def
c
=
new
Car() """) 46
  • Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions• Let’s setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizerimport
org.codehaus.groovy.control.customizers.*import
org.codehaus.groovy.control.*import
static
org.codehaus.groovy.syntax.Types.*
def
imports
=
new
ImportCustomizer().addStaticStars(java.lang.Math)def
secure
=
new
SecureASTCustomizer() 47
  • Secure AST customizer ... secure.with
{ //
disallow
closure
creation closuresAllowed
=
false
 //
disallow
method
definitions methodDefinitionAllowed
=
false
 
 //
empty
white
list
=>
forbid
imports importsWhitelist
=
[]
 staticImportsWhitelist
=
[] //
only
allow
the
java.lang.Math.*
static
import staticStarImportsWhitelist
=
[java.lang.Math ... 48
  • Secure AST customizer... //
language
tokens
allowed tokensWhitelist
=
[ PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,
 MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,
 COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,
 COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL ]
 //
types
allowed
to
be
used
(including
primitive
types) constantTypesClassesWhiteList
=
[ Integer,
Float,
Long,
Double,
BigDecimal,
 Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE ]
 //
classes
who
are
allowed
to
be
receivers
of
method
calls receiversClassesWhiteList
=
[
 Math,
Integer,
Float,
Double,
Long,
BigDecimal
]}... 49
  • Secure AST customizer• Ready to evaluate our arithmetic expressions! ... def
config
=
new
CompilerConfiguration() config.addCompilationCustomizers(imports,
secure) def
shell
=
new
GroovyShell(config) 
 shell.evaluate
cos(PI/3)• But the following would have failed: shell.evaluate
System.exit(0) 50
  • Slashy and dollar slashy strings• Slashy strings are now multiline – particularly handy for multi-line regexs• Dollar slashy string notation introduced – a multiline GString with different escaping rules def
(name,
date)
=
["Guillaume",
"May,
17th"] def
dollarSlashy
=
$/



 



Hello
$name,
today
were
${date} 



$
dollar‐sign



 



$$
dollar‐sign



 




backslash



 



/
slash



 


$/
slash /$
 51
  • New GDK methods 52
  • New GDK methods //
count 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 
 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() def
freq
=
[:].withDefault
{
k
‐>
0
} 52
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
Groovy.toList().countBy{
it
==
o
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
dddd assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() def
freq
=
[:].withDefault
{
k
‐>
0
} words.each
{
freq[it]
+=
1
} 52
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 53
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 53
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 53
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
 
 53
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
 
 //
with
GStrings
too def
g
=
"${green}"
as
Color 53
  • What’scookingfor 1.9?
  • Groovy 1.9 roadmap• Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch• JDK 7: InvokeDynamic• Towards a more modular Groovy• Rewritten Antlr 3 grammar (GSoC)• Eclipse compiler to replace the joint compiler?• What else? Your call! 55
  • Groovy 1.9 roadmap• Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch• JDK 7: InvokeDynamic• Towards a more modular Groovy• Rewritten Antlr 3 grammar (GSoC)• Eclipse compiler to replace the joint compiler?• What else? Your call! 55
  • Binary literals• We had decimal, octal and hexadecimal notations for number literals• We can now use binary representations too int
x
=
0b10101111 assert
x
==
175 
 byte
aByte
=
0b00100001 assert
aByte
==
33 
 int
anInt
=
0b1010000101000101 assert
anInt
==
41285 56
  • Underscore in literals• We can now also add underscores in number literals for more readability long
creditCardNumber
=
1234_5678_9012_3456L long
socialSecurityNumbers
=
999_99_9999L float
monetaryAmount
=
12_345_132.12 long
hexBytes
=
0xFF_EC_DE_5E long
hexWords
=
0xFFEC_DE5E long
maxLong
=
0x7fff_ffff_ffff_ffffL long
alsoMaxLong
=
9_223_372_036_854_775_807L long
bytes
=
0b11010010_01101001_10010100_10010010 57
  • Multicatch• One block for multiple exception caught – rather than duplicating the block try
{ 



/*
...
*/ }
catch(IOException
|
NullPointerException
e)
{ 



/*
one
block
to
treat
2
exceptions
*/ } 58
  • Summary ROCKS! 59
  • Thank you! e aforg pment ume L Develo Guilla Groovy om He ad of e@ gmail.c glaforg rge Email: @glafo : Twitter 60
  • Image credits• Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg• Bicycle: http://drunkcyclist.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=2131&g2_serialNumber=2• Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg• Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg• Cheating: http://fr.academic.ru/pictures/frwiki/67/Cheating.JPG• Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/• Oui nide iou: http://desencyclopedie.wikia.com/wiki/Fichier:Superdupont_we_need_you.jpg• Guitar: http://www.lelitteraire.com/IMG/breveon323.jpg• Trampoline: http://www.fitness-online.fr/images/trampoline-1-m.jpg• Curry: http://www.pot-a-epices.com/wp-content/uploads/2009/02/curry1.jpg• Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg 61