Groovy in 2014 and beyond at SpringOne2GX 2014

Groovy in 2014 and beyond at SpringOne2GX 2014

Latest updates on Groovy 2.3 and beyond.

137d3908243acfc30e126615d59d4e6d?s=128

Guillaume Laforge

September 09, 2014
Tweet

Transcript

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

    without permission. Groovy, in 2014 and beyond Guillaume Laforge — Groovy project lead / Pivotal @glaforge
  2. Stay up-to-date Groovy Weekly Newsletter (Every Tuesday) http://beta.groovy-lang.org/groovy-weekly.html 2

  3. Stay up-to-date Google+ Groovy Page https://google.com/+groovy 3

  4. Stay up-to-date Google+ Groovy Community http://bit.ly/g-community 4

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

    without permission. Agenda
  6. The Groovy roadmap 6 2015 2014 2013 Groovy 2.3 Groovy

    2.4 Groovy 2.2 Groovy 2.5 ? Groovy 3.0 ?
  7. Groovy 2.3 • JDK 8 runtime support • Traits •

    New and updates AST transformations • NIO2 module • JSON improvements & performance gains • New Markup template engine • Documentation overhaul 7
  8. Groovy 2.4 • Android support ! • New website !

    • Potentially • Macro system? • New grammar? 8
  9. Groovy 3.0 • New Meta-Object Protocol ! • Invoke-dynamic based

    runtime ! • Rewritten language grammar with Antlr v4 • unless re-scheduled for Groovy 2.4 • successful GSoC, but not fully complete coverage 9
  10. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

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

    without permission. JDK 8 support
  12. JDK 8 support — closures vs lambdas 12 IntStream.range(1,  100).forEach(s

     -­‐>                                                System.out.println(s));   ! Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it));
  13. JDK 8 support — closures vs lambdas 12 IntStream.range(1,  100).forEach(s

     -­‐>                                                System.out.println(s));   ! Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it)); IntStream.range(1,  100).forEach  {  println  it  }   ! Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  }
  14. JDK 8 support — closures vs lambdas 12 IntStream.range(1,  100).forEach(s

     -­‐>                                                System.out.println(s));   ! Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it)); IntStream.range(1,  100).forEach  {  println  it  }   ! Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  } Use Groovy closures wherever you pass lambdas in Java 8
  15. To know all about AST transformations! 13 Groovy in the

    light of Java 8 by Guillaume Laforge Tue 12:45pm / F. Park 1
  16. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Traits
  17. Traits • Like interfaces, but with method bodies • similar

    to Java 8 interface default methods • Elegant way to compose behavior • multiple inheritance without the « diamond » problem • Traits can also be stateful • traits can have properties like normal classes • Compatible with static typing and static compilation • class methods from traits also visible from Java classes • Also possible to implement traits at runtime 15
  18. Traits: a simple example 16 trait  FlyingAbility  {    

         String  fly()  {  "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!"
  19. Traits: a simple example 16 trait  FlyingAbility  {    

         String  fly()  {  "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" « trait », a new keyword for a new concept
  20. Traits: a simple example 16 trait  FlyingAbility  {    

         String  fly()  {  "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" a class 
 « implements »
 a trait
  21. Traits: a simple example 16 trait  FlyingAbility  {    

         String  fly()  {  "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" the fly() method from the trait is available
  22. Traits: a simple example 16 trait  FlyingAbility  {    

         String  fly()  {  "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!"
  23. Traits: stateful 17 trait  Named  {        

     String  name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'
  24. Traits: stateful 17 trait  Named  {        

     String  name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' a Groovy property
  25. Traits: stateful 17 trait  Named  {        

     String  name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' implement the trait
  26. Traits: stateful 17 trait  Named  {        

     String  name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Groovy named argument constructor
  27. Traits: stateful 17 trait  Named  {        

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

     String  name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'
  29. Traits: inheritance 18 trait  Named  {  String  name  }  

    ! trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  30. Traits: inheritance 18 trait  Named  {  String  name  }  

    ! trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" extend the Named trait
  31. Traits: inheritance 18 trait  Named  {  String  name  }  

    ! trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" access the name property
  32. Traits: inheritance 18 trait  Named  {  String  name  }  

    ! trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" implement the composite trait
  33. Traits: inheritance 18 trait  Named  {  String  name  }  

    ! trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  34. Traits: multiple inheritance & dynamic access 19 trait  FlyingAbility  {

             String  fly()  {  "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility   {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  35. Traits: multiple inheritance & dynamic access 19 trait  FlyingAbility  {

             String  fly()  {  "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility   {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" access a dynamic property
  36. Traits: multiple inheritance & dynamic access 19 trait  FlyingAbility  {

             String  fly()  {  "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility   {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" implements two traits!
  37. Traits: multiple inheritance & dynamic access 19 trait  FlyingAbility  {

             String  fly()  {  "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility   {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" dynamic ‘name’ property interpolated
  38. Traits: multiple inheritance & dynamic access 19 trait  FlyingAbility  {

             String  fly()  {  "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility   {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  39. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web'
  40. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web' two surf() methods
  41. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web'
  42. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web' extending a class and implementing the two traits
  43. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web'
  44. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web' last declared trait wins!
  45. Traits: what about conflicts? 20 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  KiteSurfer,  WebSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'web'
  46. Traits: what about conflicts? 21 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite'
  47. Traits: what about conflicts? 21 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite' reverse the order!
  48. Traits: what about conflicts? 21 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite'
  49. Traits: what about conflicts? 22 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }   }   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite'
  50. Traits: what about conflicts? 22 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }   }   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite' Be explicit! Override surf() 
 & use ‘super’
  51. Traits: what about conflicts? 22 trait  KiteSurfer  {  String  surf()

     {  'kite'  }  }   ! trait  WebSurfer    {  String  surf()  {    'web'  }  }   ! class  Person  {  String  name  }   ! class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {          String  surf()  {  KiteSurfer.super.surf()  }   }   ! def  h  =  new  Hipster()   assert  h.surf()  ==  'kite' Your class method takes precedence over the traits
  52. Traits: what about conflicts? 22 trait  KiteSurfer  {  String  surf()

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

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation 23
  54. trait  Named  {          String  name  

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

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation 23
  56. trait  Named  {          String  name  

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation 24
  57. trait  Named  {          String  name  

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

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation 24
  59. Traits: runtime implementation 25 trait  Named  {  String  name  }

      ! trait  Quacks  {          String  quack()  {  'Quack!'  }   }   ! class  Animal  {}   ! def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!'
  60. Traits: runtime implementation 25 trait  Named  {  String  name  }

      ! trait  Quacks  {          String  quack()  {  'Quack!'  }   }   ! class  Animal  {}   ! def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!' Implement several traits at once, at runtime
  61. Traits: runtime implementation 25 trait  Named  {  String  name  }

      ! trait  Quacks  {          String  quack()  {  'Quack!'  }   }   ! class  Animal  {}   ! def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!'
  62. Traits: miscellaneous • Traits can… ! • have private fields

    and methods • have abstract methods • implement interfaces • extend other traits or implement several traits • be statically type checked and compiled 26
  63. To know all about traits! 27 Rethinking API 
 design

    with traits by Cédric Champeau Tue 2:30pm / Trinity 3
  64. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. AST transforms
  65. New: @TailRecursive 29 import  groovy.transform.TailRecursive   ! @TailRecursive   def

     fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   ! assert  fact(1000)  >  10e2566
  66. New: @TailRecursive 29 import  groovy.transform.TailRecursive   ! @TailRecursive   def

     fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   ! assert  fact(1000)  >  10e2566 Rewrites tail recursive friendly function serially
  67. New: @TailRecursive 29 import  groovy.transform.TailRecursive   ! @TailRecursive   def

     fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   ! assert  fact(1000)  >  10e2566 Doesn’t blow up with a stack overflow error
  68. New: @TailRecursive 29 import  groovy.transform.TailRecursive   ! @TailRecursive   def

     fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   ! assert  fact(1000)  >  10e2566 Downside of tail recursion is 
 you might have to rewrite 
 your algo to be tailrec friendly
  69. New: @TailRecursive 29 import  groovy.transform.TailRecursive   ! @TailRecursive   def

     fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   ! assert  fact(1000)  >  10e2566
  70. New: @Sortable 30 import  groovy.transform.*   ! @Sortable   class

     Person  {          String  lastName          String  firstName          int  age   }
  71. New: @Sortable 30 import  groovy.transform.*   ! @Sortable   class

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

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

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

     Person  {          String  lastName          String  firstName          int  age   }
  75. @BaseScript improvements 31 abstract  class  CustomBase  extends  Script  {  

           int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  76. @BaseScript improvements 31 abstract  class  CustomBase  extends  Script  {  

           int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42 You can add your own base methods and properties to all compiled scripts
  77. @BaseScript improvements 31 abstract  class  CustomBase  extends  Script  {  

           int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42 Define the base script class for this script
  78. @BaseScript improvements 31 abstract  class  CustomBase  extends  Script  {  

           int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42 Ability to put the annotation on imports & package
  79. @BaseScript improvements 31 abstract  class  CustomBase  extends  Script  {  

           int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  80. @BaseScript custom abstract method 32 abstract  class  CustomBase  extends  Script

     {      def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   }
  81. @BaseScript custom abstract method 32 abstract  class  CustomBase  extends  Script

     {      def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   ! println  'Hello'
  82. @BaseScript custom abstract method 32 abstract  class  CustomBase  extends  Script

     {      def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   ! println  'Hello' You can define your own abstract method for script bodies
  83. @BaseScript custom abstract method 32 abstract  class  CustomBase  extends  Script

     {      def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   ! println  'Hello'
  84. To know all about AST transformations! 33 Groovy AST 


    transformations by Paul King Wed 2:30pm / Trinity 3
  85. To know all about AST transformations! 34 Writing AST 


    transformations by Simon / Sadogursky Thu 10:30pm / F. Park 3
  86. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. NIO2 module
  87. JDK 7+ NIO2 module • All the familiar methods on

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

    File 
 retrofitted on Path as well 36 path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   … Feature request to add all the java.nio.file.Files static utility methods as GDK
  89. JDK 7+ NIO2 module • All the familiar methods on

    File 
 retrofitted on Path as well 36 path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  90. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. JSON
  91. JSON parser / builder perf. increase • Re-implementation of JSON

    support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 38
  92. JSON parser / builder perf. increase • Re-implementation of JSON

    support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 38
  93. JSON parser / builder perf. increase • Re-implementation of JSON

    support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 38 Benchmark gives 3x to 4x performance factor 
 over Jackson and GSON
  94. JSON parser / builder perf. increase • Re-implementation of JSON

    support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned ! • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 38
  95. New modes for parsing • Original JsonSlurper renamed to JsonSlurperClassic

    ! • Additional parsing modes: • INDEX_OVERLAY: super fast for <2MB payloads o using a « parsing overlay » technique • CHARACTER_SOURCE: for >2MB payloads o implemented with sliding windows over readers • LAX: beyond the JSON spec, nice for configuration files o support single quotes, / and # comments • CHAR_BUFFER: general purpose 39
  96. JsonSlurper for configuration files 40 import  groovy.json.*   import  static

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

     groovy.json.JsonParserType.*   ! def  parser  =  new  JsonSlurper().setType(LAX)   ! def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }   '''   ! assert  conf.environment  ==  'production'   assert  conf.server  ==  5 More tolerant parser: 
 single quotes, 
 non-quoted keys, 
 // and # comments, missing comas
  98. JsonSlurper for configuration files 40 import  groovy.json.*   import  static

     groovy.json.JsonParserType.*   ! def  parser  =  new  JsonSlurper().setType(LAX)   ! def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }   '''   ! assert  conf.environment  ==  'production'   assert  conf.server  ==  5
  99. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Markup template engine </>
  100. Markup template engine • Based on the principles of Groovy’s

    « builders » • and particularly the MarkupBuilder class
 for generating arbitrary XML / HTML payloads ! • Compiled statically for fast template rendering ! • Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl ! • Custom base template class • ability to provide reusable methods across your templates 42
  101. Markup template engine • Based on the principles of Groovy’s

    « builders » • and particularly the MarkupBuilder class
 for generating arbitrary XML / HTML payloads ! • Compiled statically for fast template rendering ! • Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl ! • Custom base template class • ability to provide reusable methods across your templates 42 Spring Boot approved
  102. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   }
  103. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  104. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]]
  105. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]] Feed a model into your template
  106. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]] <cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>! </cars>
  107. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]] <cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>! </cars> Generate the XML output
  108. Markup template engine — the idea 43 cars  {  

         cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]] <cars>! <car make='Peugeot' name='508'/>! <car make='Toyota' name='Prius'/>! </cars>
  109. Markup template engine — in action 44 import  groovy.text.markup.*  

    ! def  config  =  new  TemplateConfiguration()   def  engine  =  new  MarkupTemplateEngine(config)   def  tmpl  =  engine.createTemplate('''          p("Hello  ${model.name}")   ''')   def  model  =  [name:  'World']   System.out  <<  tmpl.make(model)
  110. Markup template engine — includes 45 //  include  another  template

      include  template:  'foo.tpl'           //  include  raw  content   include  unescaped:  'raw.txt'   ! //  escape  &  include   include  escaped:  'to_escape.txt'
  111. Markup template engine 46 //  escaped  automatically   yield  'some

     raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                
  112. Markup template engine 46 //  escaped  automatically   yield  'some

     raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                 //  <!-­‐-­‐comment-­‐-­‐>   comment  'comment'                 ! //  adds  new  lines   newLine()                                 ! //  process.  instruct.   pi(/*  ...  */)                      
  113. Markup template engine — configuration options ! ! ! •

    declaration encoding ! • expand empty elements ! • use double quotes ! • newline string ! ! ! ! ! ! ! ! ! ! • auto escape ! • auto indent ! • base template class ! • locale 47
  114. Markup template engine — static! • Type-checked templates available •

    use createTypeCheckedModelTemplate() 
 instead of createTemplate() ! • Advantages • get compilation errors o if a variable is not available o if you make mistakes in the code snippets • even faster templates 48
  115. Markup template engine — static! • With typed check model

    creation method ! ! ! ! ! ! ! ! ! • Or declare your model types in the template 49
  116. Markup template engine — static! • With typed check model

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

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

    creation method ! ! ! ! ! ! ! ! ! • Or declare your model types in the template 49 def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   } Works with createTemplate() too
  119. Markup template engine — static! • With typed check model

    creation method ! ! ! ! ! ! ! ! ! • Or declare your model types in the template 49 def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  120. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Documentation overhaul
  121. GroovyDoc 51

  122. GroovyDoc 51

  123. GroovyDoc 51

  124. Groovy GDK documentation 52

  125. Groovy GDK documentation 52

  126. Brand new documentation 53

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

    without permission. Groovy 2.4
  128. Beta groovy-lang.org website 55

  129. Beta groovy-lang.org website 55

  130. Beta groovy-lang.org website 55

  131. Beta groovy-lang.org website 55 Notice the « improve this doc

    » button!
  132. Android support • You can use Groovy to code Android

    apps! • use Groovy 2.4.0-beta-1+ • prefer @CompileStatic ! • Two great posts to get started: • http://melix.github.io/blog/2014/06/grooid.html • http://melix.github.io/blog/2014/06/grooid2.html 56
  133. New York Times — Getting Groovy with Android 57

  134. New York Times — Getting Groovy with Android 57 http://bit.ly/nyt-groovy

  135. Android support 58

  136. Android support 58

  137. Android support 58 Source code available: https://github.com/melix/gr8confagenda

  138. To know all about AST transformations! 59 Groovy & Android,

    
 a winning pair? by Cédric Champeau Thu 12:45pm / Trinity 3
  139. Groovy Macros ! • Sergei Egorov wants to contribute a

    macro module • https://github.com/groovy/groovy-core/pull/470 ! • Simplify creation of AST transformations • less boilerplate manipulating the Groovy AST API • more powerful and less limited than AstBuilder 60
  140. Groovy Macros ! • Authoring AST transformations can be verbose:

    61 def  someVariable  =  new  ConstantExpression("xyz")   def  returnStatement  =  new  ReturnStatement(          new  ConstructorCallExpression(                  ClassHelper.make(SomeCoolClass),                  new  ArgumentListExpression(someVariable)          )   )
  141. Groovy Macros • With Groovy Macros, it could be simpler:

    62 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     }
  142. Groovy Macros • With Groovy Macros, it could be simpler:

    62 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     } Special « macro » command
  143. Groovy Macros • With Groovy Macros, it could be simpler:

    62 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     } Special « macro » command Quasi-quotation
  144. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Groovy 3.0
  145. None
  146. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. New Age Meta-Object Protocol MOP 2
  147. Goals for the new MOP • Leverage & build upon

    JDK 7+ invoke dynamic • get Java-like performance even for dynamic code • Rationalize the sedimentation of meta-programming • more coherence, less corner cases & inconsistencies • Provide a notion of « realm » • shield users of « monkey patching » • finer-grained control of meta-programming reach • Private visibility anyone? 66
  148. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Rewriting the Groovy grammar with Antlr v4 Antlr v4 Grammar
  149. Antlr v4 grammar • Problems • Groovy still uses Antlr

    v2! o but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar o harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant 
 and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs! 68
  150. Antlr v4 grammar • Problems • Groovy still uses Antlr

    v2! o but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar o harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant 
 and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs! 68 A « Google Summer of Code » student is currently helping
  151. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Support the new Java 8 language features Java 8 language support
  152. Java 8 support • Additional grammar & semantic features to

    support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations 70
  153. Java 8 support • Additional grammar & semantic features to

    support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations 70 Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
  154. To know all about AST transformations! 71 How to get

    Groovy 
 with Java 8 by Peter Ledbrook Thu 10:30pm / Trinity 3
  155. © 2014 SpringOne 2GX. All rights reserved. Do not distribute

    without permission. Summary
  156. None
  157. Groovy rocks the JVM 
 since 2003!

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

    without permission. Q & A
  159. None
  160. Image credits • Big rock • http://wallpaper.preview-reviews.com/12852-red-rocks-in-a-snowstorm • Android robot

    • http://crackberry.com/sites/crackberry.com/files/styles/large/public/topic_images/2013/ANDROID.png?itok=xhm7jaxS • Modern MOP • http://i933.photobucket.com/albums/ad179/autobin/Wonder%20Mop/wondermop4.jpg • Jason • http://static.comicvine.com/uploads/original/3/32405/1031312-jason_19_inch_figure_l.jpg • Jigsaw • http://www.psdgraphics.com/file/psd-jigsaw-icon.jpg • Many thanks • http://www.trys.ie/wp-content/uploads/2013/06/many-thanks.jpg 76