groovy to infinity and beyond - springone2gx - 2010 - guillaume laforge
TRANSCRIPT
Chicago, October 19 - 22, 2010
to Infinity and Beyond!
Guillaume Laforge — SpringSource
jeudi 21 octobre 2010
to Infinity and Beyond
jeudi 21 octobre 2010
Guillaume Laforge
• Groovy Project Manager• JSR-241 Spec Lead• Head of Groovy Development
at SpringSource• Initiator of the Grails framework• Founder of the Gaelyk toolkit• Co-author of Groovy in Action
• Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne2GX, JAX, Dynamic Language World, IJTC, and more...
3jeudi 21 octobre 2010
Bug killer... real insects with legs!
• Thanks to Groovy, with one hand left for coding, I’m still more productive than with Java!
4jeudi 21 octobre 2010
Bug killer... real insects with legs!
• Thanks to Groovy, with one hand left for coding, I’m still more productive than with Java!
4jeudi 21 octobre 2010
SpringOne 2GX 2010. All rights reserved. Do not distribute without permission.
Agenda
jeudi 21 octobre 2010
Agenda
• Past– Groovy 1.6 flashback
• Present– Groovy 1.7 novelties– A few Groovy 1.7.x refinements
• Future– What’s cooking for 1.8 and beyond
6jeudi 21 octobre 2010
looking into the Pastjeudi 21 octobre 2010
Big highlights of Groovy 1.6
• Greater compile-time and runtime performance• Multiple assignments• Optional return for if/else and try/catch/finally• Java 5 annotation definition• AST Transformations• The Grape module and dependency system• Various Swing related improvements• JMX Builder• Metaprogramming additions• JSR-223 scripting engine built-in• Out-of-the-box OSGi support
8jeudi 21 octobre 2010
Multiple assignement
// multiple assignmentdef (a, b) = [1, 2]assert a == 1 && b == 2
// with typed variablesdef (int c, String d) = [3, "Hi"]assert c == 3 && d == "Hi"
def geocode(String place) { [48.8, 2.3] }def lat, lng// assignment to existing variables(lat, lng) = geocode('Paris')
// classical variable swaping example(a, b) = [b, a]
9jeudi 21 octobre 2010
More optional return
// optional return for if statements
def m1() { if (true) 1 else 0}assert m1() == 1
// optional return for try/catch/finally
def m2(bool) { try { if (bool) throw new Exception()
1 } catch (any) { 2 } finally { 3 }}assert m2(true) == 2 && m2(false) == 1
10jeudi 21 octobre 2010
AST Transformation (1/2)
• Groovy 1.6 introduced AST Transformations• AST: Abstract Syntax Tree• Ability to change what’s being compiled by the Groovy
compiler... at compile time– No runtime impact!– Change the semantics of your programs! Even hijack the Groovy
syntax!– Implementing recurring patterns in your code base– Remove boiler-plate code
• Two kinds: global and local (triggered by anno)
11jeudi 21 octobre 2010
AST Transformations (2/2)
• Transformations introduced in 1.6– @Singleton– @Immutable, @Lazy, @Delegate– @Newify– @Category, @Mixin– @PackageScope– Swing’s @Bindable and @Vetoable– Grape’s own @Grab
12jeudi 21 octobre 2010
@Immutable
• To properly implement immutable classes– No mutations — state musn’t change– Private final fields– Defensive copying of mutable components– Proper equals() / hashCode() / toString()
for comparisons or fas keys in maps
@Immutable class Coordinates { Double lat, lng}def c1 = new Coordinates(lat: 48.8, lng: 2.5)
def c2 = new Coordinates(48.8, 2.5)assert c1 == c2
13jeudi 21 octobre 2010
Grab a grape!
• Simple distribution and sharing of Groovy scripts• Dependencies stored locally
– Can even use your own local repositories
@Grab(group = 'org.mortbay.jetty',
module = 'jetty‐embedded',
version = '6.1.0')
def startServer() { def srv = new Server(8080)
def ctx = new Context(srv , "/", SESSIONS)
ctx.resourceBase = "."
ctx.addServlet(GroovyServlet, "*.groovy")
srv.start()}
14jeudi 21 octobre 2010
Metaprogramming additions (1/2)
• ExpandoMetaClass DSL– factoring EMC changes
Number.metaClass { multiply { Amount amount ‐> amount.times(delegate) } div { Amount amount ‐> amount.inverse().times(delegate)
}}
15jeudi 21 octobre 2010
Metaprogramming additions (2/2)
• Runtime mixins
class FlyingAbility { def fly() { "I'm ${name} and I fly!" }
}
class JamesBondVehicle { String getName() { "James Bond's vehicle" }
}
JamesBondVehicle.mixin FlyingAbility
assert new JamesBondVehicle().fly() ==
"I'm James Bond's vehicle and I fly!"
16jeudi 21 octobre 2010
JMX Builder
• A DSL for handling JMX – in addition of Groovy MBean
// Create a connector serverdef jmx = new JmxBuilder()jmx.connectorServer(port:9000).start()
// Create a connector clientjmx.connectorClient(port:9000).connect()
//Export a beanjmx.export { bean new MyService() }
// Defining a timerjmx.timer(name: "jmx.builder:type=Timer",
event: "heartbeat", period: "1s").start()
// JMX listenerjmx.listener(event: "someEvent", from: "bean",
call: { evt ‐> /* do something */ })
17jeudi 21 octobre 2010
into the Present...jeudi 21 octobre 2010
Big highlights of Groovy 1.7
• Anonymous Inner Classes and Nested Classes• Annotations anywhere• Grape improvements• Power Asserts• AST Viewer• AST Builder• Customize the Groovy Truth!• Rewrite of the GroovyScriptEngine• Groovy Console improvements• SQL support refinements
19jeudi 21 octobre 2010
AIC and NC
• Anonymous Inner Classes and Nested Classes
20jeudi 21 octobre 2010
AIC and NC
• Anonymous Inner Classes and Nested Classes
For Java
copy’n paste
compatibility
sake :-)
20jeudi 21 octobre 2010
Annonymous Inner Classes
boolean called = false
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called = true
}}, 0)
sleep 100assert called
21jeudi 21 octobre 2010
Annonymous Inner Classes
boolean called = false
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called = true
}}, 0)
sleep 100assert called
{ called = true } as TimerTask
21jeudi 21 octobre 2010
Nested Classes
class Environment { static class Production extends Environment {}
static class Development extends Environment {}
}
new Environment.Production()
22jeudi 21 octobre 2010
Anotations anywhere
• You can now put annotations– on imports– on packages– on variable declarations
• Examples with @Grab following...
23jeudi 21 octobre 2010
Grape improvements (1/4)
• @Grab on import
@Grab(group = 'net.sf.json‐lib',
module = 'json‐lib', version = '2.3', classifier = 'jdk15')import net.sf.json.groovy.*
assert new JsonSlurper().parseText(
new JsonGroovyBuilder().json {
book(title: "Groovy in Action",
author: "Dierk König et al")
}.toString()).book.title == "Groovy in Action"
24jeudi 21 octobre 2010
Grape improvements (2/4)
• Shorter module / artifact / version parameter– Example of an annotation on a variable declaration
@Grab('net.sf.json‐lib:json‐lib:2.3:jdk15')
def builder = new net.sf.json.groovy.JsonGroovyBuilder()
def books = builder.books { book(title: "Groovy in Action", author: "Dierk Koenig")
}assert books.toString() == '{"books":{"book":{"title":"Groovy in Action",' +
'"author":"Dierk Koenig"}}}'
25jeudi 21 octobre 2010
Grape improvements (3/4)
• Groovy 1.7 introduced Grab resolver– For when you need to specify a specific repository
for a given dependency
@GrabResolver( name = 'restlet.org', root = 'http://maven.restlet.org')
@Grab('org.restlet:org.restlet:1.1.6')
import org.restlet.Restlet
26jeudi 21 octobre 2010
Grape improvements (4/4)
• Groovy 1.7.5 even further shrinks the grab resolver definition:
27
@GrabResolver('http://maven.restlet.org')
@Grab('org.restlet:org.restlet:1.1.6')
import org.restlet.Restlet
jeudi 21 octobre 2010
Power Asserts (1/2)
• Much better assert statement!– Invented and developed in the Spock framework
• Given this script...
def energy = 7200 * 10**15 + 1def mass = 80def celerity = 300000000
assert energy == mass * celerity ** 2
28jeudi 21 octobre 2010
Power Asserts (2/2)
• You’ll get a more comprehensible output
29jeudi 21 octobre 2010
Easier AST Transformations
• AST Transformations are a very powerful feature• But are still rather hard to develop
– Need to know the AST API closely
• To help with authoring your own transformations, we’ve introduced– the AST Viewer in the Groovy Console– the AST Builder
30jeudi 21 octobre 2010
AST Viewer
31jeudi 21 octobre 2010
AST Builder
// Ability to build AST parts
// ‐‐> from a Stringnew AstBuilder().buildFromString(''' "Hello" '''
)
// ‐‐> from codenew AstBuilder().buildFromCode { "Hello" }
// ‐‐> from a specification
List<ASTNode> nodes = new AstBuilder().buildFromSpec {
block { returnStatement {
constant "Hello"
} }}
32jeudi 21 octobre 2010
Customize the Groovy Truth!
• Ability to customize the truth by implementing a boolean asBoolean() method
class Predicate { boolean value boolean asBoolean() { value }
}
def truePred = new Predicate(value: true)
def falsePred = new Predicate(value: false)
assert truePred && !falsePred
33jeudi 21 octobre 2010
SQL support refinements
// batch statementssql.withBatch { stmt ‐>
["Paul", "Jochen", "Guillaume"].each { name ‐>
stmt.addBatch "insert into PERSON (name) values ($name)"
}}
// transaction supportdef persons = sql.dataSet("person")
sql.withTransaction { persons.add name: "Paul" persons.add name: "Jochen"
persons.add name: "Guillaume"
persons.add name: "Roshan"
}
34jeudi 21 octobre 2010
Groovy 1.7.x changes
• Since Groovy 1.7.0, Groovy 1.7.1, 1.7.2, 1.7.3, 1.7.4 and 1.7.5 have been released already!
• Here’s what’s new!
35jeudi 21 octobre 2010
Map improvements
// map auto‐vificationdef m = [:].withDefault { key ‐> "Default" }
assert m['z'] == "Default"
assert m['a'] == "Default"
// default sortm.sort()
// sort with a comparatorm.sort({ a, b ‐> a <=> b } as Comparator)
36jeudi 21 octobre 2010
XML back to String
• Ability to retrieve the XML string from a node from an XmlSlurper GPathResult
def xml = """<books> <book isbn="12345">Groovy in Action</book>
</books>"""def root = new XmlSlurper().parseText(xml)
def someNode = root.bookdef builder = new StreamingMarkupBuilder()
assert builder.bindNode(someNode).toString() ==
"<book isbn='12345'>Groovy in Action</book>"
37jeudi 21 octobre 2010
Currying improvements
// right curryingdef divide = { a, b ‐> a / b }
def halver = divide.rcurry(2)
assert halver(8) == 4 // currying n‐th parameterdef joinWithSeparator = { one, sep, two ‐>
one + sep + two}def joinWithComma = joinWithSeparator.ncurry(1, ', ')
assert joinWithComma('a', 'b') == 'a, b'
38jeudi 21 octobre 2010
New String methods
println """ def method() { return 'bar' }""".stripIndent()
println """ |def method() { | return 'bar' |}""".stripMargin('|')
// string "translation" (UNIX tr)
assert 'hello'.tr('z‐a', 'Z‐A') == 'HELLO'
assert 'Hello World!'.tr('a‐z', 'A') == 'HAAAA WAAAA!'
assert 'Hello World!'.tr('lloo', '1234') == 'He224 W4r2d!'
// capitalize the first letter
assert 'h'.capitalize() == 'H'
assert 'hello'.capitalize() == 'Hello'
assert 'hello world'.capitalize() == 'Hello world'
// tab/space (un)expansion (UNIX expand command)
assert '1234567\t8\t '.expand() == '1234567 8 '
assert ' x '.unexpand() == ' x\t '
39jeudi 21 octobre 2010
...and beyond!jeudi 21 octobre 2010
Groovy 1.8 & beyond
• Still subject to discussion• Always evolving roadmap• Things may change!
41jeudi 21 octobre 2010
What’s cooking?jeudi 21 octobre 2010
What we’re working on
• More runtime performance improvements• Closures
– closure annotation parameters– closure composition– closure memoization
• New AST transformations• Gradle build• Modularizing Groovy• Align with JDK 7 / Java 7 / Project Coin• Enhanced DSL support• AST Templates
43jeudi 21 octobre 2010
Closure annotation parameters
• Groovy 1.5 brought Java 5 annotations• What if... we could go beyond what Java offered?
– In 1.7, we can put annotations on packages, imports and variable declarations
– But annotations are still limited in terms of parameters they allow
• Here comes closure annotation parameters!– Groovy 1.8 will give us the ability to access annotation with
closure parameters at runtime
44jeudi 21 octobre 2010
GContracts
• Closures are already allowed in the Groovy 1.7 Antlr grammar– André Steingreß created GContracts,
a «design by contract» module
// a class invariant@Invariant({ name.size() > 0 && age > ageLimit() })
// a method pre‐condition@Requires({ message != null }) // a method post‐condition@Ensures({ returnResult % 2 == 0 })
45jeudi 21 octobre 2010
Closure composition
• Functional flavor!
46
def plus2 = { it + 2 }def times3 = { it * 3 } def composed1 = plus2 << times3assert composed1(3) == 11assert composed1(4) == plus2(times3(4))
def composed2 = times3 << plus2assert composed2(3) == 15assert composed2(5) == times3(plus2(5))
// reverse compositionassert composed1(3) == (times3 >> plus2)(3)
jeudi 21 octobre 2010
Closure memoization
• Memoization: remember the outcome of previous (ideally side-effect free) invocations
47
def c = { a, b ‐> sleep 1000; a + b }.memoize()
assert c(1, 2) == 3 // after 1000ms
assert c(1, 2) == 3 // return immediately
// other forms:// at least 10 invocations cached
def cAtLeast = { ... }.memoizeAtLeast(10)
// at most 10 invocations cacheddef cAtMost = { ... }.memoizeAtMost(10)
// between 10 and 20 invocations cached
def cAtLeast = { ... }.memoizeBetween(10, 20)
jeudi 21 octobre 2010
New AST Transformations
• Many new transformations coming up for removing even more boiler plate code– @Log, inject a logger in your classes– @Field, creates a field in your scripts– @PackageScope improvements (methods & fields)– @Synchronized, providing safer synchronization semantics– @InheritConstructor, ex. when extending Exception– @IndexedProperties, JavaBeans indexed property support– @AutoClone, automatic cloning of your beans– @AutoExternalizable, automatic externalization of your beans– @Canonical, adding equals, hashCode, toString– @EqualsAndHashCode, only adding equals and hashCode– @ToString, only adding toString– @TupleConstructor, for adding a tuple constructor
48jeudi 21 octobre 2010
jeudi 21 octobre 2010
jeudi 21 octobre 2010
More adhoc build
More modular Groovy
More from Hans!
jeudi 21 octobre 2010
More modular build
• «Not everybody needs everything!» ™
• A lighter Groovy-core– what’s in groovy-all?
• Modules– test, jmx, swing, xml, sql, web, template– integration (bsf, jsr-223)– tools (groovydoc, groovyc, shell, console, java2groovy)
50jeudi 21 octobre 2010
Java 7 / 8 / Project Coin
• JSR-292 InvokeDynamic
• Simple Closures (8)
• Proposals from Project Coin– Strings in switch (7)– Automatic Resource Management (7)– Improved generics type inference (diamond <>) (7)– Simplified varargs method invocation (7)– Better integral literals (7)– Language support for collections (8?)
51jeudi 21 octobre 2010
Java 7 / 8 / Project Coin
• JSR-292 InvokeDynamic
• Simple Closures (8)
• Proposals from Project Coin– Strings in switch (7)– Automatic Resource Management (7)– Improved generics type inference (diamond <>) (7)– Simplified varargs method invocation (7)– Better integral literals (7)– Language support for collections (8?)
51jeudi 21 octobre 2010
Java 7 / 8 / Project Coin
• JSR-292 InvokeDynamic
• Simple Closures (8)
• Proposals from Project Coin– Strings in switch (7)– Automatic Resource Management (7)– Improved generics type inference (diamond <>) (7)– Simplified varargs method invocation (7)– Better integral literals (7)– Language support for collections (8?)
51jeudi 21 octobre 2010
Java 7 / 8 / Project Coin
• JSR-292 InvokeDynamic
• Simple Closures (8)
• Proposals from Project Coin– Strings in switch (7)– Automatic Resource Management (7)– Improved generics type inference (diamond <>) (7)– Simplified varargs method invocation (7)– Better integral literals (7)– Language support for collections (8?)
51jeudi 21 octobre 2010
Java 7 / 8 / Project Coin
• JSR-292 InvokeDynamic
• Simple Closures (8)
• Proposals from Project Coin– Strings in switch (7)– Automatic Resource Management (7)– Improved generics type inference (diamond <>) (7)– Simplified varargs method invocation (7)– Better integral literals (7)– Language support for collections (8?)
51jeudi 21 octobre 2010
Improved DSL support
• GEP-3: an extended command expression DSL– Groovy Extension Proposal #3
• Command expressions– basically top-level statements without parens– combine named and non-named arguments in the mix
• for nicer Domain-Specific Languages–(methodName arguments )*
52jeudi 21 octobre 2010
Before GEP-3
• The idea: extend command-expressions, beyond top-level statements, for chained method calls
• Before
send("Hello").to("Graeme")
check(that: margherita).tastes(good)
sell(100.shares).of(MSFT)
take(2.pills).of(chloroquinine).after(6.hours)
wait(10.minutes).and(execute { })
blend(red, green).of(acrylic)
53jeudi 21 octobre 2010
With GEP-3
• The idea: extend command-expressions, beyond top-level statements, for chained method calls
• After
send "Hello" to "Graeme"
check that: margherita tastes good
sell 100.shares of MSFT
take 2.pills of chloroquinine after 6.hours
wait 10.minutes and execute { }
blend red, green of acrylic
54jeudi 21 octobre 2010
With GEP-3
• The idea: extend command-expressions, beyond top-level statements, for chained method calls
• After
send "Hello" to "Graeme"
check that: margherita tastes good
sell 100.shares of MSFT
take 2.pills of chloroquinine after 6.hours
wait 10.minutes and execute { }
blend red, green of acrylic
Less parens& commas
54jeudi 21 octobre 2010
SpringOne 2GX 2010. All rights reserved. Do not distribute without permission.
Summary
jeudi 21 octobre 2010
Summary (1/2)
• No need to wait for Java 7, 8, 9...– closures, properties, interpolated strings, extended annotations,
metaprogramming, [YOU NAME IT]...
56jeudi 21 octobre 2010
Summary (1/2)
• No need to wait for Java 7, 8, 9...– closures, properties, interpolated strings, extended annotations,
metaprogramming, [YOU NAME IT]...
Groovy’s still
innovative
since 2003!
56jeudi 21 octobre 2010
Summary (2/2)
• But it’s more than just a language, it’s a very rich and active ecosystem!– Grails, Griffon, Gradle, GPars, Spock, Gaelyk...
57jeudi 21 octobre 2010
SpringOne 2GX 2010. All rights reserved. Do not distribute without permission.
Q&A
jeudi 21 octobre 2010
Thanks for your attention!
Guillaume Laforge
Head of Groovy Development
Email: [email protected]
Twitter: @glaforge
• References:• http://gaelyk.appspot.com/• http://groovy.codehaus.org/• http://code.google.com/appengine/
59jeudi 21 octobre 2010
Images used in this presentation
House / past: http://www.flickr.com/photos/jasonepowell/3680030831/sizes/o/Present clock: http://www.flickr.com/photos/38629278@N04/3784344944/sizes/o/Future: http://www.flickr.com/photos/befuddledsenses/2904000882/sizes/l/Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/Puzzle: http://www.everystockphoto.com/photo.php?imageId=263521Light bulb: https://newsline.llnl.gov/retooling/mar/03.28.08_images/lightBulb.pngSpeed limit : http://www.morguefile.com/archive/display/18492Warehouse : http://www.morguefile.com/archive/display/85628Check mark: http://www.lnl.infn.it/~epics/WikiDumps/localhost/600px-symbol_ok.svg.png
60jeudi 21 octobre 2010