groovy 2 and beyond

127
Groovy 2.0 and beyond Guillaume Laforge Groovy Project Manager SpringSource / VMware @glaforge

Upload: guillaume-laforge

Post on 17-May-2015

2.616 views

Category:

Technology


2 download

DESCRIPTION

"Groovy 2.0 and beyond" presentation given at the Groovy/Grails eXchange conference. Video can be seen here: http://skillsmatter.com/podcast/groovy-grails/keynote-speech

TRANSCRIPT

Page 1: Groovy 2 and beyond

Groovy 2.0and beyondGuillaume LaforgeGroovy Project ManagerSpringSource / VMware@glaforge

Page 2: Groovy 2 and beyond

Guillaume Laforge

• Groovy Project Manager at VMware

• Initiator of the Grails framework

• Creator of the Gaelyk

• Co-author of Groovy in Action

• Follow me on...

• My blog: http://glaforge.appspot.com

• Twitter: @glaforge

• Google+: http://gplus.to/glaforge

Page 3: Groovy 2 and beyond

A blossomingECOSYSTEM

Page 4: Groovy 2 and beyond
Page 5: Groovy 2 and beyond
Page 6: Groovy 2 and beyond
Page 7: Groovy 2 and beyond
Page 8: Groovy 2 and beyond

GV

M

Page 9: Groovy 2 and beyond
Page 10: Groovy 2 and beyond

GVM

Page 11: Groovy 2 and beyond

GVMGROOVYENVIRONMENTMANAGER

Page 12: Groovy 2 and beyond

GVM: Groovy enVironment Manager

• New kid in town!

• http://gvmtool.net/ — @gvmtool

• Manage parallel versions of various SDKs

• Currently supports

• Groovy, Grails, Griffon, Gradle, Vert.x

• On Linux, MacOS, Cygwin, Solaris, FreeBSD

Page 13: Groovy 2 and beyond

GROOVY

Page 14: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

Page 15: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

A more modular Groovy

Page 16: Groovy 2 and beyond

Groovy Modularity

• Groovy’s « all » JAR weighs in at 6 MB

•Nobody needs everything

• Template engine, Ant scripting, Swing UI building...

• Provide a smaller core

• and several smaller JARs per feature

• Provide hooks for setting up DGM methods,

Page 17: Groovy 2 and beyond

The new JARs

• A smaller JAR: 3MB

• Modules

– console– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

Page 18: Groovy 2 and beyond

The new JARs

• A smaller JAR: 3MB

• Modules

– console– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

Page 19: Groovy 2 and beyond

Extension modules

• Create your own module

• contribute instance extension methods

package  foo

class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        }}

//  usage:  "Guillaume".introduces("Cédric")

Page 20: Groovy 2 and beyond

Extension modules

• Create your own module

• contribute instance extension methods

package  foo

class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        }}

//  usage:  "Guillaume".introduces("Cédric")

Same structureas Categories

Page 21: Groovy 2 and beyond

Extension modules

• Create your own module

• contribute class extension methods

package  foo

class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        }}

//  usage:  String.hi()

Page 22: Groovy 2 and beyond

Extension module descriptor

• Descriptor in: META-INF/services/org.codehaus.groovy.runtime.ExtensionModule

moduleName  =  stringExtensionsmoduleVersion  =  1.0//  comma-­‐separated  list  of  classesextensionClasses  =  foo.StringExtension//  comma-­‐separated  list  of  classesstaticExtensionClasses  =  foo.StaticStringExtension

Page 23: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

Page 24: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

Page 25: Groovy 2 and beyond

Binary literals

• We had decimal, octal and hexadecimal notations for number literals

• We can now use binary representations too

int  x  =  0b10101111assert  x  ==  175  byte  aByte  =  0b00100001assert  aByte  ==  33  int  anInt  =  0b1010000101000101assert  anInt  ==  41285

Page 26: Groovy 2 and beyond

Underscore in literals

• Now we can also add underscores in number literals for more readability

long  creditCardNumber  =  1234_5678_9012_3456Llong  socialSecurityNumbers  =  999_99_9999Lfloat  monetaryAmount  =  12_345_132.12long  hexBytes  =  0xFF_EC_DE_5Elong  hexWords  =  0xFFEC_DE5Elong  maxLong  =  0x7fff_ffff_ffff_ffffLlong  alsoMaxLong  =  9_223_372_036_854_775_807Llong  bytes  =  0b11010010_01101001_10010100_10010010

Page 27: Groovy 2 and beyond

Multicatch

• One block for multiple exception caught

• rather than duplicating the block

try  {        /*  ...  */}  catch(IOException  |  NullPointerException  e)  {        /*  one  block  to  treat  2  exceptions  */}

Page 28: Groovy 2 and beyond

InvokeDynamic

•Groovy 2.0 supports JDK 7’s invokeDynamic

• compiler has a flag for compiling against JDK 7

• might use the invokeDynamic backport for < JDK 7

• Benefits

• more runtime performance!

• at least as fast as current « dynamic » Groovy

• in the long run, will allow us to get rid of code!

• call site caching, thanks to MethodHandles

• metaclass registry, thanks to ClassValues

• will let the JIT inline calls more easily

Page 29: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

Page 30: Groovy 2 and beyond

Groovy 2.0 bird’s eye view

Static Type Checking

Static Compilation

Page 31: Groovy 2 and beyond

Static Type Checking

• Goal: make the Groovy compiler « grumpy »!

• and throw compilation errors (not at runtime)

•Not everybody needs dynamic features all the time

• think Java libraries scripting

• Grumpy should...

• tell you about your method or variable typos

• complain if you call methods that don’t exist

• shout on assignments of wrong types

• infer the types of your variables

• figure out GDK methods

Page 32: Groovy 2 and beyond

Typos in a variable or method

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Page 33: Groovy 2 and beyond

Typos in a variable or method

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilationerrors!

Page 34: Groovy 2 and beyond

Typos in a variable or method

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilationerrors!

Annotation can be atclass or method level

Page 35: Groovy 2 and beyond

Wrong assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  def  o  =  new  Object()int  x  =  o  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Page 36: Groovy 2 and beyond

Wrong assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  def  o  =  new  Object()int  x  =  o  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Compilationerrors!

Page 37: Groovy 2 and beyond

Wrong return types

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Page 38: Groovy 2 and beyond

Wrong return types

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Compilationerror!

Page 39: Groovy 2 and beyond

Type inference

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Page 40: Groovy 2 and beyond

Statically checked & dynamic methods

@TypeCheckedString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Page 41: Groovy 2 and beyond

Instanceof checks

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

Page 42: Groovy 2 and beyond

Instanceof checks

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

No needfor casts

Page 43: Groovy 2 and beyond

Instanceof checks

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

No needfor casts

Can call String#multiply(int)from the Groovy Development Kit

Page 44: Groovy 2 and beyond

Lowest Upper Bound

• Represents the lowest « super » type classes have in common

• may be virtual (aka « non-denotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Page 45: Groovy 2 and beyond

Lowest Upper Bound

• Represents the lowest « super » type classes have in common

• may be virtual (aka « non-denotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Inferred return type:List<Number & Comparable>

Page 46: Groovy 2 and beyond

Lowest Upper Bound

• Represents the lowest « super » type classes have in common

• may be virtual (aka « non-denotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Inferred return type:List<Number & Comparable>

Page 47: Groovy 2 and beyond

Flow typing

• Static type checking shouldn’t complain even for bad coding practicies which work without type checks

@TypeChecked  test()  {        def  var  =  123                  //  inferred  type  is  int        int  x  =  var                      //  var  is  an  int        var  =  "123"                      //  assign  var  with  a  String

       x  =  var.toInteger()      //  no  problem,  no  need  to  cast

       var  =  123        x  =  var.toUpperCase()  //  error,  var  is  int!}

Page 48: Groovy 2 and beyond

Gotcha: static checking vs dynamic

•Type checking works at compile-time

• adding @TypeChecked doesn’t change behavior

• do not confuse with static compilation

• Most dynamic features cannot be type checked

• metaclass changes, categories

• dynamically bound variables (ex: script’s binding)

• But compile-time metaprogramming works

• as long as proper type information is defined

Page 49: Groovy 2 and beyond

Gotcha: runtime metaprogramming

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Page 50: Groovy 2 and beyond

Gotcha: runtime metaprogramming

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Not allowed:metaClass property

is dynamic

Page 51: Groovy 2 and beyond

Gotcha: runtime metaprogramming

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Not allowed:metaClass property

is dynamic

Method notrecognized

Page 52: Groovy 2 and beyond

Gotcha: explicit type for closures

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Not  OK        }}

Page 53: Groovy 2 and beyond

Gotcha: explicit type for closures

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  it’s  a  String        }}

Page 54: Groovy 2 and beyond

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

Page 55: Groovy 2 and beyond

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Page 56: Groovy 2 and beyond

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Impossible to ensure the

assignment really happens

Page 57: Groovy 2 and beyond

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Impossible to ensure the

assignment really happens

Only methods of the most specific compatible type (LUB) are allowed by the type checker

Page 58: Groovy 2 and beyond

Closure shared variables

class  A                      {  void  foo()  {}  }class  B  extends  A  {  void  bar()  {}  }

@TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK!}

Page 59: Groovy 2 and beyond

Closure shared variables

class  A                      {  void  foo()  {}  }class  B  extends  A  {  void  bar()  {}  }

@TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK!}

var is at least an instance of A

Page 60: Groovy 2 and beyond

Static Compilation

• Given your Groovy code can be type checked...we can as well compile it « statically »

• ie. generate the same byte code as javac

• Also interesting for those stuck in JDK < 7 to benefit from performance improvements

Page 61: Groovy 2 and beyond

Static Compilation: advantages

• You gain:

•Type safety

• thanks to static type checking

• static compilation builds upon static type checking

• Faster code

• as close as possible to Java’s performance

•Code immune to « monkey patching »

• metaprogramming badly used can interfere with framework code

• Smaller bytecode size

Page 62: Groovy 2 and beyond

Static Compilation: disadvantages

• But you loose:

• Dynamic features

• metaclass changes, categories, etc.

• Dynamic method dispatch

• although as close as possible to « dynamic » Groovy

Page 63: Groovy 2 and beyond

Statically compiled & dynamic methods

@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Page 64: Groovy 2 and beyond

What about performance?

• Comparisons between:

• Java

• Groovy static compilation (Groovy 2.0)

• Groovy with primitive optimizations (Groovy 1.8+)

• Groovy without optimizations (Groovy 1.7)

Page 65: Groovy 2 and beyond

What about performance?

Fibonacci Pi (π) quadrature

Binarytrees

Java

Staticcompilation

Primitive optimizations

No prim.optimizations

191 ms 97 ms 3.6 s

197 ms 101 ms 4.3 s

360 ms 111 ms 23.7 s

2590 ms 3220 ms 50.0 s1.7

1.8

2.0

Page 66: Groovy 2 and beyond
Page 67: Groovy 2 and beyond

Back to the future...

Page 68: Groovy 2 and beyond

Full invoke dynamic support

• In Groovy 2.0, not all call paths were going through invoke dynamic calls

• essentially method calls only

• still used call site caching techniques

•On JDK 7 with the « indy » JAR, Groovy 2.1 uses invoke dynamic everywhere

• On JDK < 7, still uses call site caching

Groovy

2.1

Page 69: Groovy 2 and beyond

@DelegatesTo

• Static type checking works nicely for certain Domain-Specific Languages

• command chains, extension methods, etc.

• But for changes of delegation within closures, it’s not helping

• often used by DSLs like within Gradle

• Enters @DelegatesTo!

Groovy

2.1

Page 70: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

Page 71: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Page 72: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Page 73: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Static type checker doesn’t know about that foo() method

Page 74: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Page 75: Groovy 2 and beyond

@DelegatesTo Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Annotate with:@DelegatesTo(ExecSpec)

Page 76: Groovy 2 and beyond

@DelegatesTo

• With a special delegation strategy

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

Page 77: Groovy 2 and beyond

@DelegatesTo

• With a special delegation strategy

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

Annotate with:@DelegatesTo(value = ExecSpec, strategy = DELEGATE_FIRST)

Page 78: Groovy 2 and beyond

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Page 79: Groovy 2 and beyond

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target("id")

Page 80: Groovy 2 and beyond

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target("id") @DelegatesTo(target = "id")

Page 81: Groovy 2 and beyond

@DelegatesTo

• For DSLs using Groovy closure delegation

• Great for...

• documenting APIs

• IDE integration

• code completion, code navigation...

• working nicely with static type checking and static compilation

Groovy

2.1

Page 82: Groovy 2 and beyond

Custom type checking

• You can make Groovy’s static type checking even smarter, with your own smarts!

• even smarter than Java’s :-)

• Create your own type checker extension

Groovy

2.1

@TypeChecked(extensions  =                            'MyExtension.groovy')void  exec()  {        //  code  to  be  further  checked...}

Page 83: Groovy 2 and beyond

• Your own extension has access to an event-based API

Custom type checking

• onMethodSelection

• afterMethodCall

• beforeMethodCall

• afterVisitMethod

• beforeVisitMethod

• methodNotFound

• unresolvedVariable

• unresolvedProperty

• unresolvedAttribute

• incompatibleAssignment

Groovy

2.1

Page 84: Groovy 2 and beyond

Custom type checking

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

Groovy

2.1

MyExtension.groovy

Page 85: Groovy 2 and beyond

Custom type checking

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

Know your Groovy AST API well ;-)

Groovy

2.1

MyExtension.groovy

Page 86: Groovy 2 and beyond

Custom type checking

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

Know your Groovy AST API well ;-)

Groovy

2.1

MyExtension.groovyDoesn’t need

to be compiled

Page 87: Groovy 2 and beyond

Alias annotations

• Ability to create meta-annotations combining and/or parameterizing other annotations

• Works also for local AST transformations and their annotations

Groovy

2.1

Page 88: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

Page 89: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Page 90: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Collected annotations

Page 91: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Your own custom alias name

Collected annotations

Page 92: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

@MyAliasclass  Foo  {        String  name        int  age}

The « collector »

Your own custom alias name

Collected annotations

Page 93: Groovy 2 and beyond

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

@MyAliasclass  Foo  {        String  name        int  age}

The « collector »

Your own custom alias name

Use your concise alias

Collected annotations

Page 94: Groovy 2 and beyond

Take control of your Groovy!

• Groovy 1.8 introduced compilation customizers

• add imports, AST xforms, secure the AST...

• With static type checking and static compilation, we received feedback from people wanting them applied « by default »

• Allow to instruct the groovyc compiler with a configuration script

• groovyc -configurator compConf.groovy Foo.groovy

Groovy

2.1

Page 95: Groovy 2 and beyond

Take control of your Groovy!

• Add a default @ToString transform

Groovy

2.1

import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Page 96: Groovy 2 and beyond

Take control of your Groovy!

• Add a default @ToString transform

Groovy

2.1

import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Implicit «config» variable representing a CompilationConfiguration instance

Page 97: Groovy 2 and beyond

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

Page 98: Groovy 2 and beyond

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

Page 99: Groovy 2 and beyond

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

config.customizers  {        //  custom  filter  logic          //  with  compilation  units        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)        }}

Page 100: Groovy 2 and beyond

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Page 101: Groovy 2 and beyond

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Page 102: Groovy 2 and beyond

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Page 103: Groovy 2 and beyond

End of 2012... and the world?

2012GGeX

End of the world

Page 104: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

End of the world

Page 105: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

End of the world

Page 106: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

End of the world

Page 107: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

End of the world

Page 108: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

Page 109: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

Page 110: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

Page 111: Groovy 2 and beyond

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

Recoveringagain !

End of the world

Page 112: Groovy 2 and beyond

Happy New Year!

Jan7-13

Page 113: Groovy 2 and beyond

Happy New Year!

Jan7-13

Groovy 2.1 RC

Page 114: Groovy 2 and beyond

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Page 115: Groovy 2 and beyond

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Page 116: Groovy 2 and beyond

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Potential 2nd RC

Page 117: Groovy 2 and beyond

Happy New Year!

Jan22-29

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Potential 2nd RC

Page 118: Groovy 2 and beyond

Happy New Year!

Jan22-29

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Groovy 2.1Final !

Potential 2nd RC

Page 119: Groovy 2 and beyond

Back to 2013 and beyond

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Page 120: Groovy 2 and beyond

The infamous

MOP

2Groovy

3.0

Page 121: Groovy 2 and beyond

Antlr 4grammar

Groovy

4.0

Page 122: Groovy 2 and beyond

λJDK 8

Lambdas

Groovy

4.0

Page 123: Groovy 2 and beyond
Page 124: Groovy 2 and beyond

Summary (1/2)

• As always, a rich and blossoming ecosystem

•Groovy 2.0

• more modularity

• static theme

• static type checking

• static compilation

• JDK 7 theme

• invoke dynamic support

• project coin syntax enhancements

Page 125: Groovy 2 and beyond

Summary (2/2)

•Groovy 2.1

• complete indy support

• @DelegatesTo

• custom type checking for your DSLs

• alias annotation

• And beyond...

• a new MOP (Meta-Object Protocol)

• a new grammar with Antlr 4

• JDK 8 lambda support

Page 127: Groovy 2 and beyond

Picture credits

• Londonhttp://www.londonup.com/media/1251/Tower-Bridge-london-582331_1024_768.jpg

• cherry blossomhttp://wallpaperswide.com/cherry_blossom_3-wallpapers.html

• NKOTBhttp://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg

• USA todayhttp://www.adams-pr.com/images/uploads/USA_Today_logo.jpg

• back to the futurehttp://davidhiggerson.files.wordpress.com/2012/02/back-to-the-future-delorean.jpg

• magnifying glasshttp://www.renders-graphiques.fr/image/upload/normal/loupe.png

• Santa Claushttp://icons.iconarchive.com/icons/fasticon/santa-claus/256/Happy-SantaClaus-icon.png

• Champagnehttp://reallife101blogs.files.wordpress.com/2010/11/champagne_glasses2.jpg

• that’s all folkshttp://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg

• MOPhttp://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg

• grammarhttp://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg