The document discusses new features in Groovy 1.8 and beyond, including command chains expressions that allow dropping dots and parentheses when chaining method calls to write more readable domain-specific languages resembling plain English. It provides examples of medical instructions and coffee preparation written using this new syntax without punctuation. The author also outlines further syntax optimizations and control structures possible with command chains.
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
What's new in Groovy 1.8 and beyond
1. Whatʼs new in Groovy 1.8 and beyond?
Guillaume Laforge
Groovy Project Manager
SpringSource, a division of VMware
Twitter: @glaforge
Blog: http://glaforge.appspot.com
Google+: http://gplus.to/glaforge
2. Guillaume Laforge
• Groovy Project Manager at VMware
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action
• Speaking worldwide w/ a French accent
• Follow me on...
• My blog: http://glaforge.appspot.com
• Twitter: @glaforge
• Google+: http://gplus.to/glaforge
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 2
3. Guillaume Laforge
• Groovy Project Manager at VMware
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action
• Speaking worldwide w/ a French accent
• Follow me on...
• My blog: http://glaforge.appspot.com
• Twitter: @glaforge
• Google+: http://gplus.to/glaforge
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 2
18. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
19. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
20. 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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
21. 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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
22. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
23. Command chains expressions
turn left then right
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
24. Command chains expressions
Alternation of
method names
turn left then right
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
25. Command chains expressions
Alternation of
method names
turn left then right
and parameters
(even named ones)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
26. Command chains expressions
turn left then right
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
27. Command chains expressions
Equivalent to:
( ). ( )
turn left then right
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
29. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
30. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
Normal argument
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
31. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
Normal argument Named arguments
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
32. 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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
33. Command chains expressions
Now, even less punctuation!
take 2.pills of chloroquinine after 6.hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 11
34. Command chains expressions
Now, even less punctuation!
( ). ( ). ( )
take 2.pills of chloroquinine after 6.hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 11
35. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 12
36. Command chains expressions
take 2.pills of chloroquinine after 6.hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 13
37. Command chains expressions
take 2.pills of chloroquinine after 6.hours
... some dots remain ...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 13
38. Command chains expressions
Yes, we can... get rid of them :-)
take 2 pills of chloroquinine after 6 hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 14
39. Command chains expressions
Yes, we can... get rid of them :-)
( ). ( ). ( ). ( )
take 2 pills of chloroquinine after 6 hours
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 14
40. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 15
43. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
44. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
45. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
46. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
47. 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 {}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
48. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
49. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
50. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
51. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
52. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
53. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
54. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
55. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
56. 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
( ).
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
57. Runtime performance improvements
• Significant runtime improvements
for primitive type operations
– classical Fibonacci example x13 faster!
– almost as fast as Java
• Some direct method calls on this
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 17
58. GPars bundled
• GPars is bundled
in the Groovy distribution
• GPars covers a wide range of parallel and concurrent
paradigms
– actors, fork/join, map/filter/reduce, dataflow, agents, STM
– parallel arrays, executors, and more...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 18
60. 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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 20
61. 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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 20
88. @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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 30
89. @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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 30
90. @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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 31
91. 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?
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
92. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
93. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
94. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
95. @ThreadInterrupt
@ThreadInterrupt
import groovy.transform.ThreadInterrupt
while (true) {
// eat lots of CPU
}
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
96. @ThreadInterrupt
@ThreadInterrupt
import groovy.transform.ThreadInterrupt
while (true) {
{ if (Thread.currentThread.isInterrupted())
throw new InterruptedException() }
// eat lots of CPU
}
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
97. @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)
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
98. @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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 34
99. @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...'
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 35
100. @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)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 36
101. @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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 37
102. @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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 38
103. @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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 39
104. @InheritConstructor
• Classes like Exception are painful when extended, as all
the base constructors should be replicated
class CustomException extends Exception {
CustomException() { super() }
CustomException(String msg) { super(msg) }
CustomException(String msg, Throwable t) { super(msg, t) }
CustomException(Throwable t) { super(t) }
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 40
105. @InheritConstructor
• Classes like Exception are painful when extended, as all
the base constructors should be replicated
import groovy.transform.*
@InheritConstructors
class CustomException extends Exception {
CustomException() { super() }
CustomException(String msg) { super(msg) }
CustomException(String msg, Throwable t) { super(msg, t) }
CustomException(Throwable t) { super(t) }
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 40
106. @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
}
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 41
107. @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
}
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 41
108. Miscelanous
• Compilation customizers
• Java 7 diamond operator
• Slashy and dollar slashy strings
• New GDK methods
• (G)String to Enum coercion
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 42
109. Compilation customizers
• Ability to apply some customization to the Groovy
compilation process
• Three available customizers
– ImportCustomizer
– ASTTransformationCustomizer
– SecureASTCustomizer
• But you can implement your own
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 43
110. Imports customizer
def configuration = new CompilerConfiguration()
def custo = new ImportCustomizer()
custo.addStaticStar(Math.name)
configuration.addCompilationCustomizers(custo)
def result = new GroovyShell(configuration)
.evaluate(" cos PI/3 ")
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 44
111. 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()
""")
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 45
112. 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 customizer
import 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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 46
135. (G)String to Enum coercion
enum Color {
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
136. (G)String to Enum coercion
enum Color {
red, green, blue
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
137. (G)String to Enum coercion
enum Color {
red, green, blue
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
138. (G)String to Enum coercion
enum Color {
red, green, blue
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
139. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
140. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
141. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
142. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
// implicit coercion
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
143. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
// implicit coercion
Color b = "blue"
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
144. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
// implicit coercion
Color b = "blue"
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
145. (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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
146. (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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
148. Launching remote scripts
• With the Groovy command, you can launch remote scripts
> groovy http://groovyconsole.appspot.com/raw/110001
• Be careful to what
youʼre executing :-)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 54
153. 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 58
154. Underscore in literals
• Now we can 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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 59
155. Multicatch
• One block for multiple exception caught
– rather than duplicating the block
try {
/* ... */
} catch(IOException | NullPointerException e) {
/* one block to treat 2 exceptions */
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 60
156. InvokeDynamic
• Groovy 1.9 will support JDK 7ʼs invokeDynamic
– an «indy» branch started recently
– compiler will have a flag for compiling against JDK 7
• Benefits
– more runtime performance!
– in the long run, will allow us to get rid of code!
• call site caching, thanks to MethodHandles
• metaclass registry, thanks to ClassValues
• will let the JIT inline calls more easily
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 61
157. Groovy Modularity
• Groovyʼs «all» JAR weighs in at 4MB
• Nobody needs everything
– Template engine, Ant scripting, Swing UI building...
• Provide a smaller core
– and several smaller JARs per feature
• Provide hooks for setting up EMCs / DGM methods, etc.
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 62
158. Static Type Checking
• Goal: make the Groovy compiler «grumpy»!
– and throw compilation errors (not at runtime)
• Not everybody needs dynamic features all the time
– think Java libraries scripting
• Grumpy should...
– tell you about your method or variable typos
– complain if you call methods that donʼt exist
– shout on assignments of wrong types
– infer the types of your variables
– figure out GDK methods
– etc...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 63
159. A typo in your variable or method names
import groovy.transform.StaticTypes
void method() {}
@TypeChecked test() {
// Cannot find matching method metthhoood()
metthhoood()
def name = "Guillaume"
// variable naamme is undeclared
println naamme
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 64
160. A typo in your variable or method names
import groovy.transform.StaticTypes
void method() {}
@TypeChecked test() {
// Cannot find matching method metthhoood()
metthhoood()
def name = "Guillaume"
// variable naamme is undeclared Compilation
println naamme errors!
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 64
161. Complain on wrong assignments
// cannot assign value of type... to variable...
int x = new Object()
Set set = new Object()
def o = new Object()
int x = o
String[] strings = ['a','b','c']
int str = strings[0]
// cannot find matching method plus()
int i = 0
i += '1'
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 65
162. Complain on wrong assignments
// cannot assign value of type... to variable...
int x = new Object()
Set set = new Object() Compilation
errors!
def o = new Object()
int x = o
String[] strings = ['a','b','c']
int str = strings[0]
// cannot find matching method plus()
int i = 0
i += '1'
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 65
163. Complain on wrong return types
String method() { 'String' }
// cannot assign value of type String...
int x = method()
// checks if/else branch return values
int method() {
if (true) { 'String' }
else { 42 }
}
// works for switch/case & try/catch/finally
// transparent toString() implied
String greeting(String name) {
def sb = new StringBuilder()
sb << "Hi" << name
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 66
164. Complain on wrong return types
String method() { 'String' }
// cannot assign value of type String...
int x = method() Compilation
errors!
// checks if/else branch return values
int method() {
if (true) { 'String' }
else { 42 }
}
// works for switch/case & try/catch/finally
// transparent toString() implied
String greeting(String name) {
def sb = new StringBuilder()
sb << "Hi" << name
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 66
165. Type inference
@TypeChecked test() {
def name = " Guillaume "
// String type infered (even inside GString)
println "NAME = ${name.toUpperCase()}"
// Groovy GDK method support
// (GDK operator overloading too)
println name.trim()
int[] numbers = [1, 2, 3]
// Element n is an int
for (int n in numbers) {
println n
}
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 67
166. Staticly checked method & dynamic method
@TypeChecked
String greeting(String name) {
// call method with dynamic behavior
// but with proper signature
generateMarkup(name.toUpperCase())
}
// usual dynamic behavior
String generateMarkup(String name) {
def sw = new StringWriter()
new MarkupBuilder(sw).html {
body {
div name
}
}
sw.toString()
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 68
167. Bytecode viewer
• Groovy Consoleʼs
bytecode viewer
from the AST
browser window
– select class
generation phase
– select a class node
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 69
168. Disable Global AST transformations
// witout a specific configuration, the AST builder works
def shell = new GroovyShell()
shell.evaluate(script) // passes
def config = new CompilerConfiguration()
config.disabledGlobalASTTransformations =
['org.codehaus.groovy.ast.builder.AstBuilderTransformation']
def script = '''
import org.codehaus.groovy.ast.builder.AstBuilder
new AstBuilder().buildFromCode { "Hello" }
'''
// now with the configuration in place,
// the AST builder transform is not applied
shell = new GroovyShell(config) // <‐‐ with the configuration
shouldFail {
shell.evaluate(script) // fails
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 70
170. Thank you!
e
L aforg pment
aume vy Develo
Guill Groo m
Hea d of g mail.co
aforge@
mail: gl glaforge e
E @ o /glaforg
T witter : http://gplus.t
Go ogle+:
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 72