GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
1.
2. What’s new in Groovy 1.6?
Get started with Groovy and learn about
all the novelties in the latest release
Guillaume Laforge
Head of Groovy Development
3. Guillaume Laforge
Groovy Project Manager — SpringSource
> Working on Groovy since 2003
> JSR-241 Spec Lead
> Initiator of the Grails web framework
> Co-author of Groovy in Action
> Speaker: JavaOne, QCon, JavaPolis/Devoxx,
JavaZone, Sun Tech Days, SpringOne/The Spring
Experience, JAX, DSL DevCon, and more…
3
4. What’s new in Groovy 1.6?
Article Published by InfoQ
> This presentation was prepared with the examples
I’ve used in my article written for InfoQ
> http://www.infoq.com/articles/groovy-1-6
> Read this article for more detailed explanations of
all the new features in Groovy 1.6
4
5. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
5
6. Groovy in a Nutshell
Simplify the Life of Java Developers
> Groovy is a dynamic language for the JVM
With a Meta-Object Protocol
Compiles down to bytecode
> Open Source Apache licensed project
> Relaxed grammar derived from the Java 5 grammar
Borrowed some good ideas from Smalltalk/Python/Ruby
Java 5 features out of the box:
annotations, generics, static imports, enums…
Flat learning curve
6
7. A Taste of Groovy — Take 1
A Normal Java Program
> public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String greet() {
return "Hello " + name;
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Groovy");
System.out.println( helloWorld.greet() );
}
}
7
8. A Taste of Groovy — Take 2
A Normal Groovy Program
> public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String greet() {
return "Hello " + name;
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Groovy");
System.out.println( helloWorld.greet() );
}
}
8
9. A Taste of Groovy — Take 3
A Groovier Program
> class HelloWorld {
String name
String greet() { "Hello $name" }
}
def helloWorld = new HelloWorld(name: "Groovy")
println helloWorld.greet()
9
10. The Groovy Web Console
A Groovy Playground
> Groovy works nicely on Google App Engine
You can also deploy Grails applications
> You can play with Groovy in the web console
http://groovyconsole.appspot.com/
10
15. GStrings!
• GStrings are... interpolated strings
– Sorry, not really what you expected!
– Placeholder variables are replaced
– You can have multiline strings
• def person = ‘John’
def letter = “““${new Date()}
Dear ${person},
I hope you’re fine!
”””
15
16. Closures
• Closures are reusable and assignable code blocks or
anonymous functions
– No need to wait for Java 7/8/9 to get them!
– def greet = { println “Hello ${it}” }
greet(“Guillaume”)
• You can pass parameters
– def greet = { String name ->
println “Hello ${name}”
}
• You can passe closures around
– def method(Closure c) { c(“Hello”) }
method(greet)
16
17. BigDecimal Arithmetic
• 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)
17
18. Groovy Builders
• The Markup builder
– Easy way for creating XML or HTML content
– def mkp = new MarkupBuilder()
mkp.html {
head {
title “Groovy in Action”
}
body {
div(width: ‘100’) {
p(class: ‘para’) {
span “Best book ever!”
}
}
}
}
18
19. Parsing XML
• And it’s so easy to parser XML and navigate
through the node graph!
• def geocodingUrl = "http://...".toURL()
geocodingUrl.withInputStream { stream ->
def node = new XmlSlurper().parse(stream)
if (node.Response.Status.code == "200") {
def text = node.Response.Placemark.
Point.coordinates.text()
def coord = text.tokenize(',').
collect{ Float.parseFloat(it) }
(latitude, longitude) = coord[1..0]
}
}
19
20. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
20
21. Performance Improvements
Both Runtime & Compile-Time
> The Groovyc compiler is 3x to 5x faster
With a clever class lookup cache
> Certain online micro-benchmarks show
150% to 460% increase in performance
compared to Groovy 1.5
Thanks to advanced call-site caching techniques
Beware of micro-benchmarks!
> Makes Groovy one of the fastest dynamic languages
available
21
22. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
22
23. Multiple Assignment
Assign Multiple Variables at Once
> Newly defined variables
def (a, b) = [1, 2]
assert a == 1
assert b == 2
> Assign to existing variables
def lat, lng
(lat, lng) = geocode(‘Paris’)
> The classical swap case
(a, b) = [b, a]
> Extra elements ⇒ not assigned to any variable
> Less elements ⇒ null into extra variables
23
24. More Optional Return
In if/else and try/catch Blocks
> The return keyword is optional for the last
expression of a method body
But if/else & try/catch didn’t return any value
> def method() { if (true) 1 else 0 }
assert method() == 1
> def method(bool) {
try {
if (bool) throw new Exception("foo")
1
} catch(e) { 2 }
finally { 3 }
}
assert method(false) == 1
assert method(true) == 2
24
25. Annotation Definition
The Missing Bit of Java 5 Support
> Groovy support for Java 5 features is now complete
with the missing annotation definition
> Nothing to show here, it’s just normal Java :-)
> Note that the sole dynamic language supporting
annotation is… Groovy
Opens the door to EJB3 / JPA / Spring annotations /
Guice / TestNG…
25
26. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
26
27. Meta-What?
Meta-Programming
> The ability of a language to modify itself
> Groovy 1.6 introduces AST Transformations
Abstract Syntax Tree
> Goodbye to a lot of boiler-plate technical code!
> Two kinds of transformations
Global transformations
Local transformations: triggered by annotations
27
28. AST Transformations in 1.6
Implement Patterns through Transformations
> Several transformations find their way in Groovy 1.6
@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!
28
29. @Singleton
(Anti-)Pattern Revisited
> The evil Java singleton
public class Evil {
public static final Evil instance = new Evil ();
private Evil () {}
Evil getInstance() { return instance; }
}
> In Groovy:
@Singleton class Evil {}
> There’s also a « lazy » version
@Singleton(lazy = true) class Evil {}
29
30. @Immutable
The Immutable… Boiler-Plate Code
> 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.
> In Groovy
@Immutable final 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
30
31. @Lazy
Not Just for Lazy Dudes!
> When you need to lazy evaluate / instantiate
complex data structures for class fields, mark them
as @Lazy
class Dude {
@Lazy pets = retriveFromSlowDB()
}
> Groovy will handle the boiler-plate code for you
31
32. @Delegate
Not Just for Managers!
> You can delegate to fields of your class
Think multiple inheritance
class Employee {
def doTheWork() { "done" }
}
class Manager {
@Delegate
Employee slave = new Employee()
}
def god = new Manager()
assert god.doTheWork() == "done"
> Damn manager who will get all the praise…
32
33. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
33
34. Grab a Grape
Groovy Advanced Packaging Engine
> Helps you distribute scripts without dependencies
> Just declare your dependencies with @Grab
Will look for dependencies in Maven or Ivy 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()
}
34
35. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
35
36. @Bindable (1/2)
Event-Driven Made Easy
> Speaking of boiler-plate code…
property change listeners
> import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
public class MyBean {
private String prop;
PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.add(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.remove(l);
}
public String getProp() {
return prop;
}
public void setProp(String prop) {
pcs.firePropertyChanged("prop", this.prop, this.prop = prop);
}
}
36
37. @Bindable (2/2)
Event-Driven Made Easy
> Groovy’s solution
class MyBean {
@Bindable String prop
}
> Interesting in Griffon and Swing builder
textField text: bind { myBean.prop }
> Also of interest: @Vetoable
37
38. Griffon
The Swing MVC Framework
> Leverages Groovy’s SwingBuilder
and Grails’ infrastructure
http://griffon.codehaus.org
38
39. Swing Console Improvements
> The console can be run as an applet
> Code indentation support
> Script drag’n drop
> Add JARs in the classpath from the GUI
> Execution results visualization plugin
> Clickable stacktraces and error messages
> Not intended to be a full-blown IDE, but handy
39
41. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
41
42. ExpandoMetaClass DSL
Less Repetition
> EMC is a way to change the behavior of types at
runtime
> Before
Number.metaClass.multiply = { Amount amount ->
amount.times(delegate) }
Number.metaClass.div = { Amount amount ->
amount.inverse().times(delegate) }
> Now in Groovy 1.6
Number.metaClass {
multiply { Amount amount -> amount.times(delegate) }
div { Amount amount ->
amount.inverse().times(delegate) }
}
42
43. Runtime Mixins
Inject New Behavior to Types at Runtime
> 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!"
43
44. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
44
45. javax.script.* Scripting APIs
Groovy Scripting Engine Built-In
> The JSR-223 / javax.script.* scripting engine for
Groovy is bundled in Groovy 1.6
import javax.script.*
def manager = new ScriptEngineManager()
def engine =
manager.getEngineByName("groovy")
assert engine.evaluate("2 + 3") == 5
> To evaluate Groovy scripts at runtime in your
application, just drop the Groovy JAR in your
classpath!
45
46. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
46
47. JMX Builder (1/2)
Domain-Specific Language for JMX
• Simplify JMX handling with a Builder pattern approach
• Declaratively expose Java/Groovy objects as MBeans
• JMX's event model support
–Inline closures to create event handler & broadcaster
–Closures for receiving event notifications
• Provides a flexible registration policy for MBean
• Exposes attribute, constructors, operations,
parameters, and notifications
• Simplified creation of connector servers & clients
• Support for exporting JMX timers
• http://groovy.codehaus.org/Groovy+JmxBuilder
47
48. JMX Builder (2/2)
Domain-Specific Language for JMX
> Create a connector server
def jmx = new JmxBuilder()
jmx.connectorServer(port:9000).start()
> Create a connector client
jmx.connectorClient(port:9000).connect()
> Export a bean
jmx.export { bean new MyService() }
> Defining a timer
jmx.timer(name: "jmx.builder:type=Timer",
event: "heartbeat", period: "1s").start()
> JMX listener
jmx.listener(event: "…", from: "foo",
call: { event -> …})
48
49. nda
Ag e
> Groovy Overview
> Performance Improvements
> Syntax Enhancements
> Compile-Time Metaprogramming
> The Grape Module System
> Swing-Related Improvements
> Runtime Metaprogramming
Additions
> JSR-223 Scripting Engine Built-In
> JMX Builder
> OSGi Readiness
49
50. OSGi Readiness
> The Groovy JAR contains OSGi metadata
Can be reused in OSGi containers out-of-the-box
> Tutorials on Groovy and OSGi
http://groovy.codehaus.org/OSGi+and+Groovy
Will show you how to load Groovy as a service, write,
publish and consume Groovy services, and more
50
52. Summary
Just Remember that Groovy Rocks! :-)
> Any Java developer is a Groovy developer!
> Great for your next-generation general purpose
programming language, as well as for admin tasks,
extending apps, writing DSLs...
> Groovy 1.6 provides
Important performance gains
Efficient compile-time metaprogramming hooks
New useful features (JMX, javax.script.*, etc.)
A script dependencies system
Various Swing-related improvements
Several runtime metaprogramming additions
> Get it now!
http://groovy.codehaus.org/Download
52