Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Groovy in 2014 and beyond at Devoxx France

Groovy in 2014 and beyond at Devoxx France

New presentation on all the new features of Groovy 2.3

Guillaume Laforge

April 18, 2014
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Weekly newsletter • Every Tuesday ! • http://bit.ly/groovy-weekly- subscribe
  2. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Google+ page ! • https://plus.google.com/ +groovy
  3. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Google+ community ! • https://plus.google.com/ communities/ 105160926044623621768
  4. @glaforge #dvxgroovy 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
  5. @glaforge #dvxgroovy Groovy 3.0 ! • New Meta-Object Protocol !

    • Invoke-dynamic based runtime ! • Rewritten language grammar with Antlr v4
  6. @glaforge #dvxgroovy 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 & compilation • class methods coming from traits are also visible from Java • Also possible to implement traits at runtime
  7. @glaforge #dvxgroovy 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
  8. @glaforge #dvxgroovy 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 « trait », a new keyword for a new concept
  9. @glaforge #dvxgroovy 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 a class 
 « implements »
 a trait
  10. @glaforge #dvxgroovy 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 the fly() method from the trait is available
  11. @glaforge #dvxgroovy 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
  12. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  13. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful a Groovy property
  14. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful implement the trait
  15. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful Groovy named argument constructor
  16. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful access the property
  17. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  18. @glaforge #dvxgroovy 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
  19. @glaforge #dvxgroovy 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 extend the Named trait
  20. @glaforge #dvxgroovy 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 access the name property
  21. @glaforge #dvxgroovy 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 implement the composite trait
  22. @glaforge #dvxgroovy 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
  23. @glaforge #dvxgroovy 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 (& dynamism)
  24. @glaforge #dvxgroovy 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 (& dynamism) access a dynamic property
  25. @glaforge #dvxgroovy 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 (& dynamism) implements two traits!
  26. @glaforge #dvxgroovy 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 (& dynamism) dynamic ‘name’ property interpolated
  27. @glaforge #dvxgroovy 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 (& dynamism)
  28. @glaforge #dvxgroovy 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?
  29. @glaforge #dvxgroovy 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? two surf() methods
  30. @glaforge #dvxgroovy 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?
  31. @glaforge #dvxgroovy 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? extending a class and implementing the two traits
  32. @glaforge #dvxgroovy 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?
  33. @glaforge #dvxgroovy 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? last declared trait wins!
  34. @glaforge #dvxgroovy 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?
  35. @glaforge #dvxgroovy 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?
  36. @glaforge #dvxgroovy 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? reverse the order!
  37. @glaforge #dvxgroovy 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?
  38. @glaforge #dvxgroovy 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?
  39. @glaforge #dvxgroovy 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? Be explicit! Override surf() 
 & use ‘super’
  40. @glaforge #dvxgroovy 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? Your class method takes precedence over the traits
  41. @glaforge #dvxgroovy 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?
  42. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override
  43. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override ‘this’ is the ‘this’ of the class implementing the trait
  44. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override The default Object#toString() method always prevails, 
 in spite of the trait’s toString()
  45. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override
  46. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override
  47. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override Use @ForceOverride to force the compiler to use the trait’s method
  48. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override If Foo had implemented toString(), Foo’s toString() would always win
  49. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override
  50. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation
  51. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation Somewhat artificial to have to create an intermediary class to get named animals
  52. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation
  53. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  54. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation Runtime trait, 
 with Groovy’s usual coercion mechanism
  55. @glaforge #dvxgroovy trait  Named  {          String

     name   }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  56. @glaforge #dvxgroovy 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
  57. @glaforge #dvxgroovy 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 Implement several traits at once, at runtime
  58. @glaforge #dvxgroovy 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
  59. @glaforge #dvxgroovy 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
  60. @glaforge #dvxgroovy New: @TailRecursive 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
  61. @glaforge #dvxgroovy New: @TailRecursive 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
  62. @glaforge #dvxgroovy New: @TailRecursive 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
  63. @glaforge #dvxgroovy New: @TailRecursive 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
  64. @glaforge #dvxgroovy New: @TailRecursive 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
  65. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   }
  66. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   } Makes the class Comparable by multiple Comparators
  67. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   } First compare by lastName, then by firstName, etc.
  68. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   } You can also specify ‘includes’ / ‘excludes’ properties
  69. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   }
  70. @glaforge #dvxgroovy @BaseScript improvements abstract  class  CustomBase  extends  Script  {

             int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  71. @glaforge #dvxgroovy @BaseScript improvements 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
  72. @glaforge #dvxgroovy @BaseScript improvements 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
  73. @glaforge #dvxgroovy @BaseScript improvements abstract  class  CustomBase  extends  Script  {

             int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42 In 2.3, ability to put the annotation on imports & package
  74. @glaforge #dvxgroovy @BaseScript improvements abstract  class  CustomBase  extends  Script  {

             int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  75. @glaforge #dvxgroovy @BaseScript custom abstract method abstract  class  CustomBase  extends

     Script  {          def  run()  {                  before()                  internalRun()                  after()          }   !        abstract  internalRun()   !        def  before()  {  println  'before'  }          def  after()    {  println  'after'    }   }
  76. @glaforge #dvxgroovy @BaseScript custom abstract method 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'
  77. @glaforge #dvxgroovy @BaseScript custom abstract method 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
  78. @glaforge #dvxgroovy @BaseScript custom abstract method 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'
  79. @glaforge #dvxgroovy JDK 7+ NIO2 module • All the familiar

    methods on File retrofitted on Path as well path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  80. @glaforge #dvxgroovy JDK 7+ NIO2 module • All the familiar

    methods on File retrofitted on Path as well 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 methods
  81. @glaforge #dvxgroovy JDK 7+ NIO2 module • All the familiar

    methods on File retrofitted on Path as well path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  82. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  83. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  84. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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 Benchmark gives 3x to 4x performance factor 
 over Jackson and GSON
  85. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  86. @glaforge #dvxgroovy New modes for parsing • Original JsonSlurper renamed

    to JsonSlurperClassic • Additional parsing modes: • INDEX_OVERLAY: super fast for <2MB payloads • using a « parsing overlay » technique • CHARACTER_SOURCE: for >2MB payloads • implemented with sliding windows over readers • LAX: beyond the JSON spec, nice for configuration files • support single quotes, / and # comments • CHAR_BUFFER: general purpose
  87. @glaforge #dvxgroovy JsonSlurper for configuration files 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
  88. @glaforge #dvxgroovy JsonSlurper for configuration files 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
  89. @glaforge #dvxgroovy JsonSlurper for configuration files 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
  90. @glaforge #dvxgroovy 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
  91. @glaforge #dvxgroovy Markup template engine — the idea cars  {

           cars.each  {                car(make:  it.make,  name:  it.name)        }   }
  92. @glaforge #dvxgroovy Markup template engine — the idea cars  {

           cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  93. @glaforge #dvxgroovy Markup template engine — the idea cars  {

           cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]]
  94. @glaforge #dvxgroovy Markup template engine — the idea 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
  95. @glaforge #dvxgroovy Markup template engine — the idea 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>
  96. @glaforge #dvxgroovy Markup template engine — the idea 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
  97. @glaforge #dvxgroovy Markup template engine — the idea 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>
  98. @glaforge #dvxgroovy Markup template engine — in action 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)
  99. @glaforge #dvxgroovy Markup template engine — includes //  include  another

     template   include  template:  'foo.tpl'           //  include  raw  content   include  unescaped:  'raw.txt'   ! //  escape  &  include   include  escaped:  'to_escape.txt'
  100. @glaforge #dvxgroovy Markup template engine — useful methods //  escaped

     automatically   yield  'some  raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                
  101. @glaforge #dvxgroovy Markup template engine — useful methods //  escaped

     automatically   yield  'some  raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                 //  <!-­‐-­‐comment-­‐-­‐>   comment  'comment'                 ! //  adds  new  lines   newLine()                                 ! //  processing  instructions   pi(/*  ...  */)                      
  102. @glaforge #dvxgroovy Markup template engine — configuration • Configuration options

    ! • declaration encoding ! • expand empty elements ! • use double quotes ! • newline string ! ! ! ! • auto escape ! • auto indent ! • base template class ! • locale
  103. @glaforge #dvxgroovy Markup template engine — static! • Type-checked templates

    available • use createTypeCheckedModelTemplate() 
 instead of createTemplate() • Advantages • get compilation errors • if a variable is not available • if you make mistakes in the code snippets • even faster templates
  104. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template
  105. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes)
  106. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  107. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template 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
  108. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  109. @glaforge #dvxgroovy Goals for the new Meta-Object Protocol • Fully

    leverage and 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?
  110. @glaforge #dvxgroovy Antlr v4 grammar • Problems • Groovy still

    uses Antlr v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • 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!
  111. @glaforge #dvxgroovy Antlr v4 grammar • Problems • Groovy still

    uses Antlr v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • 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! A « Groovy Summer of Code » student to help
  112. @glaforge #dvxgroovy Java 8 support • Additional grammar and 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
  113. @glaforge #dvxgroovy Java 8 support • Additional grammar and 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 Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
  114. @glaforge #dvxgroovy Crédit image / Creative Commons • Rue pavée

    — By-Nc-Sa • http://www.flickr.com/photos/22914687@N05/4957591422/sizes/l/ • Sous la Tour Eiffel — By-Nc-Sa • http://www.flickr.com/photos/stewiedewie/244850735/sizes/l/in/photostream/ • Sous le pont — By-Nc-Nd • http://www.landscape-photo.net/displayimage.php?pid=5194 • Paris Metro - By-Nc-Sa • http://www.flickr.com/photos/22914687@N05/6317047263/sizes/l/ ! • Slide template created by @glaforge, completed by @nmartignole for Devoxx FR2014