• Save
GR8Conf 2011: Groovy 1.8 update
Upcoming SlideShare
Loading in...5
×
 

GR8Conf 2011: Groovy 1.8 update

on

  • 1,466 views

 

Statistics

Views

Total Views
1,466
Views on SlideShare
1,466
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

GR8Conf 2011: Groovy 1.8 update GR8Conf 2011: Groovy 1.8 update Presentation Transcript

  • Groovy Update What’s new in Groovy 1.8 and what’s coming next! Guillaume Laforge Groovy Project Manager SpringSource / VMwaremercredi 18 mai 2011
  • Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2mercredi 18 mai 2011
  • Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2mercredi 18 mai 2011
  • Groovy 1.7 3mercredi 18 mai 2011
  • Groovy 1.7 185 3mercredi 18 mai 2011
  • Groovy 1.7 185k 3mercredi 18 mai 2011
  • Groovy 1.7 185k FIRST MONTH AFTER RELEASE 3mercredi 18 mai 2011
  • Groovy 1.7 k 3mercredi 18 mai 2011
  • Groovy 1.7 177k SECOND MONTH AFTER RELEASE 3mercredi 18 mai 2011
  • Groovy 1.7 k 3mercredi 18 mai 2011
  • Groovy 1.7 362k USERS? 3mercredi 18 mai 2011
  • ? TIP OF THEmercredi 18 mai 2011 ICEBERG
  • Agenda •What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous 5mercredi 18 mai 2011
  • Agenda •What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous •What’s cooking for Groovy 1.9? – Continued runtime performance improvements – Alignments with JDK 7 •Project Coin (small language changes) •InvokeDynamic 5mercredi 18 mai 2011
  • Command chains expressions 6mercredi 18 mai 2011
  • Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6mercredi 18 mai 2011
  • Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6mercredi 18 mai 2011
  • Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences •(or any language, of course) 6mercredi 18 mai 2011
  • Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences •(or any language, of course) 6mercredi 18 mai 2011
  • Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences •(or any language, of course) • Let’s have a look at some examples 6mercredi 18 mai 2011
  • Command chains expressions  turn left  then right  7mercredi 18 mai 2011
  • Command chains expressions Alternation of method names  turn left  then right  7mercredi 18 mai 2011
  • Command chains expressions Alternation of method names  turn left  then right  and parameters (even named ones) 7mercredi 18 mai 2011
  • Command chains expressions  turn left  then right  7mercredi 18 mai 2011
  • Command chains expressions Equivalent to:      (    ).    (     )  turn left  then right  7mercredi 18 mai 2011
  • LookM a! N op are ns, no do ts!mercredi 18 mai 2011
  • Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours 9mercredi 18 mai 2011
  • Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument 9mercredi 18 mai 2011
  • Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument Named arguments 9mercredi 18 mai 2011
  • Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument Named arguments Woud call: def take(Map m, Quantity q) 9mercredi 18 mai 2011
  • Command chains expressions Now, even less punctuation! take 2.pills  of  chloroquinine  after  6.hours 10mercredi 18 mai 2011
  • Command chains expressions Now, even less punctuation!     (       ).   (             ).      (       ) take 2.pills  of  chloroquinine  after  6.hours 10mercredi 18 mai 2011
  • Command chains expressions // environment initialization Integer.metaClass.getPills { ‐> delegate } Integer.metaClass.getHours { ‐> delegate }   // variable injection def chloroquinine = /*...*/   { } // implementing the DSL logic def take(n) {     [of: { drug ‐>         [after: { time ‐> /*...*/ }]     }] } // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take 2.pills of chloroquinine after 6.hours 11mercredi 18 mai 2011
  • Command chains expressions take 2.pills  of  chloroquinine  after  6.hours 12mercredi 18 mai 2011
  • Command chains expressions take 2.pills  of  chloroquinine  after  6.hours ... some dots remain ... 12mercredi 18 mai 2011
  • Command chains expressions We could cheat a bit... take 2  pills of  chloroquinine 6  hours after 13mercredi 18 mai 2011
  • Command chains expressions We could cheat a bit...     ( ).     (  ).             ( ).     (     ) take 2  pills of  chloroquinine 6  hours after 13mercredi 18 mai 2011
  • Cheating is playing with the languagemercredi 18 mai 2011
  • Command chains expressions Still doable without cheating though take 2  pills of  chloroquinine after  6 hours 15mercredi 18 mai 2011
  • Command chains expressions Still doable without cheating though     ( ).     (  ).             (     ). (     ) take 2  pills of  chloroquinine after  6 hours 15mercredi 18 mai 2011
  • Command chains expressions // variable injection def (of, after, hours) = /*...*/   // implementing the DSL logic { } def take(n) {     [pills: { of ‐>         [chloroquinine: { after ‐>             [6: { time ‐> }]         }]     }] } // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take 2 pills of chloroquinine after 6 hours 16mercredi 18 mai 2011
  • Command chains expressions 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation check that: margarita  tastes good 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero‐arg methods require parens select all  unique() from names 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero‐arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (      ).    (           ).   (      ) // leverage named‐args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero‐arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (      ).    (           ).   (      ) // leverage named‐args as punctuation check that: margarita  tastes good      (               ).      (    ) // closure parameters for new control structures given {}  when {}  then {} // zero‐arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (      ).    (           ).   (      ) // leverage named‐args as punctuation check that: margarita  tastes good      (               ).      (    ) // closure parameters for new control structures given {}  when {}  then {}      (  ).    (  ).    (  ) // zero‐arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (      ).    (           ).   (      ) // leverage named‐args as punctuation check that: margarita  tastes good      (               ).      (    ) // closure parameters for new control structures given {}  when {}  then {}      (  ).    (  ).    (  ) // zero‐arg methods require parens select all  unique() from names       (   ).        .    (     ) // possible with an odd number of terms take 3  cookies 17mercredi 18 mai 2011
  • Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (      ).    (           ).   (      ) // leverage named‐args as punctuation check that: margarita  tastes good      (               ).      (    ) // closure parameters for new control structures given {}  when {}  then {}      (  ).    (  ).    (  ) // zero‐arg methods require parens select all  unique() from names       (   ).        .    (     ) // possible with an odd number of terms take 3  cookies     ( ). 17mercredi 18 mai 2011
  • Runtime perf. improvements • Significant runtime improvements for primitive int operations – classical Fibonacci example x13 faster! – almost as fast as Java • Some direct method calls on this • But there’s more to come! – in particular for all the primitive types • But Jochen «blackdrag» will tell you more on that! 18mercredi 18 mai 2011
  • GPars bundled • GPars is bundled in the Groovy distribution • GPars covers a wide range of parallel and concurrent paradigms – actors, fork/join, dataflow, agents, STM... • Václav Pech will cover the details on GPars 19mercredi 18 mai 2011
  • Closure enhancements • Closure annotation parameters • Some more functional flavor – composition – trampoline – memoization • Currying improvements 20mercredi 18 mai 2011
  • Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface Invariant {         Class value() // a closure class }   { @Invariant({ number >= 0 }) class Distance {         float number         String unit }    def d = new Distance(number: 10, unit: "meters")  def anno = Distance.getAnnotation(Invariant) def check = anno.value().newInstance(d, d) assert check(d) 21mercredi 18 mai 2011
  • Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface Invariant {         Class value() // a closure class }   { @Invariant({ number >= 0 }) class Distance {         float number     P oor-m miss Cont Andr racts an’s G é’s talk!     String unit Don’t }    def d = new Distance(number: 10, unit: "meters")  def anno = Distance.getAnnotation(Invariant) def check = anno.value().newInstance(d, d) assert check(d) 21mercredi 18 mai 2011
  • Closure composition def plus2  = { it + 2 } def times3 = { it * 3 }    { def times3plus2 = plus2 << times3 assert times3plus2(3) == 11 assert times3plus2(4) == plus2(times3(4))    { def plus2times3 = times3 << plus2 assert plus2times3(3) == 15 assert plus2times3(5) == times3(plus2(5))    // reverse composition { assert times3plus2(3) == (times3 >> plus2)(3) 22mercredi 18 mai 2011
  • Closure trampoline 23mercredi 18 mai 2011
  • Closure trampoline def factorial factorial = { int n, BigInteger accu = 1G ‐>        if (n < 2) return accu          factorial.trampoline(n ‐ 1, n * accu) }.trampoline()   assert factorial(1)    == 1 assert factorial(3)    == 1 * 2 * 3 assert factorial(1000) == 402387260... 23mercredi 18 mai 2011
  • Closure memoization 24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() 24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms 24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately 24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms 24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately   24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached def plusAtMost = { ... }.memoizeAtMost(10)  24mercredi 18 mai 2011
  • Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached def plusAtMost = { ... }.memoizeAtMost(10)  // between 10 and 20 invocations cached def plusAtLeast = { ... }.memoizeBetween(10, 20) 24mercredi 18 mai 2011
  • Currying improvements 25mercredi 18 mai 2011
  • Currying improvements // right currying def divide = { a, b ‐> a / b } def halver = divide.rcurry(2) assert halver(8) == 4     25mercredi 18 mai 2011
  • Currying improvements // right currying def divide = { a, b ‐> a / b } def halver = divide.rcurry(2) assert halver(8) == 4     // currying n‐th parameter def joinWithSeparator =      { one, sep, two ‐> one + sep + two } def joinWithComma =      joinWithSeparator.ncurry(1, , ) assert joinWithComma(a, b) == a, b 25mercredi 18 mai 2011
  • Builtin JSON support • Consuming • Producing • Pretty-printing 26mercredi 18 mai 2011
  • Builtin JSON support import groovy.json.*  def payload = new URL(     "http://github.../json/commits/...").text  def slurper = new JsonSlurper() def doc = slurper.parseText(payload)  doc.commits.message.each { println it } 27mercredi 18 mai 2011
  • Builtin JSON support import groovy.json.*    def json = new JsonBuilder()    json.person {         name "Guillaume"     age 33         pets "Hector", "Felix" }  println json.toString() 28mercredi 18 mai 2011
  • Builtin JSON support import groovy.json.*    println JsonOutput.prettyPrint(     {"person":{"name":"Guillaume","age":33, +      "pets":["Hector","Felix"]}})   29mercredi 18 mai 2011
  • Builtin JSON support import groovy.json.*    println JsonOutput.prettyPrint(     {"person":{"name":"Guillaume","age":33, +      "pets":["Hector","Felix"]}})   {         "person": {                 "name": "Guillaume",              "age": 33,                 "pets": [                         "Hector",                         "Felix"                 ]         } } 29mercredi 18 mai 2011
  • New AST transformations • @Log • @Canonical – @ToString, • @Field – @EqualsAndHashCode, – @TupleConstructor • @AutoClone • @InheritConstructor • @AutoExternalizable • @WithReadLock • Controlling the execution of your code • @WithWriteLock – @ThreadInterrupt, – @TimedInterrupt, • @ListenerList – @ConditionalInterrupt 30mercredi 18 mai 2011
  • @Log • Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j • Possible to implement your own strategy import groovy.util.logging.*    @Log class Car {         Car() {                 log.info Car constructed         } }    def c = new Car() 31mercredi 18 mai 2011
  • @Log • Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j • Possible to implement your own strategy import groovy.util.logging.*    @Log class Car {     Guarded     Car() {         w/ an if         log.info Car constructed         } }    def c = new Car() 31mercredi 18 mai 2011
  • @Log • Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j • Possible to implement your own strategy import groovy.util.logging.*    Hackerg @Log arten class Car {     certified! Guarded     Car() {         w/ an if         log.info Car constructed         } }    def c = new Car() 31mercredi 18 mai 2011
  • @Field • Surprising scoping rules in scripts – variables are local to the run() method – variables aren’t visible in methods •although visually the variable is in a surrounding scope • @Field creates a field in the script class @Field List awe = [1, 2, 3] def awesum() { awe.sum() } assert awesum() == 6 32mercredi 18 mai 2011
  • Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? 33mercredi 18 mai 2011
  • Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33mercredi 18 mai 2011
  • Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33mercredi 18 mai 2011
  • Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code • Also see compilation customizers later on 33mercredi 18 mai 2011
  • @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) {     // eat lots of CPU } 34mercredi 18 mai 2011
  • @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { {     if (Thread.currentThread.isInterrupted())         throw new InterruptedException() }     // eat lots of CPU } 34mercredi 18 mai 2011
  • @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { {     if (Thread.currentThread.isInterrupted())         throw new InterruptedException() }     // eat lots of CPU } • Two optional annotation parameters available – checkOnMethodStart (true by default) – applyToAllClasses (true by default) 34mercredi 18 mai 2011
  • @TimedInterrupt @TimedInterrupt(10) import groovy.transform.TimedInterrupt    while (true) {     // eat lots of CPU } • InterruptedException thrown when checks indicate code ran longer than desired • Optional annotation parameters available – same as @ThreadInterrupt – value: for an amount of time duration – unit: for the time duration unit (TimeUnit.SECONDS) 35mercredi 18 mai 2011
  • @ConditionalInterrupt • Specify your own condition to be inserted at the start of method and closure bodies – check for available resources, number of times run, etc. • Leverages the new closure annotation parameter feature of Groovy 1.8 @ConditionalInterrupt({ counter++ > 2 }) import groovy.transform.ConditionalInterrupt import groovy.transform.Field    @Field int counter = 0  100.times {         println executing script method... } 36mercredi 18 mai 2011
  • @ToString • Provides a default toString() method to your types • Available annotation options – includeNames, includeFields, includeSuper, excludes import groovy.transform.ToString    @ToString class Person {         String name         int age }    println new Person(name: Pete, age: 15) // => Person(Pete, 15) 37mercredi 18 mai 2011
  • @EqualsAndHashCode • Provides default implementations for equals() and hashCode() methods import groovy.transform.EqualsAndHashCode    @EqualsAndHashCode class Coord {         int x, y }    def c1 = new Coord(x: 20, y: 5) def c2 = new Coord(x: 20, y: 5)    assert c1 == c2 assert c1.hashCode() == c2.hashCode() 38mercredi 18 mai 2011
  • @TupleConstructor • Provides a «classical» constructor with all properties • Several annotation parameter options available import groovy.transform.TupleConstructor    @TupleConstructor  class Person {         String name         int age }    def m = new Person(Marion, 3)         assert m.name == Marion assert m.age  == 3 39mercredi 18 mai 2011
  • @Canonical • One annotation to rule them all! – @Canonical mixes together •@ToString •@EqualsAndHashCode •@TupleConstructor • You can customize behavior by combining @Canonical and one of the other annotations 40mercredi 18 mai 2011
  • @InheritConstructor • Classes like Exception are painful when extended, as all the base constructors should be replicated class CustomException extends Exception {     CustomException()                        { super()       }     CustomException(String msg)              { super(msg)    }     CustomException(String msg, Throwable t) { super(msg, t) }     CustomException(Throwable t)             { super(t)      } } 41mercredi 18 mai 2011
  • @InheritConstructor • Classes like Exception are painful when extended, as all the base constructors should be replicated import groovy.transform.* @InheritConstructors class CustomException extends Exception {     CustomException()                        { super()       }     CustomException(String msg)              { super(msg)    }     CustomException(String msg, Throwable t) { super(msg, t) }     CustomException(Throwable t)             { super(t)      } } 41mercredi 18 mai 2011
  • @WithReadLock, @WithWriteLock import groovy.transform.*    class ResourceProvider {         private final Map<String, String> data = new HashMap<>()       @WithReadLock         String getResource(String key) {                 return data.get(key)         }            @WithWriteLock         void refresh() {                 //reload the resources into memory         } } 42mercredi 18 mai 2011
  • @WithReadLock, @WithWriteLock import groovy.transform.*    class ResourceProvider {         private final Map<String, String> data = new HashMap<>()   {     @WithReadLock         String getResource(String key) {                 return data.get(key)         }        {     @WithWriteLock         void refresh() {                 //reload the resources into memory         } } 42mercredi 18 mai 2011
  • Miscelanous • Compilation customizers • Java 7 diamond operator • Slashy and dollar slashy strings • New GDK methods • (G)String to Enum coercion 43mercredi 18 mai 2011
  • Compilation customizers • Ability to apply some customization to the Groovy compilation process • Three available customizers – ImportCustomizer – SecureASTCustomizer – ASTTransformationCustomizer • But you can implement your own 44mercredi 18 mai 2011
  • Imports customizer def configuration = new CompilerConfiguration()   def custo = new ImportCustomizer() custo.addStaticStar(Math.name) configuration.addCompilationCustomizers(custo)    def result = new GroovyShell(configuration)     .evaluate(" cos PI/3 ") 45mercredi 18 mai 2011
  • Applying an AST transformation def configuration = new CompilerConfiguration() configuration.addCompilationCustomizers(     new ASTTransformationCustomizer(Log))    new GroovyShell(configuration).evaluate("""     class Car {                 Car() {                         log.info Car constructed                 }         }          log.info Constructing a car         def c = new Car() """) 46mercredi 18 mai 2011
  • Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions • Let’s setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizer import org.codehaus.groovy.control.customizers.* import org.codehaus.groovy.control.* import static org.codehaus.groovy.syntax.Types.*   def imports = new ImportCustomizer().addStaticStars(java.lang.Math) def secure = new SecureASTCustomizer() ... 47mercredi 18 mai 2011
  • Secure AST customizer ... secure.with { // disallow closure creation closuresAllowed = false  // disallow method definitions methodDefinitionAllowed = false    // empty white list => forbid imports importsWhitelist = []  staticImportsWhitelist = [] // only allow the java.lang.Math.* static import staticStarImportsWhitelist = [java.lang.Math ... 48mercredi 18 mai 2011
  • Secure AST customizer ... // language tokens allowed tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, MOD, POWER, PLUS_PLUS,  MINUS_MINUS, COMPARE_EQUAL, COMPARE_NOT_EQUAL,  COMPARE_LESS_THAN, COMPARE_LESS_THAN_EQUAL,  COMPARE_GREATER_THAN, COMPARE_GREATER_THAN_EQUAL ]   // types allowed to be used (including primitive types) constantTypesClassesWhiteList = [ Integer, Float, Long, Double, BigDecimal,  Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE ]   // classes who are allowed to be receivers of method calls receiversClassesWhiteList = [  Math, Integer, Float, Double, Long, BigDecimal ] } ... 49mercredi 18 mai 2011
  • Secure AST customizer • Ready to evaluate our arithmetic expressions! ... def config = new CompilerConfiguration() config.addCompilationCustomizers(imports, secure) def shell = new GroovyShell(config)   shell.evaluate cos(PI/3) • But the following would have failed: shell.evaluate System.exit(0) 50mercredi 18 mai 2011
  • Slashy and dollar slashy strings • Slashy strings are now multiline – particularly handy for multi-line regexs • Dollar slashy string notation introduced – a multiline GString with different escaping rules def (name, date) = ["Guillaume", "May, 17th"] def dollarSlashy = $/         Hello $name, today were ${date}     $ dollar‐sign         $$ dollar‐sign          backslash         / slash        $/ slash /$  51mercredi 18 mai 2011
  • New GDK methods 52mercredi 18 mai 2011
  • New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   52mercredi 18 mai 2011
  • New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   52mercredi 18 mai 2011
  • New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   52mercredi 18 mai 2011
  • New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   // map withDefault() def words = "one two two three three three".split() def freq = [:].withDefault { k ‐> 0 } words.each { freq[it] += 1 } 52mercredi 18 mai 2011
  • (G)String to Enum coercion enum Color {         red, green, blue }  53mercredi 18 mai 2011
  • (G)String to Enum coercion enum Color {         red, green, blue }    53mercredi 18 mai 2011
  • (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    53mercredi 18 mai 2011
  • (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"    53mercredi 18 mai 2011
  • (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"    // with GStrings too def g = "${green}" as Color 53mercredi 18 mai 2011
  • What’s cookingmercredi 18 mai 2011 for 1.9?
  • Groovy 1.9 roadmap • Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch • JDK 7: InvokeDynamic • Towards a more modular Groovy • Rewritten Antlr 3 grammar (GSoC) • Eclipse compiler to replace the joint compiler? • What else? Your call! 55mercredi 18 mai 2011
  • Groovy 1.9 roadmap • Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch • JDK 7: InvokeDynamic • Towards a more modular Groovy • Rewritten Antlr 3 grammar (GSoC) • Eclipse compiler to replace the joint compiler? • What else? Your call! 55mercredi 18 mai 2011
  • Binary literals • We had decimal, octal and hexadecimal notations for number literals • We can now use binary representations too int x = 0b10101111 assert x == 175   byte aByte = 0b00100001 assert aByte == 33   int anInt = 0b1010000101000101 assert anInt == 41285 56mercredi 18 mai 2011
  • Underscore in literals • We can now also add underscores in number literals for more readability long creditCardNumber = 1234_5678_9012_3456L long socialSecurityNumbers = 999_99_9999L float monetaryAmount = 12_345_132.12 long hexBytes = 0xFF_EC_DE_5E long hexWords = 0xFFEC_DE5E long maxLong = 0x7fff_ffff_ffff_ffffL long alsoMaxLong = 9_223_372_036_854_775_807L long bytes = 0b11010010_01101001_10010100_10010010 57mercredi 18 mai 2011
  • Multicatch • One block for multiple exception caught – rather than duplicating the block try {     /* ... */ } catch(IOException | NullPointerException e) {     /* one block to treat 2 exceptions */ } 58mercredi 18 mai 2011
  • Summary ROCK! 59mercredi 18 mai 2011
  • Thank you! e aforg pment ume L Develo Guilla Groovy om He ad of e@ gmail.c glaforg rge Email: @glafo : Twitter 60mercredi 18 mai 2011
  • Image credits • Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg • Bicycle: http://drunkcyclist.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=2131&g2_serialNumber=2 • Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg • Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg • Cheating: http://fr.academic.ru/pictures/frwiki/67/Cheating.JPG • Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/ • Oui nide iou: http://desencyclopedie.wikia.com/wiki/Fichier:Superdupont_we_need_you.jpg • Guitar: http://www.lelitteraire.com/IMG/breveon323.jpg • Trampoline: http://www.fitness-online.fr/images/trampoline-1-m.jpg • Curry: http://www.pot-a-epices.com/wp-content/uploads/2009/02/curry1.jpg • Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg 61mercredi 18 mai 2011