Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge

Preview:

Citation preview

to Infinity and Beyond

mercredi 19 mai 2010

Guillaume LaforgeSpringSource, a division of VMWare

to infinity and beyond!

mercredi 19 mai 2010

Guillaume LaforgeGroovy Project Manager

on Groovy since 2003!

JSR-241 Spec Lead

Head of Groovy Developmentat SpringSource (division of VMWare)

Initiator of the Grails framework

Creator of the Gaelyk toolkit

Co-author of Groovy in Action

International speaker

mercredi 19 mai 2010

AgendaPast

Groovy 1.6 flashback

PresentGroovy 1.7 novelties

A few Groovy 1.7.x refinements

FutureWhat’s cooking for 1.8 and beyond

mercredi 19 mai 2010

looking into the Pastmercredi 19 mai 2010

Big highlights of Groovy 1.6Greater compile-time and runtime performanceMultiple assignmentsOptional return for if/else and try/catch/finallyJava 5 annotation definitionAST TransformationsThe Grape module and dependency systemVarious Swing related improvementsJMX BuilderMetaprogramming additionsJSR-223 scripting engine built-inOut-of-the-box OSGi support

mercredi 19 mai 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]

mercredi 19 mai 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 (b) throw new Exception()

        1    } catch (any) { 2 }    finally { 3 }}assert m2(true) == 2 && m2(false) == 1

mercredi 19 mai 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)

mercredi 19 mai 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

mercredi 19 mai 2010

@ImmutableTo 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

mercredi 19 mai 2010

Grab a grape!Simple distribution and sharing of Groovy scripts

Dependencies stored locallyCan 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()}

mercredi 19 mai 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) 

    }}

mercredi 19 mai 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!"

mercredi 19 mai 2010

JMX BuilderA 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 */ })

mercredi 19 mai 2010

into the Present...mercredi 19 mai 2010

Big highlights of Groovy 1.7Anonymous Inner Classes and Nested ClassesAnnotations anywhereGrape improvementsPower AssertsAST ViewerAST BuilderCustomize the Groovy Truth!Rewrite of the GroovyScriptEngineGroovy Console improvementsSQL support refinements

mercredi 19 mai 2010

AIC and NCAnonymous Inner Classe and Nested Classes

mercredi 19 mai 2010

AIC and NCAnonymous Inner Classe and Nested Classes

For Java

copy’n paste

compatibility

sake :-)

mercredi 19 mai 2010

Annonymous Inner Classes

boolean called = false

Timer timer = new Timer()

timer.schedule(new TimerTask() {

    void run() {

        called = true

    }}, 0)

sleep 100assert called

mercredi 19 mai 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

mercredi 19 mai 2010

Nested Classes

class Environment {    static class Production         extends Environment {}

    static class Development         extends Environment {}

} new Environment.Production()

mercredi 19 mai 2010

Anotations anywhere

You can now put annotationson imports

on packages

on variable declarations

Examples with @Grab following...

mercredi 19 mai 2010

Grape improvements (1/3)@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"

mercredi 19 mai 2010

Grape improvements (2/3)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"}}}'''

mercredi 19 mai 2010

Grape improvements (3/3)Groovy 1.7 introduced Grab resolver

For when you need to specify a specific repositoryfor a given dependency

@GrabResolver(    name = 'restlet.org',    root = 'http://maven.restlet.org')

@Grab('org.restlet:org.restlet:1.1.6')

import org.restlet.Restlet

mercredi 19 mai 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

mercredi 19 mai 2010

Power Asserts (2/2)You’ll get a more comprehensible output

mercredi 19 mai 2010

Spock testing framework

mercredi 19 mai 2010

Easier AST TransformationsAST Transformations are a very powerful feature

But are still rather hard to developNeed 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

mercredi 19 mai 2010

AST Viewer

mercredi 19 mai 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"

        }    }}

mercredi 19 mai 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

mercredi 19 mai 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"

}

mercredi 19 mai 2010

Groovy 1.7.x changes

Groovy 1.7.1 and 1.7.2 have been released

Groovy 1.7.3 is coming soon

Here’s what’s new!

mercredi 19 mai 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)

mercredi 19 mai 2010

XML back to StringAbility 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>"

mercredi 19 mai 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'

mercredi 19 mai 2010

New icon for the Swing console

mercredi 19 mai 2010

New icon for the Swing console

mercredi 19 mai 2010

New String methodsprintln """    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 '

mercredi 19 mai 2010

...and beyond!mercredi 19 mai 2010

Groovy 1.8 & beyondStill subject to discussion

Always evolving roadmap

Things may change!

mercredi 19 mai 2010

What’s cooking?mercredi 19 mai 2010

What we’re working onMore runtime performance improvements

Closure annotations

Gradle build

Modularizing Groovy

Align with JDK 7 / Java 7 / Project Coin

Enhanced DSL support

AST Templates

Towards MOP 2

mercredi 19 mai 2010

«Blackdrag» revealedthe black magic!

mercredi 19 mai 2010

Closure annotationsGroovy 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 annotations!Groovy 1.8 will give us the ability to access annotation with closure parameters at runtime

mercredi 19 mai 2010

GContractsClosures are already allowed in the Groovy 1.7 Antlr grammar

Andre 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 })

mercredi 19 mai 2010

mercredi 19 mai 2010

mercredi 19 mai 2010

More adhoc build

More modular Groovy

More from Hans!

mercredi 19 mai 2010

More modular build«Not everybody needs everything!» ™

A lighter Groovy-corewhat’s in groovy-all?

Modulestest, jmx, swing, xml, sql, web, template

integration (bsf, jsr-223)

tools (groovydoc, groovyc, shell, console, java2groovy)

mercredi 19 mai 2010

Java 7 / JDK 7 / Project CoinJSR-292 InvokeDynamic

Simple Closures?

Proposals from Project CoinStrings in switch

Automatic Resource Management

Improved generics type inference (diamond <>)

Simplified varargs method invocation

Better integral literals

Language support for collections

mercredi 19 mai 2010

Improved DSL support

GEP-3: an extended command expression DSLGroovy Extension Proposal #3

A Google Summer of Code student will work on that

Command expressionsbasically top-level statements without parens

combine named and non-named arguments in the mixfor nicer Domain-Specific Languages

mercredi 19 mai 2010

Before GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls

Before

send("Hello").to("Jochen")send("Hello", from: "Guillaume").to("Jochen")

sell(100.shares).of(MSFT)

take(2.pills).of(chloroquinine).in(6.hours)

every(10.minutes).execute {  }

given { }.when { }.then { }

blend(red, green).of(acrylic)

mercredi 19 mai 2010

With GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls

After

send "Hello"  to "Jochen"send "Hello", from: "Guillaume"  to "Jochen"

sell 100.shares  of MSFT

take 2.pills  of chloroquinine  in 6.hours

every 10.minutes  execute {  }

given { } when { } then { }

blend red, green  of acrylic

mercredi 19 mai 2010

With GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls

After

send "Hello"  to "Jochen"send "Hello", from: "Guillaume"  to "Jochen"

sell 100.shares  of MSFT

take 2.pills  of chloroquinine  in 6.hours

every 10.minutes  execute {  }

given { } when { } then { }

blend red, green  of acrylic

Less parens& commas

mercredi 19 mai 2010

AST TemplatesSince AST, it’s easier to write AST Transformations

But we can even do better!

Hamlet D’Arcy is working on a new proposalGEP-4 — AST Templates

mercredi 19 mai 2010

a new

MOP

mercredi 19 mai 2010

Towards a new MOP?The Meta-Object Protocol show its age

different stratification layersDGM, categories, custom MetaClasses, ExpandoMetaClass...

different characteristicsscope: global, local, thread-bound

works across the hierarchy or not

A better MOP could...help for performance

offer more granularity

let the developer choose the characteristics he needs

provide a layered approach of changes

mercredi 19 mai 2010

Some potential modulesGPars was considered a potential module for addition into core

but got a life of its own!

Parser combinatorsfor when you hit the walls of the Groovy syntax

and AST transformations won’t cut it

Pattern matching

mercredi 19 mai 2010

Summary (1/2)No need to wait for Java 7, 8, 9...

closures, properties, interpolated strings, extended annotations, metaprogramming, [YOU NAME IT]...

mercredi 19 mai 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!

mercredi 19 mai 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...

mercredi 19 mai 2010

Questions & Answers

mercredi 19 mai 2010

Images used in this presentationHouse / 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/

Black dragon: http://www.free-computer-wallpapers.com/pictures/Fantasy-wallpaper/Black_Dragon

Puzzle: http://www.everystockphoto.com/photo.php?imageId=263521

Light bulb: https://newsline.llnl.gov/retooling/mar/03.28.08_images/lightBulb.png

Spock: http://altoladeira.files.wordpress.com/2009/07/spock2.jpg

mercredi 19 mai 2010