what makes groovy groovy - guillaume laforge (pivotal)

255
Guillaume Laforge @glaforge What makes Groovy groovy?

Upload: jaxlondonconference

Post on 06-May-2015

950 views

Category:

Technology


1 download

DESCRIPTION

Presented at JAX London 2013 Groovy is not a newcomer to the arena of alternative languages for the JVM. With over 1.7 million downloads a year, it's clearly ahead of the pack. But what makes it a great choice for your projects? - a flat learning curve for Java developers - its seamless Java integration where you can mix & mash Groovy & Java together - a malleable & concise syntax fit for Domain-Specific Languages - an interesting take on type safety - its rich ecosystem of projects: Grails, Gradle, GPars, Spock, Griffon, Geb...

TRANSCRIPT

Page 1: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Guillaume Laforge @glaforge !

What makes Groovy groovy?

Page 2: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Guillaume Laforge

Groovy project lead at .

!

@glaforge http://glaforge.appspot.com

Page 3: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 4: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Groovy vision

Part 1

Page 5: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 6: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Simplify the life of(Java) developers

Page 7: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 8: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy as aJava superset

Page 9: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

It’s so easyto learn!

Groovy as aJava superset

Page 10: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 11: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 12: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 13: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

Page 14: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 15: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

As safe and fast as Java withstatic type checking & compilation

Page 16: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

As safe and fast as Java withstatic type checking & compilation

Page 17: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 18: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

new  MarkupBuilder().html  {          head  {                  title  "The  Script  Bowl"          }  !

       body  {                  div(class:  "banner")  {                          p  "Groovy  rocks!"                  }          }  }

Page 19: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 20: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

move  forward  at  3.km/h

Expressive,Concise,Readable

Page 21: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 22: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 23: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@RestController  class  App  {          @RequestMapping("/")          String  home()  {  "Hello  World!"  }  }

Speaking of conciseness...A full Spring app in the span of a tweet!

Page 24: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

million downloadsper year1.7

Page 25: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 26: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Great forscripting

Page 27: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Great forscripting

Fit for Domain-Specific Languages

Page 28: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Great forscripting

Fit for Domain-Specific Languages

Most seamless integration &interoperability wih java!

Page 29: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 30: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 31: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Yup, we’re allusing Groovy!

Page 32: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Cool Groovy gems

Part 2

Page 33: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 34: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Most Java code is alsovalid Groovy code!

Page 35: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Any Java developer is aGroovy developer!

Most Java code is alsovalid Groovy code!

Page 36: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 37: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Flat learningcurve

Page 38: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Flat learningcurve

Easy to learn

Page 39: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Scripts versus Classes

!18

public  class  Main  {          public  static  void  main(String[]  args)  {                  System.out.println("Hello");          }  }

vs

Page 40: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Scripts versus Classes

!18

public  class  Main  {          public  static  void  main(String[]  args)  {                  System.out.println("Hello");          }  }

println  "Hello"

vs

Page 41: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

Page 42: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

Semicolons

Page 43: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

SemicolonsParentheses

Page 44: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

SemicolonsParentheses

return keyword

Page 45: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

SemicolonsParentheses

return keyword public keyword

Page 46: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional

SemicolonsParentheses

return keyword public keyword

Typing!

Page 47: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!20

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Page 48: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!20

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Semicolons

Page 49: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!21

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

Page 50: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!22

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

Page 51: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!22

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

Parentheses

Page 52: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!23

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 53: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!23

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

return keyword

Page 54: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!24

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                                owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 55: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!24

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                                owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

public keyword

Page 56: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!25

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 57: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!25

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

optional typing

Page 58: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!26

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 59: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!26

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

handy println shortcut

Page 60: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!27

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Page 61: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!27

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

verbose Java properties!

Page 62: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!28

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Page 63: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!28

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Property notation

Page 64: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!29

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.owner        "Guillaume"  !                      println  greeter.greet("Marion")

Page 65: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!29

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.owner        "Guillaume"  !                      println  greeter.greet("Marion")

Named argumentconstructor

Page 66: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!30

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Page 67: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!30

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Interpolated strings!(aka GStrings)

Page 68: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!31

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  ${name},  I  am  ${owner}"          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Page 69: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!31

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  ${name},  I  am  ${owner}"          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Let’s reformat thatmess of whitespace!

Page 70: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!32

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

Page 71: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!32

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Page 72: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Optional...

!32

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

Page 73: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Native syntax constructs

!33

//  closures  def  adder  =  {  a,  b  -­‐>  a  +  b  }  !//  lists  def  list  =  [1,  2,  3,  4,  5]  !//  maps  def  map  =  [a:  1,  b:  2,  c:  3]  !//  regular  expressions  def  regex  =  ~/.*foo.*/  !//  ranges  def  range  128..255

Page 74: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — the basics

!34

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Page 75: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — the basics

!34

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Closureparameters

Page 76: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — the basics

!34

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Assign a functioninto a variable

Closureparameters

Page 77: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — the basics

!34

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Short form of:adder.call(‘a’, ‘b’)

Assign a functioninto a variable

Closureparameters

Page 78: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — the basics

!34

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Short form of:adder.call(‘a’, ‘b’)

Genericity withduck typing &

operator overloading

Assign a functioninto a variable

Closureparameters

Page 79: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — explicit type

!35

!def  intAdder  =  {  int  a,  int  b  -­‐>  a  +  b  }  

Page 80: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — explicit type

!35

!def  intAdder  =  {  int  a,  int  b  -­‐>  a  +  b  }  

Be explicit aboutthe types

Page 81: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — implicit parameter

!36

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Page 82: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — implicit parameter

!36

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Implicitparameter

Page 83: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — implicit parameter

!36

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Implicitparameter

Multiply alsodefined on strings

Page 84: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — variable arguments

!37

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

Page 85: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — variable arguments

!37

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

Variable numberof arguments

Page 86: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — variable arguments

!37

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

You can specifythe type: int...

Variable numberof arguments

Page 87: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — default values

!38

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Page 88: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — default values

!38

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Page 89: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — default values

!38

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Provided valuefor b

Page 90: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — default values

!38

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Provided valuefor b

Default valueused for b

Page 91: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — methods as functions

!39

def  logBase10  =  Math.&log10  def  printer  =  System.out.&println  !

assert  logBase10(10)  ==  1  printer  'abc'

Page 92: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — methods as functions

!39

def  logBase10  =  Math.&log10  def  printer  =  System.out.&println  !

assert  logBase10(10)  ==  1  printer  'abc'

Turn a method into a closure function

Page 93: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

Page 94: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

Page 95: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

Page 96: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

Page 97: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

Page 98: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

Page 99: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

Page 100: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

assert  names  ==  "ERINE,  MARION"

Page 101: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — map / filter / reduce

!40

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

assert  names  ==  "ERINE,  MARION"

find/findAll, inject, collect, flatten, min/max, unique,

reverse, collate, groupBy, any/every, head/tail/last, count/

countBy, combinations/permutations/subsequences/

transpose, withDefault/withLazyDefault

Page 102: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — resource handling

!41

new  File('bible.txt').withReader  {  r  -­‐>          new  File('out.txt').withWriter  {  w  -­‐>                  r.eachLine  {  line  -­‐>                          if  (line.contains('Groovy'))                                  w  <<  line.toUpperCase()                  }          }  }

Page 103: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — resource handling

!41

new  File('bible.txt').withReader  {  r  -­‐>          new  File('out.txt').withWriter  {  w  -­‐>                  r.eachLine  {  line  -­‐>                          if  (line.contains('Groovy'))                                  w  <<  line.toUpperCase()                  }          }  }

Take care of properlyopening / closing resources

Page 104: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — custom control structures

!42

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Page 105: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — custom control structures

!42

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Closure as last argument

Page 106: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Closures — custom control structures

!42

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Closure as last argument

Equivalent to:unless(10<9, {...})

Page 107: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lists

!43

def  list  =  ['a',  'b',  'c']  !list  <<  'd'  assert  list.contains('d')  !assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

Page 108: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lists

!43

def  list  =  ['a',  'b',  'c']  !list  <<  'd'  assert  list.contains('d')  !assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definition

Page 109: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lists

!43

def  list  =  ['a',  'b',  'c']  !list  <<  'd'  assert  list.contains('d')  !assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definitionAppend an element

(operator overloading)

Page 110: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lists

!43

def  list  =  ['a',  'b',  'c']  !list  <<  'd'  assert  list.contains('d')  !assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definitionAppend an element

(operator overloading)

Functional-stylemap / filter / reduce

with closures

Page 111: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Maps

!44

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Page 112: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Maps

!44

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Page 113: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Maps

!44

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Indexed access

Page 114: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Maps

!44

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Indexed accessPropertynotation access

Page 115: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Regular expressions

!45

def  pattern  =  ~/.*foo.*/  !assert  "Alibaba"  ==~  /.*(ba){2}/  !def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !'75001  Paris'.find(/(\d{5})\s(\w)+/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

Page 116: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Regular expressions

!45

def  pattern  =  ~/.*foo.*/  !assert  "Alibaba"  ==~  /.*(ba){2}/  !def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !'75001  Paris'.find(/(\d{5})\s(\w)+/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

Pattern

Page 117: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Regular expressions

!45

def  pattern  =  ~/.*foo.*/  !assert  "Alibaba"  ==~  /.*(ba){2}/  !def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !'75001  Paris'.find(/(\d{5})\s(\w)+/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Page 118: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Regular expressions

!45

def  pattern  =  ~/.*foo.*/  !assert  "Alibaba"  ==~  /.*(ba){2}/  !def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !'75001  Paris'.find(/(\d{5})\s(\w)+/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Find

Page 119: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Regular expressions

!45

def  pattern  =  ~/.*foo.*/  !assert  "Alibaba"  ==~  /.*(ba){2}/  !def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !'75001  Paris'.find(/(\d{5})\s(\w)+/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Find

Nice way to decompose the matched regions

Page 120: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Ranges

!46

def  range  =  'a'..'z'  !assert  range.contains('m')  assert  range.contains('z')  !def  exclusive  =  1..<10  !assert  !exclusive.contains(10)  !def  reverse  =  10..0  !assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Page 121: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Ranges

!46

def  range  =  'a'..'z'  !assert  range.contains('m')  assert  range.contains('z')  !def  exclusive  =  1..<10  !assert  !exclusive.contains(10)  !def  reverse  =  10..0  !assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Page 122: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Ranges

!46

def  range  =  'a'..'z'  !assert  range.contains('m')  assert  range.contains('z')  !def  exclusive  =  1..<10  !assert  !exclusive.contains(10)  !def  reverse  =  10..0  !assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Page 123: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Ranges

!46

def  range  =  'a'..'z'  !assert  range.contains('m')  assert  range.contains('z')  !def  exclusive  =  1..<10  !assert  !exclusive.contains(10)  !def  reverse  =  10..0  !assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Reverse range

Page 124: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Ranges

!46

def  range  =  'a'..'z'  !assert  range.contains('m')  assert  range.contains('z')  !def  exclusive  =  1..<10  !assert  !exclusive.contains(10)  !def  reverse  =  10..0  !assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Reverse range

Negative index countfrom the end

Page 125: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Strings, GStrings, multiline strings

!47

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !assert  tmpl.toString().contains('Groovy')

Page 126: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Strings, GStrings, multiline strings

!47

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !assert  tmpl.toString().contains('Groovy')

Plain java.lang.String

Page 127: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Strings, GStrings, multiline strings

!47

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !assert  tmpl.toString().contains('Groovy')

Plain java.lang.String

Multiline string withexpression interpolation

Page 128: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!48

System.out.println(  2.0  -­‐  1.1  );

Page 129: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!48

System.out.println(  2.0  -­‐  1.1  );

0.8999999999999999

Page 130: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!48

System.out.println(  2.0  -­‐  1.1  );

0.8999999999999999

Page 131: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!49

System.out.println(  3  /  2  );

Page 132: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!49

System.out.println(  3  /  2  );

1

Page 133: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Surprising numbers...

!49

System.out.println(  3  /  2  );

1

Page 134: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

BigDecimal by default!

!50

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

Page 135: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

BigDecimal by default!

!50

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

One of the reasons why micro-benchmarks sometimes showed

Groovy to be slow...

Page 136: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

BigDecimal by default!

!50

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

One of the reasons why micro-benchmarks sometimes showed

Groovy to be slow...

But you can use doubles & floatsfor performance, with ‘d’ or ‘f ’suffixes or with explicit type

Page 137: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 138: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Powerfulswitch / case

on steroids

Page 139: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Powerfulswitch / case

on steroids

switch(obj)  {          case  123:                  "number  123";              break          case  "abc":              "string  abc";              break          case  String:            "is  a  string";            break          case  [1,  2,  3]:      "in  list";                    break          case  ~/.*o+.*/:      "regex  match";            break          case  {  it  <  3  }:    "closure  criteria";  break          default:                    "unknown"  }

Page 140: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments

!52

move  obj,  x:  3,  y:  4

Page 141: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments

!52

move  obj,  x:  3,  y:  4

Normal argument

Page 142: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments

!52

move  obj,  x:  3,  y:  4

Normal argument Named argument

Page 143: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments

!52

move  obj,  x:  3,  y:  4

Normal argument Named argument

Calls:move(Map m, Object)

Page 144: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Command chains

• Ability to chain method calls without parentheses and dots

!53

move  forward  at  3.km/h

Page 145: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Command chains

• Ability to chain method calls without parentheses and dots

!53

move  forward  at  3.km/h

Actually equivalent to:move(forward).at(3.getKm().div(h))

Page 146: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments & command chains

!54

check  that:  vodka  tastes  good

Page 147: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Named arguments & command chains

!54

check  that:  vodka  tastes  good

Will call:check(that: vodka).tastes(good)

Page 148: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment & destructuring

!55

def  (a,  b)  =  ['A',  'B']  !(a,  b)  =  [b,  a]  !def  (int  i,  int  j)  =  [1,  2]  !def  geocode(String  place)  {          return  [45.4,  2.3]  }  !def  (la,  lo)  =  geocode("Paris")  !assert  la  ==  45.4  &&  lo  ==  2.3

Page 149: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment & destructuring

!55

def  (a,  b)  =  ['A',  'B']  !(a,  b)  =  [b,  a]  !def  (int  i,  int  j)  =  [1,  2]  !def  geocode(String  place)  {          return  [45.4,  2.3]  }  !def  (la,  lo)  =  geocode("Paris")  !assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »

Page 150: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment & destructuring

!55

def  (a,  b)  =  ['A',  'B']  !(a,  b)  =  [b,  a]  !def  (int  i,  int  j)  =  [1,  2]  !def  geocode(String  place)  {          return  [45.4,  2.3]  }  !def  (la,  lo)  =  geocode("Paris")  !assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Page 151: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment & destructuring

!55

def  (a,  b)  =  ['A',  'B']  !(a,  b)  =  [b,  a]  !def  (int  i,  int  j)  =  [1,  2]  !def  geocode(String  place)  {          return  [45.4,  2.3]  }  !def  (la,  lo)  =  geocode("Paris")  !assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Methodreturning a list

Page 152: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment & destructuring

!55

def  (a,  b)  =  ['A',  'B']  !(a,  b)  =  [b,  a]  !def  (int  i,  int  j)  =  [1,  2]  !def  geocode(String  place)  {          return  [45.4,  2.3]  }  !def  (la,  lo)  =  geocode("Paris")  !assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Methodreturning a list

Destructuring

Page 153: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment and destructuring

!56

class  Point  {          double  x,  y  !        double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !assert  x  ==  48.3  &&  y  ==  3.5

Page 154: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment and destructuring

!56

class  Point  {          double  x,  y  !        double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !assert  x  ==  48.3  &&  y  ==  3.5

Method signatureconvention: getAt(int)

Page 155: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Multiple assignment and destructuring

!56

class  Point  {          double  x,  y  !        double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !assert  x  ==  48.3  &&  y  ==  3.5

Method signatureconvention: getAt(int)

Transparent destructuring

Page 156: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Builders — JSON builder

!57

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Page 157: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Builders — JSON builder

!57

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Page 158: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Builders — JSON builder

!57

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Closure blocksdelimiting the

structure

Page 159: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Builders — JSON builder

!57

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Closure blocksdelimiting the

structure

{"person": {

"name": "Guillaume","age": 36,"daughters": [

"Marion","Erine"

],"address": {

"street": "1 Main Street","zip": 75001,"city": "Paris"

}}

}

Page 160: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GPath expressions

• GPath expressions are like XPath but for an object graph

!58

import  groovy.json.*  !def  url  =      "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

Page 161: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GPath expressions

• GPath expressions are like XPath but for an object graph

!58

import  groovy.json.*  !def  url  =      "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression

Page 162: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GPath expressions

• GPath expressions are like XPath but for an object graph

!58

import  groovy.json.*  !def  url  =      "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression Add find / findAllinto the mix

Page 163: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GPath expressions

• GPath expressions are like XPath but for an object graph

!58

import  groovy.json.*  !def  url  =      "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression Add find / findAllinto the mix

No (un)marshalling!

Page 164: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Power asserts

!59

def  (a,  b,  c)  =  [20,  30,  40]  !assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Page 165: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Power asserts

!59

def  (a,  b,  c)  =  [20,  30,  40]  !assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Assertion  failed:    !assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1                |  |    |  |        |        |        |  |  |      |                |  580|  29      58      false|  |  60    61                20      30                              |  40                                                            120  !   at  script1.run(script1.groovy:3)

Page 166: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Power asserts

!59

def  (a,  b,  c)  =  [20,  30,  40]  !assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Assertion  failed:    !assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1                |  |    |  |        |        |        |  |  |      |                |  580|  29      58      false|  |  60    61                20      30                              |  40                                                            120  !   at  script1.run(script1.groovy:3)

Invented by the Spock testing framework

Page 167: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

Page 168: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

With Java, you only get an NPE. No idea where it came from!

Page 169: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

With Java, you only get an NPE. No idea where it came from!

Groovy will say: Cannot get property ‘name’ on null object

Page 170: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

Page 171: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

o?.line?.item?.name

Page 172: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Null handling

!60

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !println  o.line.item.name

o?.line?.item?.name

Safe navigation:will just return

null; No NPE

Page 173: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 174: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Truth,the Groovy Truth!

Page 175: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Truth,the Groovy Truth!

And what if I couldcustomize the truth?

Page 176: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Groovy Truth

!62

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

Page 177: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Groovy Truth

!62

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

null, empty, 0-sized, zeroare coerced to false

Page 178: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Groovy Truth

!62

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

null, empty, 0-sized, zeroare coerced to false

true otherwise

Page 179: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Customizing the truth!

!63

class  Account  {          String  name          boolean  disabled  =  false  !        boolean  asBoolean()  {  !disabled  }  }  !assert    new  Account(name:  'current')  assert  !new  Account(name:  'old',  disabled:  true)

Page 180: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Customizing the truth!

!63

class  Account  {          String  name          boolean  disabled  =  false  !        boolean  asBoolean()  {  !disabled  }  }  !assert    new  Account(name:  'current')  assert  !new  Account(name:  'old',  disabled:  true)

while (account), if (account), etc…

Page 181: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

?:

Page 182: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

The Elvisoperator!

?:

Page 183: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

Page 184: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

Page 185: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

Page 186: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  y

Page 187: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  y

Page 188: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  y

Page 189: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  y

Page 190: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y

Page 191: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y Null, empty, zero-

sized... false,otherwise true!

Page 192: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y Null, empty, zero-

sized... false,otherwise true!

Good old ternaryoperator

Page 193: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Towards Elvis...

!65

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y Null, empty, zero-

sized... false,otherwise true!

Good old ternaryoperatorElvis!

Page 194: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

AST transformations

• Abstract Syntax Tree – in memory representation of your program

before being compiled into bytecode !

• AST transformation == process of transforming the AST of a program before it’s compiled !

• Macro-like compiler hook!

!66

Page 195: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lots of AST transformations...

• Code generation

– @ToString, @EqualsAndHashCode, @Canonical, @TupleConstructor, @InheritConstructors, @Category, @IndexedProperty, @Lazy, @Newify

• Class design

– @Delegate, @Immutable, @Memoized, @Singleton, @Mixin

• Logging

– @Log, @Log4j, @Log4j2, @Slf4j!67

Page 196: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lots of AST transformations...

• Safer scripting

– @ConditionalInterrupt, @ThreadInterrupt, @TimedInterupt

• Compiler directives

– @Field, @PackageScope, @AnnotationCollector, @DelegatesTo, @TypeChecked, @CompileStatic, @CompileDynamic

• Swing patterns

– @Bindable, @ListenerList, @Vetoable

!68

Page 197: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Lots of AST transformations...

• Dependencies handling

– @Grab, @GrabConfig, @GrabExclude, @GrabResolver

• Test assistance

– @NotYetImplemented, @ASTTest

!69

Page 198: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Immutability

• Implement immutability by the book !

– final class – tuple-style constructor – private final backing fields – defensive copying of collections – equals() and hashCode() methods – toString() method – ...

!70

Page 199: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Immutability

• Implement immutability by the book !

– final class – tuple-style constructor – private final backing fields – defensive copying of collections – equals() and hashCode() methods – toString() method – ...

!70

Can be error-prone towrite immutableclasses oneself !

Page 200: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Immutability

• A Person class with – a String name – an int age

!71

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Page 201: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Immutability

• A Person class with – a String name – an int age

!71

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Damnverbose

Java!

Page 202: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Immutability

• A Person class with – a String name – an int age

!71

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Damnverbose

Java!

Although it’s also a validGroovy program!

Page 203: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@Immutable

!72

import  groovy.transform.*  !

@Immutable  class  Person  {          String  name          int  age  }

Page 204: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Memoization

• Cache the result of previous invocations of closures or methods with the same set of argument values

!73

import  groovy.transform.*  !@Memoized  long  fib(long  n)  {          if  (n  ==  0)  0          else  if  (n  ==  1)  1          else  fib(n  -­‐  1)  +  fib(n  -­‐  2)  }  !println  fib(40)

Page 205: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Memoization

• Cache the result of previous invocations of closures or methods with the same set of argument values

!73

import  groovy.transform.*  !@Memoized  long  fib(long  n)  {          if  (n  ==  0)  0          else  if  (n  ==  1)  1          else  fib(n  -­‐  1)  +  fib(n  -­‐  2)  }  !println  fib(40)

Best applied toside-effect free

functions

Page 206: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 207: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy allows youto be lazy

Page 208: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy allows youto be lazy

The compiler will dothe job for you

Page 209: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy allows youto be lazy

The compiler will dothe job for you

More concise, morereadable code

Page 210: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy allows youto be lazy

The compiler will dothe job for you

More concise, morereadable code

Less stuff to maintainand worry about

Page 211: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments

!

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!75

Page 212: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments

!

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!75

You can even extend thestatic type checker!

Page 213: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments

!

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!75

You can even extend thestatic type checker!

Type check DSLs ordynamic features!

Page 214: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@TypeChecked & @CompileStatic

!

• What is type checked can also be compiled statically with @CompileStatic

!

– generate the same bytecode as javac !

– same performance as Java

!76

Page 215: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Static compilation performance

!77

Fibonacci Pi (π) quadrature

Binarytrees

Java 191 ms 97 ms 3.6 s

Staticcompilation 197 ms 101 ms 4.3 s

Primitive optimizations 360 ms 111 ms 23.7 s

No prim.optimizations 2590 ms 3220 ms 50.0 s1.7

1.8

2.x

Page 216: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Superb community!

Part 3

Page 217: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

A blossoming Ecosystem

Page 218: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 219: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 220: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 221: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 222: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GVM

Page 223: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 224: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GVM

Page 225: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GVMGROOVY ENVIRONMENT MANAGER

Page 226: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

GVM: Groovy enVironment Manager

• The new kid on the block – http://gvmtool.net/ — @gvmtool

!

• Manage parallel versions of the various ecosystem projects !

• Supports... – Groovy, Grails, Griffon, Gradle, Vert.x, Spring Boot

!

• On Linux, MacOS, Cygwin, Solaris, FreeBSD!86

Page 227: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 228: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

I’m Spock...

Page 229: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

I’m Spock...

...the Spock testingframework

Page 230: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

I’m Spock...

...the Spock testingframework

Page 231: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

Page 232: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

@Grab a dependency

Page 233: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

@Grab a dependency

Meaningful testmethod names

Page 234: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

@Grab a dependency

Meaningful testmethod names

Clever use of labelsfor BDD style

Page 235: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

@Grab a dependency

Meaningful testmethod names

Clever use of labelsfor BDD style

Expression tobe asserted

Page 236: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Spock example

!88

@Grab('org.spockframework:spock-­‐core:0.7-­‐groovy-­‐2.0')  import  spock.lang.*  !class  MathSpec  extends  Specification  {          def  "maximum  of  two  numbers"()  {              expect:                  Math.max(a,  b)  ==  c  !            where:                  a  |  b  ||  c                  1  |  3  ||  3                  7  |  4  ||  4                  0  |  0  ||  0          }  }

@Grab a dependency

Meaningful testmethod names

Clever use of labelsfor BDD style

Expression tobe assertedCute data-

driven tests!

Page 237: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)
Page 238: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@GrabResolver("https://oss.jfrog.org/artifactory/repo")  @Grab("org.ratpack-­‐framework:ratpack-­‐groovy:0.9.0-­‐SNAPSHOT")  import  static  org.ratpackframework.groovy.RatpackScript.ratpack  import  static  org.ratpackframework.groovy.Template.groovyTemplate  !ratpack  {          handlers  {                  get  {                          response.send  "Welcome!"                  }  !                get("date")  {                          render  groovyTemplate("date.html")                  }  !                assets  "public"          }  }

Page 239: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

@GrabResolver("https://oss.jfrog.org/artifactory/repo")  @Grab("org.ratpack-­‐framework:ratpack-­‐groovy:0.9.0-­‐SNAPSHOT")  import  static  org.ratpackframework.groovy.RatpackScript.ratpack  import  static  org.ratpackframework.groovy.Template.groovyTemplate  !ratpack  {          handlers  {                  get  {                          response.send  "Welcome!"                  }  !                get("date")  {                          render  groovyTemplate("date.html")                  }  !                assets  "public"          }  }

Lightweight Netty-basedweb app toolkit

Page 240: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb

• Browser automation solution !

• WebDriver + jQuery selectors + Groovy !

• Handy for – scripting, scraping, automation... – functional / web / acceptance testing

• when integrated with JUnit, TestNG or Spock

!90

Page 241: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Page 242: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Drive the browserto this site

Page 243: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Drive the browserto this site

Check the contentof the title

Page 244: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Drive the browserto this site

Check the contentof the title

Find & fill inthe form

Page 245: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Drive the browserto this site

Check the contentof the title

Find & fill inthe form

Submit theform

Page 246: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — Example

!91

import  geb.Browser  !Browser.drive  {          go  "http://myapp.com/login"  !        assert  $("h1").text()  ==  "Please  Login"  !        $("form.login").with  {                  username  =  "admin"                  password  =  "password"                  login().click()          }  !        assert  $("h1").text()  ==                  "Admin  Section"  }  

Drive the browserto this site

Check the contentof the title

Find & fill inthe form

Submit theform

In the admin section, yeah!

Page 247: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — With page objects and Spock

!92

import  geb.spock.GebSpec  !class  GoogleWikipediaSpec  extends  GebSpec  {  !        def  "first  result  for  wikipedia  search  should  be  wikipedia"()  {                  given:                  to  GoogleHomePage  !                expect:                  at  GoogleHomePage  !                when:                  search.field.value("wikipedia")  !                then:                  waitFor  {  at  GoogleResultsPage  }  !                and:                  firstResultLink.text()  ==  "Wikipedia"  !                when:                  firstResultLink.click()  !                then:                  waitFor  {  at  WikipediaPage  }          }  }

Page 248: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — With page objects and Spock

!92

import  geb.spock.GebSpec  !class  GoogleWikipediaSpec  extends  GebSpec  {  !        def  "first  result  for  wikipedia  search  should  be  wikipedia"()  {                  given:                  to  GoogleHomePage  !                expect:                  at  GoogleHomePage  !                when:                  search.field.value("wikipedia")  !                then:                  waitFor  {  at  GoogleResultsPage  }  !                and:                  firstResultLink.text()  ==  "Wikipedia"  !                when:                  firstResultLink.click()  !                then:                  waitFor  {  at  WikipediaPage  }          }  }

With page objects

Page 249: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — With page objects and Spock

!92

import  geb.spock.GebSpec  !class  GoogleWikipediaSpec  extends  GebSpec  {  !        def  "first  result  for  wikipedia  search  should  be  wikipedia"()  {                  given:                  to  GoogleHomePage  !                expect:                  at  GoogleHomePage  !                when:                  search.field.value("wikipedia")  !                then:                  waitFor  {  at  GoogleResultsPage  }  !                and:                  firstResultLink.text()  ==  "Wikipedia"  !                when:                  firstResultLink.click()  !                then:                  waitFor  {  at  WikipediaPage  }          }  }

With page objects

BDD style: given/when/then

Page 250: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Geb — With page objects and Spock

!92

import  geb.spock.GebSpec  !class  GoogleWikipediaSpec  extends  GebSpec  {  !        def  "first  result  for  wikipedia  search  should  be  wikipedia"()  {                  given:                  to  GoogleHomePage  !                expect:                  at  GoogleHomePage  !                when:                  search.field.value("wikipedia")  !                then:                  waitFor  {  at  GoogleResultsPage  }  !                and:                  firstResultLink.text()  ==  "Wikipedia"  !                when:                  firstResultLink.click()  !                then:                  waitFor  {  at  WikipediaPage  }          }  }

With page objects

BDD style: given/when/then

Wait for slow loading pages

Page 251: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Summary

Part 4

Page 252: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Java’s best friend

• Java derived syntax –Flat learning curve –Easy to learn

• But goes beyond Java –Concise, expressive, readable –Fit for Domain-Specific Languages

• Seamless & transparent Java integration –Mix & match Groovy & Java classes (joint compil.) –No language barrier to cross

!94

Page 253: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy’s nature

!

• Object oriented dynamic language... !

• But... – as type safe as you want it — static type checking – as fast as you need it — static compilation – as functional as you make it — closures...

!95

Page 254: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Groovy use cases

• Scripting tasks, build automation

• Extension points for customizing/configuring apps

• Business languages & Domain-Specific Languages

• Full blown apps

– for desktop with Griffon – for the web with Grails, Ratpack, Gaelyk – for web reactive programming with Reactor

!96

Page 255: What makes Groovy Groovy  - Guillaume Laforge (Pivotal)

Thanks! Q & A

Part 5