Groovy SDK Changelog

What's new in Groovy SDK 2.4

Jul 27, 2015
  • Android Support:
  • With Groovy 2.4, you can write Android applications in Groovy!
  • To build your Android applications with the Groovy support, you’ll be able to use the Gradle Groovy Android plugin.
  • The SwissKnife library builds upon the Groovy support to offer very useful AST transformations that kill the usual Android boilerplate code, for instance for dealing with UI events, with logic to be run in background threads, or make objects easily "parcelables", etc.
  • The work on the Android support also lead to various optimizations in terms of bytecode generation, as explained further down, as well as, for instance, improving the handling of overloaded setters which are frequent in the Android SDK.
  • Performance improvements and reduced bytecode:
  • This new major release of Groovy has seen various improvements across the board to reduce the quantity of bytecode produced, to lower memory consumption of internal data structures, fine tune bytecode for better performance.
  • Here are some of the tickets related to the topic:
  • Cheaper comparison operations
  • Reduced memory consumption for respondsTo()
  • For fully statically compiled classes, MOP related generated methods are not needed
  • Remove unneeded inner class distributor methods when no inner classes are present
  • Removal of the timestamp in Groovy classes
  • Optimization of primitive type conversions with the as operator
  • Traits @SelfType annotation:
  • Sometimes, it’s desired to be able to restrict a trait’s application so that it can only be applied to subclasses of a certain type. That’s what the @SelfType annotation is for.
  • Here’s a concrete example of @SelfType in action.
  • import groovy.transform.*
  • class Component {
  • void doSomething() {
  • println "Done!"
  • @SelfType(Component)
  • @TypeChecked
  • trait ComponentDecorator {
  • void logAndDoSomething() {
  • println "Going to do something"
  • doSomething()
  • class ConcreteComponent
  • extends Component
  • implements ComponentDecorator {}
  • def c = new ConcreteComponent()
  • c.logAndDoSomething()
  • The ComponentDecorator trait is calling the doSomething() method from the Component sub-class to which it will be applied. If you don’t specify the @SelfType(Component) annotation, when using static type checking or static compilation, the compiler will throw a compilation error as it wouldn’t know where the doSomething() method would be coming from. With the annotation, you instruct the compiler to figure out that this trait will only be applied to child of Component that will have that method available. @SelfType is interesting in the context of static type checking or compilation, but is not needed if your code is dynamic as the resolution will take place at runtime as usual.
  • GDK improvements:
  • System.currentTimeSeconds() to get the current time in seconds
  • List#getIndices() to get a range representing the indices of the elements of the list
  • More collection related methods are moved to iterator-based variants to apply to all iterable collection types and missing methods have been added like init(), dropRight(), takeRight()
  • Iterable gets disjoin(), minus() and toSpreadMap() methods
  • Refinements and concistency for existing collection methods, leveraging iterable approaches for stream-like traversals, consistency for mutation in place vs new collection creation, minor optimizations, etc.
  • New List#removeAt(index) and Collection#removeElement(Object) methods
  • Iterable gets a size() method like iterators
  • AST transformations:
  • The @ToString transformation offers an includeSuperProperties parameter so properties from the super class are also present in the string representation
  • You can define the compilation phase for the @ASTTest transformation for testing your AST transformations
  • @Synchronized supports explicit static locks to be used by instance methods if needed
  • Clean up generated code for @AutoExternalizable and @EqualsAndHashCode the when using @CompileStatic
  • @Builder’s default and initializer strategies improved Java integration
  • @PackageScope allowed on constructors too
  • Groovysh improvements:
  • The venerable Groovysh shell continues seeing some useful improvements:
  • Groovysh supports custom .rc and .profile scripts to be loaded on startup
  • completion of instanceof statements
  • completion of static members only displayed in a static context
  • completion candidates in color
  • with :set interpreterMode true, you can let Groovysh to let you see and use locally-defined variables after further line executions
  • the :load command supports file names containing spaces
  • make arguments and flags consistent with the groovy command and allow the launch of a script on startup passed as argument and continue execution of Groovysh
  • make it easier to subclass Groovysh for reuse as an embedded shell
  • Miscellaneous:
  • Allow Ant targets declaration by AntBuilder without immediate execution
  • Make NamespaceBuilder automatically detect namespace declarations
  • Implement and register type checking extensions as subclasses of TypeCheckingExtension
  • ConfigObject overrides toString() and offers a prettyPrint() method
  • Improved type checking for certain GDK methods
  • Grape is using JCenter through HTTP first for resolving dependencies, and now HTTPS is used for better security
  • Parameters of @DelegatesTo and @ClosureParams are better aligned
  • Multiple labels are supported on the same statement
  • Breaking changes:
  • A few issues fixed might also be considered breaking changes in some situations:
  • Malformed class names for closures in inner classes
  • Avoid creation of MOP methods in static compilation
  • Reduce memory consumption for respondsTo()
  • Making Groovysh more easily extendable and embeddable

New in Groovy SDK 2.3 (Jul 27, 2015)

  • Groovy 2.3 is the new major release of Groovy, featuring official support for running Groovy on JDK 8, traits, new and improved AST transformations like @TailRecursive, @Builder and @Sortable, a new NIO2 module with Path support, lightening fast JSON parsing and building,closure parameter type inference, a new markup template engine, Groovysh and GroovyConsole ease of use improvements, a new GroovyAssert test utility, more @BaseScript class capabilities, and more.
  • Official support for running Groovy on JDK 8:
  • This is the first version of Groovy to be officially compatible with JDK 8.
  • JDK 8 and its interface default methods introduced some incompatibilities with a few methods of the Groovy Development Kit, so we had to adapt to the situation, introducing minor breaking changes for the affected methods and their outcome.
  • Note that we’re not planning to backport the changes to older versions of Groovy, so if you want to run Groovy on JDK 8, you’ll have to upgrade to the shiniest version of Groovy!
  • Groovy 2.3 doesn’t support the new syntax constructs offered by Java 8 (such as lambdas, method references, default methods in interfaces, etc), but you can very well already use the new APIs offered by JDK 8, and even use Groovy closures in lieu of Java 8 lambdas.
  • For reference, here are a couple of examples which use Java 8 streams, for iterating over a stream of ints, or over the lines of a file:
  • IntStream.range(1, 100).forEach { println it }
  • Files.lines(Paths.get('README.adoc'))
  • .map { it.toUpperCase() }
  • .forEach { println it }
  • In particular, in the two statements above, notice that we replaced Java 8 lambdas with Groovy closures, as Groovy provides a closure coercion mechanism which transforms a Groovy closure into a functional interface — unlike Java, Groovy also provides that coercion mechanism for abstract classes containing a single abstract method.
  • In future versions of Groovy, certain Java 8 syntax constructs, or particular Groovy methods decorating JDK 8 APIs might be added.
  • Traits:
  • A major highlight for Groovy 2.3 is the introduction of the concept of traits.
  • Traits are reusable components of behavior that your classes can implement, and are an additional Object-Oriented concept alongside classes and interfaces.
  • Below, we create a trait with a concrete method fly() which returns a String.
  • trait FlyingAbility {
  • String fly() { "I'm flying!" }
  • Then we create a class, Bird, that implements that trait, and instantiate it:
  • class Bird implements FlyingAbility {}
  • def b = new Bird()
  • We can check that the Bird instance does have the new fly() method mixed-in:
  • assert b.fly() == "I'm flying!"
  • Groovy traits are stateful (unlike Java 8 interface default methods). A trait can have Groovy properties like plain classes:
  • trait Named {
  • String name
  • This time, the Bird class implements that Named trait:
  • class Bird implements Named {}
  • We can instantiate the Bird with the named-argument constructor shortcut provided by Groovy:
  • def b = new Bird(name: 'Colibri')
  • We assert that the instantiated Bird does have the name property added to it:
  • assert b.name == 'Colibri'
  • They allow the composition of behavior without going into the "diamond inheritance" problem allowing you to decide which behavior prevails upon conflict, either by convention (last trait declared wins) or by explicitly overriding the conflicting method:
  • 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'
  • Above, the surf() method from WebSurfer wins, as it’s the last declared trait, but you can reverse the trait implementation order if you want kite to be returned. If you want to be more explicit, your Hipster class can override the surf() method itself, and call WebSurfer.super.foo() or KiteSurfer.super.foo() or do something entirely different.
  • Traits support inheritance, thus a trait can extend another trait or implement an interface, as shown below:
  • 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 are compatible with static type checking and compilation, as well as our usual dynamic behavior. Trait mixed-in methods are actually "real" methods (ie. visible from Java as well) and not just dynamic. Note however, that not all existing AST transformations are compatible with traits.
  • Traits can also be implemented at runtime with as or with withTraits if you just want to add behavior of a trait to an object you’re instantiating, without having to create an intermediary artificial class just for that purpose (also called per-instance traits):
  • 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!'
  • New and updated AST transformations:
  • New transformations:
  • @TailRecursive:
  • @TailRecursive on methods adds tail recursion to methods which are recursive and call themselves at the last operation of the method body, which helps avoid blowing up the stack with the recursive calls.
  • Here’s a slightly rewritten factorial implementation, that is friendly to tail-call transformation:
  • 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
  • @Builder:
  • Recent Java APIs have adopted the builder pattern (not to be confused with Groovy’s builders) to instantiate complex objects, without requiring to multiply the number of constructors with variants taking various combination of parameters. Groovy 2.3 introduces a @Builder transformation to automate the creation of such builder APIs.
  • The @Builder transformation offers different implementation strategies that you can choose from:
  • a simple strategy for creating chained setters
  • an external strategy where you annotate an explicit builder class while leaving some buildee class being built untouched
  • a default strategy which creates a nested helper class for instance creation
  • and an initializer strategy which creates a nested helper class for instance creation which when used with @CompileStatic allows type-safe object creation
  • @Sortable:
  • @Sortable on classes implements comparison methods for you (through implementing the Comparable interface), according to the declaration order of your properties.
  • Additionally, you can define included / excluded fields, access individual field comparators with methods like comparatorByFirst().
  • @SourceURI:
  • With @SourceURI, you can annotate a java.net.URI or even a java.lang.String script variable or class field so that the variable or field are injected the URI of the Groovy file.
  • If you evaluate or compile a Groovy script or class, the variable or field will contain a data URI, for example, for the following example:
  • import groovy.transform.SourceURI
  • @SourceURI String src
  • println src
  • The src variable will contain the following data URI:
  • data:,import groovy.transform.SourceURI
  • @SourceURI String src
  • println src
  • If you save the script in a file called sourceuri.groovy in /tmp, and run that script with the groovy command, you’ll see an absolute File path printed:
  • file:/tmp/sourceuri.groovy
  • As we mentioned above, you can also write @SourceURI URI src, if you want to have a URI instead of a String.
  • Updated transformations:
  • @Delegate improvements:
  • @Delegate supports includeTypes and excludeTypes attributes to give you fine-grained control over which methods to include or exclude from delegation. Rather than just matching on name, this option matches on the name and parameter types expressed in an interface type.
  • @BaseScript class improvements:
  • @BaseScript is a fairly recent addition in Groovy, and it allowed to annotate a variable in your script to instruct the compiler to use a particular base script class for this script. Now we have another notation which is nicer as you can annotate an import or a package to indicate that base script class.
  • @BaseScript(MyScript)
  • import groovy.transform.BaseScript
  • Additionally, base script classes can now use any abstract method for the script body. This means that you can implement the run() method to implement specific behavior like setup and tear down in tests.
  • Given the following custom base script class, where we implement the default run() method, we also create a new abstract method called internalRun():
  • abstract class CustomBase extends Script {
  • def run() {
  • before()
  • internalRun()
  • after()
  • abstract internalRun()
  • def before() { println 'before' }
  • def after() { println 'after' }
  • We can then have the script below transparently implement the internalRun() method instead of the usual run() one:
  • import groovy.transform.BaseScript
  • @BaseScript CustomBase script
  • println 'Hello'
  • New NIO module for Java 7+:
  • On JDK 7 and beyond, you can benefit from the same methods as the ones of File but for the new NIO2 class Path.
  • You’ll find familiar methods of the Groovy GDK on File also available on Path like these ones:
  • path.withReader { Reader r -> ... }
  • path.eachLine { String line -> ... }
  • path.eachFileRecurse { Path p -> ... }
  • path

New in Groovy SDK 2.2 (Jul 27, 2015)

  • Implicit closure coercion:
  • Java 8 will feature lambdas, which are similar to Groovy’s closures. One particular aspect which is interesting with lambdas is how they are converted transparently by Java to interface types that contain one single abstract method. With Groovy closures, except for a few cases, we have to explicitly use the as operator to do the coercion. In Groovy 2.2, we are allowing the same transparent closure coercion to happen, but without the explicit as type coercion, and furthermore, we make it possible to work as well with abstract classes as well.
  • interface Predicate {
  • boolean test(obj)
  • List filter(List list,Predicate pred) {
  • list.findAll { pred.test(it) }
  • def input = [1, 2, 3, 4, 5]
  • def odd = filter(input) { it % 2 == 1 }
  • assert odd == [1, 3, 5]
  • Notice how the closure is coerced into a Predicate instance. Without that new capabilities, we would have had to write the following instead:
  • def odd = filter(input, { it % 2 == 1} as Predicate)
  • That way, Groovy closure coercion to SAM types is as concise as Java 8 lambda closure conversion.
  • Here’s another example using abstract classes, which are not supported by Java 8 lambda conversion.
  • @Memoized AST transformation for methods:
  • Similarly to our Closure memoization capability, you can now annotate your methods with the new @Memoized annotation. It will use the same underlying cache solution used for closures, and will cache the result of previous executions of the annotated method with the same entry parameters.
  • import groovy.transform.Memoized
  • @Memoized
  • int expensiveOp(int a, int b) {
  • sleep 1000
  • return a + b
  • expensiveOp(1, 2) // one second to return
  • expensiveOp(1, 2) // immediate result returned expensiveOp(1, 2)
  • Bintray’s JCenter repository:
  • The default Grab configuration now use Bintray’s JCenter repository as the first in the chain of resolvers, as Bintray’s JCenter repository is noticeably faster and more responsive than Maven Central, offers dependencies always with their checksums, and stores and caches dependencies it wouldn’t have for faster delivery the next time a dependency is required. This should make your scripts relying on @Grab faster when downloading dependencies for the first time.
  • Define base script classes with an annotation:
  • All scripts usually extend the kink:http://groovy.codehaus.org/api/groovy/lang/Script.html[groovy.lang.Script] abstract class, but it’s possible to set up our own base script class extending Script through CompilerConfiguration. A new AST transformation is introduced in Groovy 2.2 which allows you to define the base script class as follows:
  • import groovy.transform.BaseScript
  • abstract class DeclaredBaseScript extends Script {
  • int meaningOfLife = 42
  • @BaseScript DeclaredBaseScript baseScript
  • assert meaningOfLife == 42
  • New DelegatingScript base class for scripts:
  • With the CompilerConfiguration class that you pass to GroovyShell (as well as GroovyClassLoader and others), you can define a base script class for the scripts that will be compiled with that shell. It’s handy to share common methods to all scripts.
  • For DSL purposes, it’s interesting to actually delegate the method calls and unbound variable assignments to a different object than the script itself, thanks to the new DelegatingScript.
  • New @Log variant for the Log4j2 logging framework:
  • A new @Log variant has been added to support Log4j2, with the @Log4j2 AST transformation:
  • import groovy.util.logging.Log4j2
  • @Log4j2
  • class MyClass {
  • void doSomething() {
  • log.info 'did something groovy today!'
  • @DelegatesTo with generics type tokens:
  • The @DelegatesTo annotation, introduced in Groovy 2.1 that helps the type checker, IDEs, tools, to provide better support for DSLs using closure delegation strategies, works with generics token types as well. You can tell Groovy that the delegatee is of the type of the generics component.
  • import groovy.transform.*
  • @InheritConstructors
  • class MyList extends LinkedList {}
  • public Object map(
  • @DelegatesTo.Target List target,
  • @DelegatesTo(genericTypeIndex = 0) Closure arg) {
  • arg.delegate = target.join('')
  • arg()
  • @TypeChecked
  • def test() {
  • map(new MyList([’f', `o', `o'])) {
  • assert toUpperCase() == 'FOO'
  • Note the genericTypeIndex attribute of @DelegatesTo that points at the index of the generic component. Unfortunately, as the generic placeholders are not kept at the bytecode level, it’s impossible to just reference T, and we had to use an index to point at the right type.
  • Precompiled type checking extensions:
  • The static type checking extensions introduced in Groovy 2.1 were working solely with non-compiled scripts. But with this beta, you can also specify a fully-qualified name of the precompiled class implementing your extension.
  • @TypeChecked(extensions = 'com.enterprise.MyDslExtension')

  • Type checking extensions now also support two more events: ambiguousMethods and incompatibleReturnType.
  • Groovysh enhancements:
  • Groovysh has been expanded with various enhancements:
  • support for code completion in various places, like imports, package names, class names, variable names, parameter names, keywords, etc.
  • a doc command allows you to open the relevant JavaDoc and Groovy GDK web pages to have more information for a given class, for example try in Groovysh:
  • doc java.util.List
  • you can complete file names inside strings, particularly handy for your scripting tasks where you want to open a file with new File('data.|') (where the pipe character is the position of your cursor), and then hit the TAB key to have the completion of the file name
  • OSGi manifests for the invokedynamic JARs:
  • If you’re using Groovy in the context of an OSGi container, the Groovy JARs contained the right OSGi metadata information in its manifest. However, it wasn’t the case for the invokedynamic JARs, as the underlying library used by the Gradle OSGi plugin wasn’t supporting JDK 7 bytecode. Fortunately, this deficiency has been fixed, the Gradle OSGi plugin updated, and we’re now able to have our indy JARs work fine under OSGi has well.