Transcript
Page 1: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Groovy, in 2014 and beyondGuillaume Laforge — Groovy project lead / Pivotal

@glaforge

Page 2: Groovy in 2014 and Beyond

Stay up-to-date

Groovy Weekly Newsletter (Every Tuesday) http://beta.groovy-lang.org/groovy-weekly.html

2

Page 3: Groovy in 2014 and Beyond

Stay up-to-date

Google+ Groovy Page https://google.com/+groovy

3

Page 4: Groovy in 2014 and Beyond

Stay up-to-date

Google+ Groovy Community http://bit.ly/g-community

4

Page 5: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Agenda

Page 6: Groovy in 2014 and Beyond

The Groovy roadmap

6

2015 20142013

Groovy 2.3

Groovy 2.4Groovy 2.2

Groovy 2.5 ?

Groovy 3.0 ?

Page 7: Groovy in 2014 and Beyond

Groovy 2.3

• JDK 8 runtime support • Traits • New and updates AST transformations • NIO2 module • JSON improvements & performance gains • New Markup template engine • Documentation overhaul

7

Page 8: Groovy in 2014 and Beyond

Groovy 2.4

• Android support !

• New website !

• Potentially • Macro system? • New grammar?

8

Page 9: Groovy in 2014 and Beyond

Groovy 3.0

• New Meta-Object Protocol !

• Invoke-dynamic based runtime !

• Rewritten language grammar with Antlr v4 • unless re-scheduled for Groovy 2.4 • successful GSoC, but not fully complete coverage

9

Page 10: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Groovy 2.3

Page 11: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

JDK 8 support

Page 12: Groovy in 2014 and Beyond

JDK 8 support — closures vs lambdas

12

IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));  !Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it));

Page 13: Groovy in 2014 and Beyond

JDK 8 support — closures vs lambdas

12

IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));  !Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it));

IntStream.range(1,  100).forEach  {  println  it  }  !Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  }

Page 14: Groovy in 2014 and Beyond

JDK 8 support — closures vs lambdas

12

IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));  !Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it));

IntStream.range(1,  100).forEach  {  println  it  }  !Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  }

Use Groovy closureswherever you passlambdas in Java 8

Page 15: Groovy in 2014 and Beyond

To know all about AST transformations!

13

Groovy in the light of Java 8 by Guillaume Laforge Tue 12:45pm / F. Park 1

Page 16: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Traits

Page 17: Groovy in 2014 and Beyond

Traits

• Like interfaces, but with method bodies • similar to Java 8 interface default methods

• Elegant way to compose behavior • multiple inheritance without the « diamond » problem

• Traits can also be stateful • traits can have properties like normal classes

• Compatible with static typing and static compilation • class methods from traits also visible from Java classes

• Also possible to implement traits at runtime 15

Page 18: Groovy in 2014 and Beyond

Traits: a simple example

16

trait  FlyingAbility  {          String  fly()  {  "I'm  flying!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird()  !

assert  b.fly()  ==  "I'm  flying!"

Page 19: Groovy in 2014 and Beyond

Traits: a simple example

16

trait  FlyingAbility  {          String  fly()  {  "I'm  flying!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird()  !

assert  b.fly()  ==  "I'm  flying!"

« trait », a new keyword for a new concept

Page 20: Groovy in 2014 and Beyond

Traits: a simple example

16

trait  FlyingAbility  {          String  fly()  {  "I'm  flying!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird()  !

assert  b.fly()  ==  "I'm  flying!"

a class « implements »

a trait

Page 21: Groovy in 2014 and Beyond

Traits: a simple example

16

trait  FlyingAbility  {          String  fly()  {  "I'm  flying!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird()  !

assert  b.fly()  ==  "I'm  flying!"

the fly() method from the trait is available

Page 22: Groovy in 2014 and Beyond

Traits: a simple example

16

trait  FlyingAbility  {          String  fly()  {  "I'm  flying!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird()  !

assert  b.fly()  ==  "I'm  flying!"

Page 23: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

Page 24: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

a Groovy property

Page 25: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

implement the trait

Page 26: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

Groovy named argument constructor

Page 27: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

access the property

Page 28: Groovy in 2014 and Beyond

Traits: stateful

17

trait  Named  {          String  name  }  !

class  Bird  implements  Named  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'

Page 29: Groovy in 2014 and Beyond

Traits: inheritance

18

trait  Named  {  String  name  }  !

trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

Page 30: Groovy in 2014 and Beyond

Traits: inheritance

18

trait  Named  {  String  name  }  !

trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

extend the Named trait

Page 31: Groovy in 2014 and Beyond

Traits: inheritance

18

trait  Named  {  String  name  }  !

trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

access the name property

Page 32: Groovy in 2014 and Beyond

Traits: inheritance

18

trait  Named  {  String  name  }  !

trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

implement the composite trait

Page 33: Groovy in 2014 and Beyond

Traits: inheritance

18

trait  Named  {  String  name  }  !

trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }  }  !

class  Bird  implements  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

Page 34: Groovy in 2014 and Beyond

Traits: multiple inheritance & dynamic access

19

trait  FlyingAbility  {          String  fly()  {  "I'm  a  flying  $name!"  }  }  !

trait  Named  {  String  name  }  !

class  Bird  implements  Named,  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

Page 35: Groovy in 2014 and Beyond

Traits: multiple inheritance & dynamic access

19

trait  FlyingAbility  {          String  fly()  {  "I'm  a  flying  $name!"  }  }  !

trait  Named  {  String  name  }  !

class  Bird  implements  Named,  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

access a dynamic property

Page 36: Groovy in 2014 and Beyond

Traits: multiple inheritance & dynamic access

19

trait  FlyingAbility  {          String  fly()  {  "I'm  a  flying  $name!"  }  }  !

trait  Named  {  String  name  }  !

class  Bird  implements  Named,  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

implements two traits!

Page 37: Groovy in 2014 and Beyond

Traits: multiple inheritance & dynamic access

19

trait  FlyingAbility  {          String  fly()  {  "I'm  a  flying  $name!"  }  }  !

trait  Named  {  String  name  }  !

class  Bird  implements  Named,  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

dynamic ‘name’ property interpolated

Page 38: Groovy in 2014 and Beyond

Traits: multiple inheritance & dynamic access

19

trait  FlyingAbility  {          String  fly()  {  "I'm  a  flying  $name!"  }  }  !

trait  Named  {  String  name  }  !

class  Bird  implements  Named,  FlyingAbility  {}  def  b  =  new  Bird(name:  'Colibri')  !

assert  b.name  ==  'Colibri'  assert  b.fly()  ==  "I'm  a  flying  Colibri!"

Page 39: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

Page 40: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

two surf() methods

Page 41: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

Page 42: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

extending a class and implementing the two traits

Page 43: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

Page 44: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

last declared trait wins!

Page 45: Groovy in 2014 and Beyond

Traits: what about conflicts?

20

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'web'

Page 46: Groovy in 2014 and Beyond

Traits: what about conflicts?

21

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Page 47: Groovy in 2014 and Beyond

Traits: what about conflicts?

21

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

reverse the order!

Page 48: Groovy in 2014 and Beyond

Traits: what about conflicts?

21

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Page 49: Groovy in 2014 and Beyond

Traits: what about conflicts?

22

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }  }  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Page 50: Groovy in 2014 and Beyond

Traits: what about conflicts?

22

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }  }  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Be explicit! Override surf()

& use ‘super’

Page 51: Groovy in 2014 and Beyond

Traits: what about conflicts?

22

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }  }  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Your class method takes precedence over the traits

Page 52: Groovy in 2014 and Beyond

Traits: what about conflicts?

22

trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  !trait  WebSurfer    {  String  surf()  {    'web'  }  }  !class  Person  {  String  name  }  !class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }  }  !def  h  =  new  Hipster()  assert  h.surf()  ==  'kite'

Page 53: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  class  NamedAnimal  implements  Named  {}  !

def  na  =  new  NamedAnimal(name:  'Felix')  !

assert  na.name  ==  'Felix'

Traits: runtime implementation

23

Page 54: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  class  NamedAnimal  implements  Named  {}  !

def  na  =  new  NamedAnimal(name:  'Felix')  !

assert  na.name  ==  'Felix'

Traits: runtime implementation

23

Somewhat artificial to have to create an intermediary class to

get named animals

Page 55: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  class  NamedAnimal  implements  Named  {}  !

def  na  =  new  NamedAnimal(name:  'Felix')  !

assert  na.name  ==  'Felix'

Traits: runtime implementation

23

Page 56: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  !

!

def  na  =  new  Animal()  as  Named  na.name  =  'Felix'  assert  na.name  ==  'Felix'

Traits: runtime implementation

24

Page 57: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  !

!

def  na  =  new  Animal()  as  Named  na.name  =  'Felix'  assert  na.name  ==  'Felix'

Traits: runtime implementation

24

Runtime trait, with Groovy’s usual

coercion mechanism

Page 58: Groovy in 2014 and Beyond

trait  Named  {          String  name  }  !

class  Animal  {}  !

!

def  na  =  new  Animal()  as  Named  na.name  =  'Felix'  assert  na.name  ==  'Felix'

Traits: runtime implementation

24

Page 59: Groovy in 2014 and Beyond

Traits: runtime implementation

25

trait  Named  {  String  name  }  !

trait  Quacks  {          String  quack()  {  'Quack!'  }  }  !

class  Animal  {}  !

def  na  =  new  Animal().withTraits  Named,  Quacks  na.name  =  'Daffy'  assert  na.name  ==  'Daffy'  assert  na.quack()  ==  'Quack!'

Page 60: Groovy in 2014 and Beyond

Traits: runtime implementation

25

trait  Named  {  String  name  }  !

trait  Quacks  {          String  quack()  {  'Quack!'  }  }  !

class  Animal  {}  !

def  na  =  new  Animal().withTraits  Named,  Quacks  na.name  =  'Daffy'  assert  na.name  ==  'Daffy'  assert  na.quack()  ==  'Quack!'

Implement several traits at once, at runtime

Page 61: Groovy in 2014 and Beyond

Traits: runtime implementation

25

trait  Named  {  String  name  }  !

trait  Quacks  {          String  quack()  {  'Quack!'  }  }  !

class  Animal  {}  !

def  na  =  new  Animal().withTraits  Named,  Quacks  na.name  =  'Daffy'  assert  na.name  ==  'Daffy'  assert  na.quack()  ==  'Quack!'

Page 62: Groovy in 2014 and Beyond

Traits: miscellaneous

• Traits can… !

• have private fields and methods • have abstract methods • implement interfaces • extend other traits or implement several traits • be statically type checked and compiled

26

Page 63: Groovy in 2014 and Beyond

To know all about traits!

27

Rethinking API design with traits by Cédric Champeau Tue 2:30pm / Trinity 3

Page 64: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

AST transforms

Page 65: Groovy in 2014 and Beyond

New: @TailRecursive

29

import  groovy.transform.TailRecursive  !

@TailRecursive  def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)  }  !

assert  fact(1000)  >  10e2566

Page 66: Groovy in 2014 and Beyond

New: @TailRecursive

29

import  groovy.transform.TailRecursive  !

@TailRecursive  def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)  }  !

assert  fact(1000)  >  10e2566

Rewrites tail recursive friendly function serially

Page 67: Groovy in 2014 and Beyond

New: @TailRecursive

29

import  groovy.transform.TailRecursive  !

@TailRecursive  def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)  }  !

assert  fact(1000)  >  10e2566

Doesn’t blow up with a stack overflow error

Page 68: Groovy in 2014 and Beyond

New: @TailRecursive

29

import  groovy.transform.TailRecursive  !

@TailRecursive  def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)  }  !

assert  fact(1000)  >  10e2566

Downside of tail recursion is you might have to rewrite

your algo to be tailrec friendly

Page 69: Groovy in 2014 and Beyond

New: @TailRecursive

29

import  groovy.transform.TailRecursive  !

@TailRecursive  def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)  }  !

assert  fact(1000)  >  10e2566

Page 70: Groovy in 2014 and Beyond

New: @Sortable

30

import  groovy.transform.*  !

@Sortable  class  Person  {          String  lastName          String  firstName          int  age  }

Page 71: Groovy in 2014 and Beyond

New: @Sortable

30

import  groovy.transform.*  !

@Sortable  class  Person  {          String  lastName          String  firstName          int  age  }

Makes the class Comparable by multiple Comparators

Page 72: Groovy in 2014 and Beyond

New: @Sortable

30

import  groovy.transform.*  !

@Sortable  class  Person  {          String  lastName          String  firstName          int  age  }

First compare by lastName, then by firstName, etc.

Page 73: Groovy in 2014 and Beyond

New: @Sortable

30

import  groovy.transform.*  !

@Sortable  class  Person  {          String  lastName          String  firstName          int  age  }

You can also specify ‘includes’ / ‘excludes’

properties

Page 74: Groovy in 2014 and Beyond

New: @Sortable

30

import  groovy.transform.*  !

@Sortable  class  Person  {          String  lastName          String  firstName          int  age  }

Page 75: Groovy in 2014 and Beyond

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

@BaseScript(CustomBase)  import  groovy.transform.BaseScript  !

assert  meaningOfLife  ==  42

Page 76: Groovy in 2014 and Beyond

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

@BaseScript(CustomBase)  import  groovy.transform.BaseScript  !

assert  meaningOfLife  ==  42

You can add your own base methods and properties to all compiled scripts

Page 77: Groovy in 2014 and Beyond

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

@BaseScript(CustomBase)  import  groovy.transform.BaseScript  !

assert  meaningOfLife  ==  42

Define the base script class for this script

Page 78: Groovy in 2014 and Beyond

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

@BaseScript(CustomBase)  import  groovy.transform.BaseScript  !

assert  meaningOfLife  ==  42

Ability to put the annotation on imports & package

Page 79: Groovy in 2014 and Beyond

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

@BaseScript(CustomBase)  import  groovy.transform.BaseScript  !

assert  meaningOfLife  ==  42

Page 80: Groovy in 2014 and Beyond

@BaseScript custom abstract method

32

abstract  class  CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }  !    abstract  internalRun()  !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }  }

Page 81: Groovy in 2014 and Beyond

@BaseScript custom abstract method

32

abstract  class  CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }  !    abstract  internalRun()  !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }  }

import  groovy.transform.BaseScript  @BaseScript  CustomBase  script  !println  'Hello'

Page 82: Groovy in 2014 and Beyond

@BaseScript custom abstract method

32

abstract  class  CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }  !    abstract  internalRun()  !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }  }

import  groovy.transform.BaseScript  @BaseScript  CustomBase  script  !println  'Hello'

You can define your own abstract method for script bodies

Page 83: Groovy in 2014 and Beyond

@BaseScript custom abstract method

32

abstract  class  CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }  !    abstract  internalRun()  !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }  }

import  groovy.transform.BaseScript  @BaseScript  CustomBase  script  !println  'Hello'

Page 84: Groovy in 2014 and Beyond

To know all about AST transformations!

33

Groovy AST transformations by Paul King Wed 2:30pm / Trinity 3

Page 85: Groovy in 2014 and Beyond

To know all about AST transformations!

34

Writing AST transformations by Simon / Sadogursky Thu 10:30pm / F. Park 3

Page 86: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

NIO2 module

Page 87: Groovy in 2014 and Beyond

JDK 7+ NIO2 module

• All the familiar methods on File retrofitted on Path as well

36

path.withReader  {  Reader  r  -­‐>  ...  }  path.eachLine  {  String  line  -­‐>  ...  }  path.eachFileRecurse  {  Path  p  -­‐>  ...  }  path  <<  'some  content'  path  <<  bytes  path.readLines()  …

Page 88: Groovy in 2014 and Beyond

JDK 7+ NIO2 module

• All the familiar methods on File retrofitted on Path as well

36

path.withReader  {  Reader  r  -­‐>  ...  }  path.eachLine  {  String  line  -­‐>  ...  }  path.eachFileRecurse  {  Path  p  -­‐>  ...  }  path  <<  'some  content'  path  <<  bytes  path.readLines()  …

Feature request to add all the java.nio.file.Files static utility

methods as GDK

Page 89: Groovy in 2014 and Beyond

JDK 7+ NIO2 module

• All the familiar methods on File retrofitted on Path as well

36

path.withReader  {  Reader  r  -­‐>  ...  }  path.eachLine  {  String  line  -­‐>  ...  }  path.eachFileRecurse  {  Path  p  -­‐>  ...  }  path  <<  'some  content'  path  <<  bytes  path.readLines()  …

Page 90: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

JSON

Page 91: Groovy in 2014 and Beyond

JSON parser / builder perf. increase

• Re-implementation of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned !

• Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html

38

Page 92: Groovy in 2014 and Beyond

JSON parser / builder perf. increase

• Re-implementation of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned !

• Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html

38

Page 93: Groovy in 2014 and Beyond

JSON parser / builder perf. increase

• Re-implementation of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned !

• Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html

38

Benchmark gives 3x to 4x performance factor

over Jackson and GSON

Page 94: Groovy in 2014 and Beyond

JSON parser / builder perf. increase

• Re-implementation of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned !

• Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html

38

Page 95: Groovy in 2014 and Beyond

New modes for parsing

• Original JsonSlurper renamed to JsonSlurperClassic !

• Additional parsing modes: • INDEX_OVERLAY: super fast for <2MB payloads

o using a « parsing overlay » technique • CHARACTER_SOURCE: for >2MB payloads

o implemented with sliding windows over readers • LAX: beyond the JSON spec, nice for configuration files

o support single quotes, / and # comments • CHAR_BUFFER: general purpose

39

Page 96: Groovy in 2014 and Beyond

JsonSlurper for configuration files

40

import  groovy.json.*  import  static  groovy.json.JsonParserType.*  !def  parser  =  new  JsonSlurper().setType(LAX)  !def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }  '''  !assert  conf.environment  ==  'production'  assert  conf.server  ==  5

Page 97: Groovy in 2014 and Beyond

JsonSlurper for configuration files

40

import  groovy.json.*  import  static  groovy.json.JsonParserType.*  !def  parser  =  new  JsonSlurper().setType(LAX)  !def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }  '''  !assert  conf.environment  ==  'production'  assert  conf.server  ==  5

More tolerant parser: single quotes,

non-quoted keys, // and # comments,

missing comas

Page 98: Groovy in 2014 and Beyond

JsonSlurper for configuration files

40

import  groovy.json.*  import  static  groovy.json.JsonParserType.*  !def  parser  =  new  JsonSlurper().setType(LAX)  !def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }  '''  !assert  conf.environment  ==  'production'  assert  conf.server  ==  5

Page 99: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Markup template engine

</>

Page 100: Groovy in 2014 and Beyond

Markup template engine

• Based on the principles of Groovy’s « builders » • and particularly the MarkupBuilder class

for generating arbitrary XML / HTML payloads !

• Compiled statically for fast template rendering !

• Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl !

• Custom base template class • ability to provide reusable methods across your templates 42

Page 101: Groovy in 2014 and Beyond

Markup template engine

• Based on the principles of Groovy’s « builders » • and particularly the MarkupBuilder class

for generating arbitrary XML / HTML payloads !

• Compiled statically for fast template rendering !

• Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl !

• Custom base template class • ability to provide reusable methods across your templates 42

Spring Boot approved

Page 102: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

Page 103: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

Your template

Page 104: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)!]]

Page 105: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)!]]

Feed a model into your template

Page 106: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)!]]

<cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>!</cars>

Page 107: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)!]]

<cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>!</cars>

Generate the XML output

Page 108: Groovy in 2014 and Beyond

Markup template engine — the idea

43

cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }  }

model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)!]]

<cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>!</cars>

Page 109: Groovy in 2014 and Beyond

Markup template engine — in action

44

import  groovy.text.markup.*  !def  config  =  new  TemplateConfiguration()  def  engine  =  new  MarkupTemplateEngine(config)  def  tmpl  =  engine.createTemplate('''          p("Hello  ${model.name}")  ''')  def  model  =  [name:  'World']  System.out  <<  tmpl.make(model)

Page 110: Groovy in 2014 and Beyond

Markup template engine — includes

45

//  include  another  template  include  template:  'foo.tpl'          //  include  raw  content  include  unescaped:  'raw.txt'  !

//  escape  &  include  include  escaped:  'to_escape.txt'

Page 111: Groovy in 2014 and Beyond

Markup template engine

46

//  escaped  automatically  yield  'some  raw  content'  !//  include  raw  content  yieldUnescaped  'content'  !//  <?xml  version='1.0'?>  xmlDeclaration()                

Page 112: Groovy in 2014 and Beyond

Markup template engine

46

//  escaped  automatically  yield  'some  raw  content'  !//  include  raw  content  yieldUnescaped  'content'  !//  <?xml  version='1.0'?>  xmlDeclaration()                

//  <!-­‐-­‐comment-­‐-­‐>  comment  'comment'                !//  adds  new  lines  newLine()                                !//  process.  instruct.  pi(/*  ...  */)                      

Page 113: Groovy in 2014 and Beyond

Markup template engine — configuration options

!!!

• declaration encoding !

• expand empty elements !

• use double quotes !

• newline string !!!!!!!

!!

!• auto escape

!• auto indent

!• base template class

!• locale

47

Page 114: Groovy in 2014 and Beyond

Markup template engine — static!

• Type-checked templates available • use createTypeCheckedModelTemplate()

instead of createTemplate() !

• Advantages • get compilation errors

o if a variable is not available o if you make mistakes in the code snippets

• even faster templates

48

Page 115: Groovy in 2014 and Beyond

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

Page 116: Groovy in 2014 and Beyond

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

def  modelTypes  =  [cars:  "List<Car>"]  !def  tmpl  =  engine.      createTypeCheckedModelTemplate(            "page.tpl",  modelTypes)

Page 117: Groovy in 2014 and Beyond

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

def  modelTypes  =  [cars:  "List<Car>"]  !def  tmpl  =  engine.      createTypeCheckedModelTemplate(            "page.tpl",  modelTypes)

modelTypes  =  {          List<Car>  cars  }  !cars.each  {  car  -­‐>          p("Car  name:  $car.name")  }

Page 118: Groovy in 2014 and Beyond

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

def  modelTypes  =  [cars:  "List<Car>"]  !def  tmpl  =  engine.      createTypeCheckedModelTemplate(            "page.tpl",  modelTypes)

modelTypes  =  {          List<Car>  cars  }  !cars.each  {  car  -­‐>          p("Car  name:  $car.name")  }

Works with createTemplate() too

Page 119: Groovy in 2014 and Beyond

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

def  modelTypes  =  [cars:  "List<Car>"]  !def  tmpl  =  engine.      createTypeCheckedModelTemplate(            "page.tpl",  modelTypes)

modelTypes  =  {          List<Car>  cars  }  !cars.each  {  car  -­‐>          p("Car  name:  $car.name")  }

Page 120: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Documentation overhaul

Page 121: Groovy in 2014 and Beyond

GroovyDoc

51

Page 122: Groovy in 2014 and Beyond

GroovyDoc

51

Page 123: Groovy in 2014 and Beyond

GroovyDoc

51

Page 124: Groovy in 2014 and Beyond

Groovy GDK documentation

52

Page 125: Groovy in 2014 and Beyond

Groovy GDK documentation

52

Page 126: Groovy in 2014 and Beyond

Brand new documentation

53

Page 127: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Groovy 2.4

Page 128: Groovy in 2014 and Beyond

Beta groovy-lang.org website

55

Page 129: Groovy in 2014 and Beyond

Beta groovy-lang.org website

55

Page 130: Groovy in 2014 and Beyond

Beta groovy-lang.org website

55

Page 131: Groovy in 2014 and Beyond

Beta groovy-lang.org website

55

Notice the « improve this doc » button!

Page 132: Groovy in 2014 and Beyond

Android support

• You can use Groovy to code Android apps! • use Groovy 2.4.0-beta-1+ • prefer @CompileStatic !

• Two great posts to get started: • http://melix.github.io/blog/2014/06/grooid.html • http://melix.github.io/blog/2014/06/grooid2.html

56

Page 133: Groovy in 2014 and Beyond

New York Times — Getting Groovy with Android

57

Page 134: Groovy in 2014 and Beyond

New York Times — Getting Groovy with Android

57

http://bit.ly/nyt-groovy

Page 135: Groovy in 2014 and Beyond

Android support

58

Page 136: Groovy in 2014 and Beyond

Android support

58

Page 137: Groovy in 2014 and Beyond

Android support

58

Source code available:https://github.com/melix/gr8confagenda

Page 138: Groovy in 2014 and Beyond

To know all about AST transformations!

59

Groovy & Android, a winning pair? by Cédric Champeau Thu 12:45pm / Trinity 3

Page 139: Groovy in 2014 and Beyond

Groovy Macros

!

• Sergei Egorov wants to contribute a macro module • https://github.com/groovy/groovy-core/pull/470 !

• Simplify creation of AST transformations • less boilerplate manipulating the Groovy AST API • more powerful and less limited than AstBuilder

60

Page 140: Groovy in 2014 and Beyond

Groovy Macros

!

• Authoring AST transformations can be verbose:

61

def  someVariable  =  new  ConstantExpression("xyz")  def  returnStatement  =  new  ReturnStatement(          new  ConstructorCallExpression(                  ClassHelper.make(SomeCoolClass),                  new  ArgumentListExpression(someVariable)          )  )

Page 141: Groovy in 2014 and Beyond

Groovy Macros

• With Groovy Macros, it could be simpler:

62

def  someVariable  =  macro  {  "xyz"  }  def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })    }

Page 142: Groovy in 2014 and Beyond

Groovy Macros

• With Groovy Macros, it could be simpler:

62

def  someVariable  =  macro  {  "xyz"  }  def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })    }

Special « macro » command

Page 143: Groovy in 2014 and Beyond

Groovy Macros

• With Groovy Macros, it could be simpler:

62

def  someVariable  =  macro  {  "xyz"  }  def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })    }

Special « macro » command

Quasi-quotation

Page 144: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Groovy 3.0

Page 145: Groovy in 2014 and Beyond
Page 146: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

New Age Meta-Object Protocol

MOP 2

Page 147: Groovy in 2014 and Beyond

Goals for the new MOP

• Leverage & build upon JDK 7+ invoke dynamic • get Java-like performance even for dynamic code

• Rationalize the sedimentation of meta-programming • more coherence, less corner cases & inconsistencies

• Provide a notion of « realm » • shield users of « monkey patching » • finer-grained control of meta-programming reach

• Private visibility anyone?

66

Page 148: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Rewriting the Groovy grammar

with Antlr v4

Antlr v4 Grammar

Page 149: Groovy in 2014 and Beyond

Antlr v4 grammar

• Problems • Groovy still uses Antlr v2!

o but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar

o harder to fix and evolve, especially with Antlr v2 • Advantages

• Start from a clean slate • Antlr 4 more tolerant

and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs!

68

Page 150: Groovy in 2014 and Beyond

Antlr v4 grammar

• Problems • Groovy still uses Antlr v2!

o but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar

o harder to fix and evolve, especially with Antlr v2 • Advantages

• Start from a clean slate • Antlr 4 more tolerant

and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs!

68

A « Google Summer of Code » student is currently helping

Page 151: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Support the new Java 8

language features

Java 8 language support

Page 152: Groovy in 2014 and Beyond

Java 8 support

• Additional grammar & semantic features to support • to keep saying Groovy / Java interoperability is awesome!

• New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations

70

Page 153: Groovy in 2014 and Beyond

Java 8 support

• Additional grammar & semantic features to support • to keep saying Groovy / Java interoperability is awesome!

• New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations

70

Groovy had already: closures, method pointers, mixins,

enriched collection & time APIs

Page 154: Groovy in 2014 and Beyond

To know all about AST transformations!

71

How to get Groovy with Java 8 by Peter Ledbrook Thu 10:30pm / Trinity 3

Page 155: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Summary

Page 156: Groovy in 2014 and Beyond
Page 157: Groovy in 2014 and Beyond

Groovy rocks the JVM since 2003!

Page 158: Groovy in 2014 and Beyond

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Q & A

Page 159: Groovy in 2014 and Beyond
Page 160: Groovy in 2014 and Beyond

Image credits• Big rock

• http://wallpaper.preview-reviews.com/12852-red-rocks-in-a-snowstorm • Android robot

• http://crackberry.com/sites/crackberry.com/files/styles/large/public/topic_images/2013/ANDROID.png?itok=xhm7jaxS • Modern MOP

• http://i933.photobucket.com/albums/ad179/autobin/Wonder%20Mop/wondermop4.jpg • Jason

• http://static.comicvine.com/uploads/original/3/32405/1031312-jason_19_inch_figure_l.jpg • Jigsaw

• http://www.psdgraphics.com/file/psd-jigsaw-icon.jpg • Many thanks

• http://www.trys.ie/wp-content/uploads/2013/06/many-thanks.jpg

76


Top Related