Groovy overview, DSLs and ecosystem - Mars JUG - 2010
1. Groovy
Overview, DSLs, ecosystem
Presentation given for the
Mars JUG
by Guillaume Laforge
Groovy Project Manager
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
2. Guillaume Laforge
• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
at SpringSource / VMWare
• Initiator of the Grails framework
• Co-author of Groovy in Action
• Member of @lescastcodeurs
• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
Devoxx, The Spring Experience, SpringOne, JAX,
Dynamic Language World, IJTC, and more...
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 2
3. Contact information
• Email
– glaforge@gmail.com
• Twitter
– @glaforge
• Blog
– http://glaforge.free.fr/blog/groovy
• Groovy mailing-lists
– http://old.nabble.com/codehaus---Groovy-f11866.html
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 3
4. A little story
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 4
5. nd a
Ag e • Introduction to Groovy
– syntax basics
– useful APIs
• Domain-Specific
Languages
• Rich ecosystem
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 5
6. nd a
Ag e • Introduction to Groovy
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 6
7. Groovy in a few words
• Groovy is a dynamic language for the JVM
– with a Meta Object Protocol
– compiles directly to bytecode
– provides seamless Java interoperability
• Groovy was created in 2003, is hosted at
Codehaus, and is under the Apache license
• Relaxed grammar deriving from Java 5
– annotations, generics, static imports, enums, varargs...
– borrowed good ideas from Ruby, Python, Smalltalk
–flat learning curve for Java developers
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 7
8. Most popular alternative
language for the JVM
• In terms of...
– Poll and survey popularity
– Books available on the shelves
– Jobs on the job boards
– Integration in other products
– Download numbers
– Community activity
– Innovation
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 8
9. In terms of polls & surveys
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 9
10. In terms of books
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 10
11. In terms of jobs
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 11
12. In terms of integration in
other projects and products
• Groovy is integrated in many Open Source projects
and Commercial products
– Spring, IntelliJ IDEA, SAP Composition on Grails, RIFE,
Mule ESB, Apache Camel, eXo Platform, SOAP UI,
JBoss SEAM, XWiki, Oracle OC4J, SpringSource
tcServer, Oracle Data Integrator, Canoo WebTest,
Oracle Busines Components, IBM WebSphere sMash,
CodeStreet MarketData Works, SpringSource Hyperic
HQ
– Mutual of Omaha, US National Cancer Institute,
Patterson Institute for Cancer Research, IRSN...
• and certainly many more I’ve forgotten!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 12
13. In terms of download numbers
• Number of downloads per month
– 2003: a few hundreds
– 2005: ~5k
– 2008: ~35k
– 2009: ~70k
• Add to that number
– all the integrations...
– all the artifacts downloads from Maven’s repository!
• Highly successful OSS project!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 13
14. In terms of community activity
• Very high traffic on the mailing-lists
– 1500+ members
• Dedicated conferences
– Groovy Grails eXchange
– SpringOne 2GX
– GR8 Conference (Europe / USA)
– Excellent coverage of Groovy and Grails at all major
conferences around the world
• Dedicated podcast
– GrailsPodcast
• Dedicated online PDF magazine
– GroovyMag
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 14
15. In terms of innovation
• JAX Innovation Award
– Biggest German Java conference
• Groovy won first prize in 2007
– Grails scored second in 2008
– Spring arrived first in 2006
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 15
16. Features at a glance
• Fully Object-Oriented: same as Java
• Closures: reusable/assignable code blocks
• Properties: no more boring getters/setters
• Optional typing: your choice!
• Various shortcut notations: native syntax for lists,
maps, ranges, regex...
• Handy wrapper APIs: XML, JDBC, template
engine, Swing UIs, collection methods...
• Strong ability for authoring DSLs
• A rich and lively ecosystem of additional modules
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 16
17. Mandatory Hello World
• Java public class HelloWorld {
private String name;
style...
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String greet() {
return "Hello " + name;
}
) {
public static void main(String[] args
ld();
HelloWorld helloWorld = new HelloWor
helloWorld.setName("Groovy");
));
System.out.println(helloWorld.greet(
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 17
18. Mandatory Hello World
• Groovy public class HelloWorld {
private String name;
style...
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String greet() {
return "Hello " + name;
}
) {
public static void main(String[] args
ld();
HelloWorld helloWorld = new HelloWor
helloWorld.setName("Groovy");
));
System.out.println(helloWorld.greet(
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 18
19. Mandatory Hello World
• Groovy
style...
class HelloWorld {
String name
String greet() { "Hello $name" }
}
def helloWorld =
new HelloWorld(name: "Groovy")
println helloWorld.greet()
Take 2!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 19
20. Syntax basics
• Grammar deriving from Java 5
– annotations, enums, static imports, generics...
• Usual Java keywords, control structures...
• Same APIs
– strings, collections, regex, security, threading...
• Same Object Orientation
– No impedance mismatch!
– Flat learning curve for Java developers!
• But offers additional native syntax constructs
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 20
21. On Java interoperability
• Groovy is the alternative JVM language providing
the best integration with Java JInterface GInterface
<<implements>> <<implements>>
• Mix and match Groovy and Java GClass JClass
– even with a cyclic language dependency
JClass GClass
• Groovy comes with a «joint compiler»
– compiling Groovy as Java stubs
– calling the Javac compiler
– compiling the Groovy classes
• Excellent IDE support (Eclipse/IntelliJ/NetBeans)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 21
22. Native syntax constructs
• Lists
def someNumbers = [1, 2, 3, 5, 7, 11]
• Ranges
def range = 1..18
• Maps
def states = [CA: ‘California’, TX: ‘Texas’]
• Regular expressions
~/fo*/
‘foo’ =~ /fo*/
‘foo’ ==~ /fo*/
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 22
23. GStrings
• Sexiest feature of the language!
• Ability to embed variables
inside strings
def firstname = "Guillaume"
def lastname = "${firstname} Laforge"
e"
assert lastname == "Guillaume Laforg
def date = "Today is: ${new Date()}"
def multiline = """Hello,
How are you?"""
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 23
24. Closures
• A reusable / assignable code block
– CS 101 for a proper definition
}
def helloPrinter = { println "hello"
helloPrinter()
def twice = { it * 2 }
assert twice(3) == 6
assert twice('foo') == 'foofoo'
def mult = { int a, int b -> a * b }
def multBy5 = mult.curry(5)
assert multBy5(4) == 20
def apply(closure) { closure() }
apply { /* do something */ }
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 24
25. Time savers
• The «Groovy Truth»
def blank = ""; assert !blank
def empty = []; assert !empty
• Safe graph navigation
def order = null
assert order?.customer?.address == null
• Elvis operator
def na me = customer.name ?: "Unknown"
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 25
26. GDK: Groovy Development Kit
• Thanks to Groovy’s dynamic nature, we «decorate»
existing JDK classes to add new handy methods
– we can’t extend java.io.File or java.lang.String, can we?
n it }
new File("apache.log").eachLine { printl
(1..100).findAll { it % 2 == 1 }
speakers.groupBy { it.lastname }
"123".padLeft(5, '0')
"ls -la".execute()
)
"R3Jvb3Z5IHJvY2tzIQ==".decodeBase64(
Th read.start { /* code to execute */ }
• Add your own extensions!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 26
27. Now onto APIs!
• After this language crash course,
let’s have a look at the APIs Groovy provides:
– Markup builders and slurpers
– Swing builder
– Template engine
– JDBC facilities
– JMX builder
– Ant scripting
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 27
28. Markup builder
• Producing markup content
new MarkupBuilder().languages {
language(name: "Groovy") {
feature(coolness: "low", "SQL")
)
feature(coolness: "high", "Template"
}
language(name: "Perl")
}
• Will yield
<languages>
<language name = "Groovy">
<feature coolness="low">SQL</feature>
ature>
<feature coolness="high">Template</fe
</language>
<language name: "Perl"/>
</languages>
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 28
29. XML slurper
• Easily parsing and consumming XML content
• Navigating through the nodes as an object graph
def xml = """
<languages>
<language name="Groovy">
<feature coolness="low">SQL</feature>
ature>
<feature coolness="high">Template</fe
</language>
<language name="Perl"/>
</languages>"""
(xml)
def root = new XmlSlurper().parseText
t()
println root.language.feature[1].tex
] == "low" }
root.lan guage.feature.findAll{ it['@coolness'
.each{ println it.text() }
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 29
30. Swing builder
• Creating Swing UI with a programmatic descriptive
Domain-Specific Language
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
def count = 0
new SwingBuilder().edt { ow: true) {
fram e(title: 'Frame', size: [300,300], sh
borderLayout()
tton!",
textlabel = label(text: "Click the bu
constraints: BL.NORTH)
button(text: 'Click Me',
actionPerformed: {
count++
me(s)."
textlabel.text = "Clicked ${count} ti
println "clicked"},
constraints:BL.SOUTH)
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 30
31.
32. Template engine
• Templating capabilities, with embedded GStrings,
and scriptlet notation
ne
import groovy.text.SimpleTemplateEngi
def text = '''
Dear <%= firstname %>
%>.
So nice to meet you in <% print city
${signed}'''
e",
def binding = [fir stname: "Guillaume", city: "The Hagu
signed: "MrG"]
()
def engine = new SimpleTemplateEngine
ke(binding)
temp late = engine.createTemplate(text).ma
• A template servlet also exists
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 32
33. JDBC facilities
• Transparent resource handling thanks to closures
)
def sql = Sql.newInstance(url, usr, pwd, driverar)")
sql.execut e("insert into table values ($foo, $b, b])
, [a
sql.ex ecute("insert into table values(?,?)" .name }
it
sql.ea chRow("select * from USER") { print
ER")
def list = sql.rows("select * from US
• A poorman’s dataset notion
def set = sql.dataSet("USER")
set.add(name: "Johnny", age: 33) ame }
set.each { user -> println user.n 42 }
se t.findAll { it.age > 22 && it.age <
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 33
34. JMX Builder
• Expose, configure JMX beans, export operations,
create timers, event handling with closures, and
more...
def jmx = new JmxBuilder()
def beans = jmx.export {
bean(new CpuLoadMonitor())
bean(new DiskOccupationMonitor())
}
• You could easily monitor your Spring application’s
exposed JMX beans through some Groovy script!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 34
35. Ant builder
• Script and reuse any Ant task
– FTP, SSH, Javac, file handling, etc.
new AntBuilder().sequential {
def buildClasses = "build/classes"
// create classes directory
mkdir dir: buildClasses
// compile sources
lasses
javac srcdir: "src", destdir: buildC
// jar everything
dClasses
jar destfile: "my.jar", basedir: buil
}
• Used in Gant and Gradle
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 35
36. Grape: a great way for sharing
Groovy scripts
• Grape: Groovy Advanced Packagning Engine
• You can «grab» dependencies in your scripts
– first run will download the dependencies
– next runs, the dependencies will be found in the ivy
cache on your system
jdk15")
@Grab("net.sf.json-lib:json-lib:2.3:
import net.sf.json.groovy.*
assert new JsonSlurper().parseText(
new JsonGroovyBuilder().json { aume")
book(title : "Groovy in Action", author: "Guill
}.toString()
).book.title == "Groovy in Action"
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 36
37. Benefits of the Groovy APIs
• Easily share scripts thanks to Grape
– no need to package JARs
–automate all repetitive tasks with Ant builder
• Simple to create reports or generate code with
markup builders or template engines
• You can migrate / inject / modify data with the
SQL facilities accessing your database through JDBC
• Create simple Swing UIs to interact with backends
• You can monitor server farms through JMX
builder
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 37
38. Spring integration (1/2)
•Groovy integrated in Spring since 2.0
–ability to define beans in Groovy
–to monitor changes of Groovy beans on the filesystem
–to modify the behaviour of Groovy scripts and beans
–to inline Groovy scripts with <lang:inline-script>
<lang:groovy id="messenger"
refresh-check-delay="5000"
roovy">
script-source="classpath:Messenger.g
"Hi" />
<lang:property name="message" value=
</lang:groovy>
BookingService">
<bean id ="bookingService" class="x.y.Default
nger" />
<property name="messenger" ref="messe
</bean>
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 38
39. Spring integration (2/2)
• Grails provides a Spring bean builder
– for programmatically define Spring configurations
– more flexible than pure XML declarative descriptions
)
de f bb = new grails.spring.BeanBuilder(
bb.beans {
adder(AdderImpl)
calcBean(CalcImpl)
}
t()
def ctx == bb.createApplicationContex
def calc = ctx.getBean(‘calcBean’)
println calc.doAdd(3, 4)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 39
40. Question & Answers
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 40
41. nd a
Ag e • Domain-Specific
Languages
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 41
44. Developer producing LOLCODE
HAI
CAN HAS STDIO?
I HAS A VAR
IM IN YR LOOP
UP VAR!!1
VISIBLE VAR
IZ VAR BIGGER THAN 10? KTHXBYE
IM OUTTA YR LOOP
KTHXBYE
48. DSL: a potential solution?
•Use a more expressive language
than a general purpose one
•Share a common metaphore of understanding
between developers and subject matter experts
•Have domain experts help with the design
of the business logic of an application
•Avoid cluttering business code with
too much boilerplate technical code
•Cleanly separate business logic from application code
•Let business rules have their own lifecycle
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 48
49. Towards more readibility (1)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 49
50. Towards more readibility (1)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 49
51. Towards more readibility (1)
20%
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 49
52. Towards more readibility (2)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 50
53. Towards more readibility (2)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 50
54. Towards more readibility (2)
80%
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 50
55. A collection of DSLs
• In our everyday life, we’re surrounded by DSLs
– Technical dialects
– Notations
– Business languages
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 51
56. Technical dialects
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 52
63. Real-life Groovy examples
• Anti-malaria drug resistance simulation
• Human Resources employee skills representation
• Insurance policies risk calculation engine
• Loan acceptance rules engine for a financial
platform
• Mathematica-like lingua for nuclear safety
simulations
• Market data feeds evolution scenarios
• and more...
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 59
64. Three levels of techniques
Flexible & Meta- AST
malleable syntax programming transformations
• scripts • POGO • AST traversal
• optional typing • categories • local
• native syntax • builders transformations
constructs • custom MetaClass • global
• parens / semi • ExpandoMetaClass transformations
ommission • hooks into Antlr
• named arguments
• BigDecimal
• operator overloading
• closures
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 60
65. A flexible & malleable syntax
• No need to write full-blown classes, use scripts
• Optional typing (def)
– in scripts, you can even omit the def keyword
• Native syntax constructs
• Parentheses & semi-colons are optional
• Named arguments
• BigDecimal by default for decimal numbers
• Closures for custom control structures
• Operator overloading
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 61
66. Scripts vs classes
• Hide all the boilerplate technical code
– an end-user doesn’t need to know about classes
– public class Rule {
public static void main(String[] args) {
System.out.println(“Hello”);
}
}
– println “Hello”
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 62
67. Optional typing
• No need to bother with types or even generics
– unless you want to!
• Imagine an interest rate lookup table method
returning some generified type:
–Rate<LoanType, Duration, BigDecimal>[]
lookupTable() { ... }
def table = lookupTable()
• No need to repeat the horrible generics type info!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 63
68. Native syntax constructs
• Lists
– [Monday, Tuesday, Wednesday]
• Maps
– [CA: ‘California’, TX: ‘Texas’]
• Ranges
– def bizDays = Monday..Friday
– def allowedAge = 18..65
– You can create your own custom ranges
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 64
69. Optional parens & semis
• Make statements and expressions
look more like natural languages
– move(left);
– move left
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 65
70. Named arguments
• In Groovy you can mix named and unnamed
arguments for method parameters
– named params are actually put in a map parameter
– plus optional parens & semis
• take 1.pill,
of: Chloroquinine,
after: 6.hours
• Corresponds to a method signature like:
– def take(Map m, MedicineQuantity mq)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 66
71. BigDecimal by default
• Main reason why financial institutions often decide
to use Groovy for their business rules!
– Although these days rounding issues are overrated!
• Java vs Groovy for a simple interpolation equation
• BigDecimal uMinusv = c.subtract(a);
BigDecimal vMinusl = b.subtract(c);
BigDecimal uMinusl = a.subtract(b);
return e.multiply(uMinusv)
.add(d.multiply(vMinusl))
.divide(uMinusl, 10, BigDecimal.ROUND_HALF_UP);
• (d * (b - c) + e * (c - a)) / (a - b)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 67
72. Custom control structures,
thanks to closures
• When closures are last, they can be put “out” of the
parentheses surrounding parameters
• unless (account.balance > 100.euros,
{ account.debit 100.euros })
• unless (account.balance > 100.euros) {
account.debit 100.euros
}
• Signature def unless(boolean b, Closure c)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 68
73. Operator overloading
a + b
a - b
a.plus(b)
a.minus(b)
• Currency amounts
a * b a.multiply(b) – 15.euros + 10.dollars
a / b a.divide(b)
a % b a.modulo(b) • Distance handling
a ** b a.power(b) – 10.kilometers - 10.meters
a | b a.or(b)
a & b a.and(b)
• Workflow, concurrency
a ^ b a.xor(b)
a[b] a.getAt(b)
– taskA | taskB & taskC
a << b a.leftShift(b)
a >> b a.rightShift(b) • Credit an account
+a a.unaryPlus() – account << 10.dollars
-a a.unaryMinus() account += 10.dollars
~a a.bitwiseNegate() account.credit 10.dollars
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 69
75. Groovy’s MOP
• All the accesses to methods, properties,
constructors, operators, etc. can be intercepted
thanks to the MOP
• While Java’s behavior is hard-wired at compile-
time in the class
• Groovy’s runtime behavior is adaptable at
runtime through the metaclass
• Different hooks for changing the runtime behavior
– GroovyObject, custom MetaClass implementation,
categories, ExpandoMetaClass
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 71
76. GroovyObject
• All instances of classes created in Groovy
implement the GroovyObject interface:
–get/setProperty(String name)
–invokeMethod(
String name, Object[] params)
–propertyMissing(String name)
–methodMissing(
String name, Object[] params)
–get/setMetaClass(MetaClass mc)
• A GO can have “pretended” methods and properties
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 72
77. MetaClass
• The core of Groovy’s MOP system
–invokeConstructor()
–invokeMethod() and invokeStaticMethod()
–invokeMissingMethod()
–getProperty() and setProperty()
–getAttribute() and setAttribute()
–respondsTo() and hasProperty()
• MetaClasses can change the behavior of existing
third-party classes — even from the JDK
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 73
78. ExpandoMetaClass
• A DSL for MetaClasses!
• MoneyAmount.metaClass.constructor = { ... }
Number.metaClass.getDollars = { ... }
Distance.metaClass.toMeters = { ... }
Distance.metaClass.static.create = { ... }
• To avoid repetition of Type.metaClass, you can pass
a closure to metaClass { ... }
• The delegate variable in closure represents the
current instance, and it the default parameter
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 74
80. A builder for HR
• softskills {
ideas {
capture 2
formulate 3
}
...
}
knowhow {
languages {
java 4
groovy 5
}
...
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 76
81. A builder for HR
• softskills {
ideas {
capture 2
formulate 3
}
...
}
knowhow {
languages {
java 4
groovy 5
}
...
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 76
82. Builders
• Builders are...
– a mechanism for creating any tree-structered graph
– the realization of the GoF builder pattern at the syntax level
in Groovy
– simply a clever use of chained method invocation, closures,
parentheses omission, and use of the GroovyObject methods
• Existing builders
– XML, Object graph, Swing, Ant, JMX, and more...
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 77
83. The clever trick
• GroovyObject#invokeMethod() is used to catch all
non-existing method calls in the context of the
builder
• The nesting of closures visually shows the level of
nesting / depth in the tree
• builder.m1(attr1:1, attr2:2, { builder.m2(..., {...}) }
becomes equivalent to
builder.m1(attr1:1, attr2:2) { m2(...) {...} }
thanks to parens omission
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 78
84. Adding properties to numbers
• Three possible approaches
– create a Category
•a category is a kind of decorator for default MCs
– create a custom MetaClass
•a full-blown MC class to implement and to set on the
POGO instance
– use ExpandoMetaClass
•friendlier DSL approach but with a catch
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 79
85. With a Category
• class DistanceCategory {
static Distance getMeters(Integer self) {
new Distance(self, Unit.METERS)
}
}
use(DistanceCategory) {
100.meters
}
• Interesting scope: thread-bound & lexical
• Have to surround with “use”
– but there are ways to hide it
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 80
86. With an ExpandoMetaClass
• Number.metaClass.getMeters = {->
new Distance(delegate, Unit.METERS)
}
100.meters
• Works for the class hierarchy for POJOs, and a flag
exists to make it work for POGOs too
• But the catch is it’s really a global change, so
beware EMC enhancements collisions
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 81
87. Compile-time
metaprogramming
• Groovy 1.6 introduced AST Transformations
• Compile-time == No runtime performance penalty!
Transformation
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 82
88. Compile-time
metaprogramming
• With metaprogramming, Groovy’s able to modify
the behaviour of programs... at runtime
• Groovy 1.6 introduced AST Transformations
– AST: Abstract Syntax Tree
– Ability to change what’s being compiled at compile-time!
•No runtime impact!
•Lets you change the semantics of your programs!
•Nice way of implementing patterns and removing boiler-
plate technical code
• Two kinds of transformations: global and local
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 83
89. AST Transformations
• Two kinds of transformations
– Global transformations
•applicable to all compilation units
– Local transformations
•applicable to marked program elements
•using specific marker annotations
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 84
90. AST Transformations
in Groovy 1.6
• Several (local) transformations finds their way
– @Singleton — okay, not really a pattern :-)
– @Immutable, @Lazy, @Delegate
– @Newify
– @Category and @Mixin
– @PackageScope
– Swing’s @Bindable and @Vetoable
– Grape’s @Grab
• Let’s have a look at some of them
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 85
91. The @Singleton anti-pattern
•The evil Java singleton
public class Evil {
new Evil();
public static final Evil instance =
privavte Evil() {}
; }
Evil getInstance() { return instance
}
•In Groovy now:
@Singleton class Evil {}
•A lazy version also:
@Singleton(lazy = true) class Evil {}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 86
92. @Immutable
• To properly implement immutable classes
– No mutators (state musn’t change)
– Private final fields
– Defensive copying of mutable components
– Proper equals() / hashCode() / toString() for
comparisons, or for keys in maps, etc.
@I mmutable class Coordinates {
Double lat, lng
}
5)
def c1 = new Coordinates(lat: 48.8, lng: 2.
de f c2 = new Coordinates(48.8, 2.5)
assert c1 == c2
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 87
93. @Lazy, not just for lazy dudes!
• When you need to lazily evaluate or instantiate
complex data structures for class fields, mark them
with the @Lazy annotation
class Dude {
@Lazy pets = retrieveFromSlowDB()
}
• Groovy will handle the boiler-plate code for you!
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 88
94. @Delegate
Not just for managers!
•You can delegate to fields of your class
–Think multiple inheritance
class Employee {
def doTheWork() { "done" }
}
class Manager {
@Deleg ate Employee slave = new Employee()
}
def god = new Manager()
assert god.doTheWork() == "done"
•Damn manager will get all the praise...
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 89
95. Global transformations
• Implement ASTTransformation
• Annotate the transfo specifying a compilation phase
• @GroovyASTTransformation(phase=CompilePhase.CONVERSION)
public class MyTransformation
implements ASTTransformation {
public void visit(ASTNode[] nodes, SourceUnit unit)
{ ... }
}
• For discovery, create the file META-INF/services/
org.codehaus.groovy.transform.ASTTransformation
• Add the fully qualified name of the class in that file
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 90
96. Local transformations
• Same approach as Globale transformations
• But you don’t need the META-INF file
• Instead create an annotation to specify on which
element the transformation should apply
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.METHOD])
@GroovyASTTransformationClass(
["fqn.MyTransformation"])
public @interface WithLogging {...}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 91
97. Example: the Spock
framework
• Changing the semantics of the original code
• But keeping a valid Groovy syntax
@Speck
class HelloSpock {
to?"() {
def "can you figure out what I'm up
expect:
name.size() == size
where:
name | size
"Kirk" | 4
"Spock" | 5
"Scotty" | 6
}
}
• Check out http://www.spockframework.org
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 92
98. Various integration
mechanisms
• Java 6’s javax.script.* APIs (aka JSR-223)
• Spring’s language namespace
• Groovy’s own mechanisms
• But a key idea is to externalize those DSL programs
– DSL programs can have their own lifecycle
– no need to redeploy an application because of a rule
change
– business people won’t see the technical code
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 93
99. Java 6’s javax.script.* API
• Groovy 1.6 provides its own implementation of the
javax.script.* API
• ScriptEngineManager mgr =
new ScriptEngineManager();
ScriptEngine engine =
mgr.getEngineByName(“Groovy”);
String result = (String)engine.eval(“2+3”);
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 94
100. Spring’s lang namespace
• POGOs (Plain Old Groovy Objects) can be pre-
compiled as any POJO and used interchangeably
with POJOs in a Spring application
• But Groovy scripts & classes can be loaded at
runtime through the <lang:groovy/> namespace
and tag
• Reloadable on change
• Customizable through a custom MetaClass
• <lang:groovy id="events"
script-source="classpath:dsl/eventsChart.groovy"
customizer-ref="eventsMetaClass" />
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 95
101. Groovy’s own mechanisms
• Eval
– for evaluating simple expressions
• GroovyShell
– for more complex scripts and DSLs
• GroovyClassLoader
– the most powerful mechanism
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 96
102. Eval
• Simple mechanism to evaluate math-like formulas
• Eval.me ( ‘3*4’)
Eval.x (1, ‘3*x + 4’)
Eval.xy (1, 2, ‘x + y’)
Eval.xyz(1, 2, 3, ‘x * y - z’)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 97
103. GroovyShell
• A Binding provides a context of execution
– can implement lazy evaluation if needed
• A base script class can be specified
• def binding = new Binding()
binding.mass = 22.3
binding.velocity = 10.6
def shell = new GroovyShell(binding)
shell.evaluate(“mass * velocity ** 2 / 2”)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 98
104. GroovyClassLoader
• Most powerful mechanism
– could also visit or change the AST
– scripts & classes can be loaded from elsewhere
– more control on compilation
• GroovyClassLoader gcl =
new GroovyClassLoader();
Class clazz = gcl.parseClass(
new File(“f.groovy”));
GroovyObject instance =
(GroovyObject)clazz.newInstance();
instance.setMetaClass(customMC);
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 99
105. Externalize business rules
• Although Groovy DSLs can be embedded in normal
Groovy classes, you should externalize them
• Store them elsewhere
– in a database, an XML file, etc.
• Benefits
– Business rules are not entangled
in technical application code
– Business rules can have their own lifecycle, without
requiring application redeployments
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 100
106. A few considerations
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 101
114. Various levels
of sandboxing
• Groovy supports the usual
Java Security Managers
• Use metaprogramming tricks to prevent calling /
instanciating certain classes
• Create a special GroovyClassLoader AST code
visitor to filter only the nodes of the AST you want
to keep
– ArithmeticShell in Groovy’s samples
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 109
115. Test, test, test!
• Don’t just test for nominal cases
– Explicitely test for errors!
• Ensure end-users get meaninful error messages
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 110
116. Question & Answers
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 111
117. nd a
Ag e • The Groovy Ecosystem
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 112
118. The Groovy Ecosystem
• Many projects based on Groovy
• Serve various purposes:
– build applications (ie. frameworks)
•Grails (web apps), Gaelyk (Google App Engine),
Griffon (Swing apps)
– enhanced testing
•Easyb (BDD), Spock, Gmock (mocking), SoapUI (WS)
– help building projects
•Gant (ant sugar), Gradle (adhoc build system)
– web services interaction
•HTTPBuilder (REST), GroovyWS (SOAP)
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 113
119. Gaelyk
•Groovy on Google App Engine
– Lightweight Groovy tooking for writing
applications in Groovy on GAE/J
– Leverages Groovlets and
Groovy’s template engine
– http://gaelyk.appspot.com
• Groovy Web Console
– http://groovyconsole.appspot.com
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 114
120. GPars
• Actors, dataflow,
concurrency, and more
– for harnessing our
multicore platforms
• GPars web site:
– http://gpars.codehaus.org
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 115
121. Easyb (1/4)
• From the website:
– « Easyb is a behavior driven development (BDD)
framework for the Java platform. By using a specification
based Domain-Specific Language, Easyb aims to enable
executable, yet readable documentation »
• Write specifications in Groovy
• Run them from CLI, Maven, or Ant
– provides various report formats
• BDD == given/when/then paradigm
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 116
122. Easyb (2/4)
• First, let’s write a story
given "an invalid zip code"
itialized"
and "given the zipcodevalidator is in
lid zip code"
wh en "validate is invoked with the inva
return false"
then "the validator instance should
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 117
123. Easyb (3/4)
• Let’s write the test itself
given "an invalid zip code", {
invalidzipcode = "221o1"
}
d", {
and "giv en the zipcodevalidator is initialize
zipvalidate = new ZipCodeValidator()
}
p code", {
when "val idate is invoked with the invalid zi
pcode)
va lue = zipvalidate.validate(invalidzi
}
e", {
then "the validator instance should return fals
value.shouldBe false
}
• Afterwards, write the code that make the test pass
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 118
124. Easyb (4/4)
• There’s also the specification format
instance", {
before "initialize zipcodevalidator
;
zipvalidate = new ZipCodeValidator()
}
{
it "should deny invalid zip codes", zip ->
[" 221o1", "2210", "22010-121o"].each {
zipvalidate.validate(zip).is false
}
}
{
it "should accept valid zip codes",
{ zip ->
["22101", "22100", "22010-1210"].each
ue
zipvalidate.validate(zip).shouldBe tr
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 119
125. Spock (1/3)
• From the horse’s mouth:
– « Spock is a testing and specification framework for Java
and Groovy applications. What makes it stand out from
the crowd is its beautiful and highly expressive
specification language. »
cification {
cl ass HelloSpock extends spock.lang.Spe
() {
def "can you figure out what I'm up to?"
expect:
name.size() == size
where:
y"]
name << ["Kirk", "Spock", "Scott
size << [4, 5, 6]
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 120
126. Spock (2/3)
• Extensible (but transparent) use of AST
transformations to «pervert» the Groovy language
– reuse of labels for the BDD actions
• Spock brought Groovy 1.7’s enhanced asserts
Condition not satisfied:
max(a, b) == c
| | | | |
3 1 3 | 2
false
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 121
127. Spock (3/3)
• Another example of the expressive language
once"() {
def "subscribe rs receive published events at least
when: publisher.send(event)
vent)
then: (1.._) * subscriber.receive(e
"]
where: ev ent << ["started", "paused", "stopped
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 122
128. GMock (1/3)
• GMock is a mocking framework for Groovy
path/file.txt"))
File mo ckFile = mock(File, constructor("/a/
")
mockFile.getName().returns("file.txt
play {
")
def file = new File("/a/path/file.txt
()
assertEquals "file.txt", file.getName
}
• Mocking capabilities
– method calls – constructor calls
– property access – time matching
– static calls – order matching
– partial mocks – regex method matching
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 123
129. GMock (2/3)
• Mocking method calls
def loader = mock()
loader.put("fruit").returns("apple")
play {
fruit")
assertEquals "apple", loader.put("
}
• Mock static calls
def mockMath = mock(Math)
)
mockMath.static.random().returns(0.5
play {
assertEquals 0.5, Math.random()
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 124
130. GMock (3/3)
• Expecting exceptions
ception, "an exception")
loader.put ("throw exception").raises(RuntimeEx
• Time matching
– never, once, atLeastOnce, atMostOnce, stub, times,
atLeast, atMost
)
mockLo ader.load(2).returns(3).atLeastOnce(
play {
2)
assertEquals 3, mockLoader.load(
2)
assertEquals 3, mockLoader.load(
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 125
131. Gant
• Gant is a tool for scripting Ant tasks using Groovy
instead of XML to specify the logic
includeTargets << gant.targets.Clean
]
cleanPattern << ['**/*~', '**/*.bak'
cleanDirectory << 'build'
uff.') {
target(stuff: 'A target to do some st
println 'Stuff'
depends clean
Ant.'
echo message: 'A default message from
otherStuff()
}
her stuff') {
target (otherStuff: 'A target to do some ot
println 'OtherStuff'
Ant.'
echo message: 'Another message from
clean()
}
setDefaultTarget stuff
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 126
132. Gradle (1/2)
• From the website:
« Gradle is an enterprise-grade build system providing:
– A very flexible general purpose build tool like Ant
– Switchable, build-by-convention frameworks à la Maven,
for Java, Groovy and Scala projects
–Groovy build scripts
– Powerful support for multi-project builds
– Dependency management based on Ivy
– Full support for existing Maven or Ivy repository infra
– Support for transitive dependency management
– Ant tasks and builds as first class citizens. »
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 127
133. Gradle (2/2)
• For example, for a classical Java project
usePlugin ‘java’
repositories {
mavenCentral()
}
dependencies {
compile group: ‘commons-collection’,
n: ‘3.2’
module: ‘commons-collection’, versio
testCompile group: ‘junit’,
module: ‘junit’, version: ‘4.+’
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 128
134. Other build and quality tools
• You can use Ant, Gant, Maven (GMaven plugin) or
Gradle to build your projects
– fits nicely in an existing build and continuous
integration infrastructure
• A few Groovy-friendly tools provide handy metrics
– CodeNarc: provides various rules for static analysis of
your Groovy codebase (style, size, braces, naming...)
– Simian: detects duplication in your Groovy code base
– Cobertura, Clover: gives code coverage metrics
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 129
135. HTTPBuilder (1/3)
• HTTPBuilder provides a convenient builder API for
complex HTTP requests
)
def http = new HTTP Builder( 'http://ajax.googleapis.com'
http.request(GET, JSON) {
'
uri.path = '/ajax/services/search/web
Hobbes']
ur i.query = [v: '1.0', q: 'Calvin and
refox/3.0.4'
headers.'User- Agent' = 'Mozilla/5.0 Ubuntu/8.10 Fi
response.success = { resp, json ->
println resp.statusLine
json.responseData.results.each { Url}"
println " ${ it.titleNoFormatting} : ${it.visible
}
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 130
136. HTTPBuilder (2/3)
• Posting to a URL
import groovyx.net.http.HTTPBuilder
LENC
import static groovyx.net.http.ContentType.UR
tuses/' )
def htt p = new HTTPBuilder( 'http://twitter.com/sta
tpbuilder']
def postBody = [status: 'update!', source: 'ht
http.post( path: 'update.xml', body: postBody,
->
requestContentType: URLENC ) { resp
usLine}"
println "Tweet response status: ${resp.stat
assert resp.statusLine.statusCode == 200
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 131
137. HTTPBuilder (3/3)
• Posting XML content to a URL
http.request(POST, XML) {
body = {
auth {
user 'Bob'
password 'pass'
}
}
}
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 132
138. GroovyWS (1/2)
• Publishing and consuming WS-I
compliant SOAP web services
import groovyx.net.ws.WSClient
def proxy = new WSClient( asmx?WSDL",
"http://www.w3 schools.com/webservices/tempconvert.
this.class.classLoader)
proxy.initialize()
t(0)
def result = proxy.CelsiusToFahrenhei
grees Farhenheit"
println "You are probably freezing at ${result} de
• Can also deal with complex objects
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 133
139. GroovyWS (2/2)
• Publishing a service
– considering a service
class MathService { }
double add(do uble arg0, double arg1) { arg0 + arg1
g0 }
do uble square(double arg0) { arg0 * ar
}
– publishing the service
import groovyx.net.ws.WSServer
def server = new WSServer() /MathService")
server.setNode(" MathService", "http://localhost:6980
server.start()
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 134
140. nd a
Ag e • Summary
•Q & A
Copyright 2010 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 135