groovy in 2014 and beyond

Post on 02-Jul-2015

801 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

With 3 million downloads in a year, Groovy still clearly leads the pack of alternative languages on the JVM, but it's not resting on its laurels. The latest Groovy 2.3 release is pack full of useful new features and performance improvements. In particular, Groovy now supports the concept of "traits" for elegantly composing behaviors. Its JSON support is now the most performant among all the JSON libraries available to date. Groovy 2.3 introduces a new markup-based template engine, new code transformations, and much more.

TRANSCRIPT

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

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

@glaforge

Stay up-to-date

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

2

Stay up-to-date

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

3

Stay up-to-date

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

4

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

Agenda

The Groovy roadmap

6

2015 20142013

Groovy 2.3

Groovy 2.4Groovy 2.2

Groovy 2.5 ?

Groovy 3.0 ?

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

Groovy 2.4

• Android support !

• New website !

• Potentially • Macro system? • New grammar?

8

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

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

Groovy 2.3

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

JDK 8 support

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));

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  }

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

To know all about AST transformations!

13

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

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

Traits

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

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!"

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

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

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

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!"

Traits: stateful

17

trait  Named  {          String  name  }  !

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

assert  b.name  ==  'Colibri'

Traits: stateful

17

trait  Named  {          String  name  }  !

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

assert  b.name  ==  'Colibri'

a Groovy property

Traits: stateful

17

trait  Named  {          String  name  }  !

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

assert  b.name  ==  'Colibri'

implement the trait

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

Traits: stateful

17

trait  Named  {          String  name  }  !

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

assert  b.name  ==  'Colibri'

access the property

Traits: stateful

17

trait  Named  {          String  name  }  !

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

assert  b.name  ==  'Colibri'

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!"

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

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

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

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!"

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!"

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

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!

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

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!"

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'

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

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'

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

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'

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!

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'

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'

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!

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'

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'

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’

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

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'

trait  Named  {          String  name  }  !

class  Animal  {}  class  NamedAnimal  implements  Named  {}  !

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

assert  na.name  ==  'Felix'

Traits: runtime implementation

23

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

trait  Named  {          String  name  }  !

class  Animal  {}  class  NamedAnimal  implements  Named  {}  !

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

assert  na.name  ==  'Felix'

Traits: runtime implementation

23

trait  Named  {          String  name  }  !

class  Animal  {}  !

!

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

Traits: runtime implementation

24

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

trait  Named  {          String  name  }  !

class  Animal  {}  !

!

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

Traits: runtime implementation

24

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!'

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

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!'

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

To know all about traits!

27

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

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

AST transforms

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

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

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

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

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

New: @Sortable

30

import  groovy.transform.*  !

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

New: @Sortable

30

import  groovy.transform.*  !

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

Makes the class Comparable by multiple Comparators

New: @Sortable

30

import  groovy.transform.*  !

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

First compare by lastName, then by firstName, etc.

New: @Sortable

30

import  groovy.transform.*  !

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

You can also specify ‘includes’ / ‘excludes’

properties

New: @Sortable

30

import  groovy.transform.*  !

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

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

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

assert  meaningOfLife  ==  42

@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

@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

@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

@BaseScript improvements

31

abstract  class  CustomBase  extends  Script  {          int  meaningOfLife  =  42  }

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

assert  meaningOfLife  ==  42

@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'    }  }

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

@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

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

To know all about AST transformations!

33

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

To know all about AST transformations!

34

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

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

NIO2 module

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()  …

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

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()  …

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

JSON

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

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

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

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

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

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

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

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

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

Markup template engine

</>

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

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

Markup template engine — the idea

43

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

Markup template engine — the idea

43

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

Your template

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’)!]]

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

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>

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

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>

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)

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'

Markup template engine

46

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

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(/*  ...  */)                      

Markup template engine — configuration options

!!!

• declaration encoding !

• expand empty elements !

• use double quotes !

• newline string !!!!!!!

!!

!• auto escape

!• auto indent

!• base template class

!• locale

47

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

Markup template engine — static!

• With typed check model creation method

!

!

!

!

!

!

!

!

!

• Or declare your model types in the template

49

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)

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

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

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

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

Documentation overhaul

GroovyDoc

51

GroovyDoc

51

GroovyDoc

51

Groovy GDK documentation

52

Groovy GDK documentation

52

Brand new documentation

53

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

Groovy 2.4

Beta groovy-lang.org website

55

Beta groovy-lang.org website

55

Beta groovy-lang.org website

55

Beta groovy-lang.org website

55

Notice the « improve this doc » button!

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

New York Times — Getting Groovy with Android

57

New York Times — Getting Groovy with Android

57

http://bit.ly/nyt-groovy

Android support

58

Android support

58

Android support

58

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

To know all about AST transformations!

59

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

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

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

Groovy Macros

• With Groovy Macros, it could be simpler:

62

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

Groovy Macros

• With Groovy Macros, it could be simpler:

62

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

Special « macro » command

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

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

Groovy 3.0

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

New Age Meta-Object Protocol

MOP 2

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

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

Rewriting the Groovy grammar

with Antlr v4

Antlr v4 Grammar

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

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

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

Support the new Java 8

language features

Java 8 language support

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

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

To know all about AST transformations!

71

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

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

Summary

Groovy rocks the JVM since 2003!

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

Q & A

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