Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Info
titleStatus

This is a work in progress document for the upcoming release notes for Groovy 2.1

With this new 2.1 release, Groovy:

  • has full support for the JDK 7 “invoke dynamic” instruction and API,
  • goes beyond conventional static type checking capabilities with a special annotation for closure delegate based Domain-Specific Languages and static type checker extensions,
  • provides additional compilation customization options,
  • and features a meta-annotation facility for combining annotations elegantly.

...

Table of Content

Table of Contents
excludeTable of Content

Full invoke dynamic support

With Groovy 2.0, we introduced support for JDK 7’s “invoke dynamic” bytecode instruction and API to benefit from the dedicated support and performance improvements for dynamic languages starting with JDK 7. Groovy 2.1 brings full support for “invoke dynamic” (aka “indy”), completing the work introduced in 2.0. 

In Groovy 2.0, most method calls were using the “invoke dynamic” instruction, but there have been exceptions: constructor calls or “spread calls” (where you pass arguments with the “spread operator”). Groovy 2.1 completes the implementation started in 2.0. Now, code compiled with the “invoke dynamic” JAR on JDK 7 will not be using the old “call site caching” code which served us well for getting good performance for Groovy prior to JDK 7. If you are lucky enough to be using JDK 7 in production, be sure to use the Groovy 2.1 “indy” JAR to benefit from the full “invoke dynamic” support. The “indy” version is bundled with the binary download package and can be obtained via Maven (all JARs with “invoke dynamic” support are postfixed with “-indy”).

You can learn more about the invoke dynamic support.

GPars 1.0

Groovy 2.1’s distribution bundles the recently released GPars 1.0, the one-stop shop for all your concurrency needs. This new version comes with various enhancements in the asynchronous functions, promises, parallel collections, actors, dataflow support, Google App Engine support, etc.

...

Code Block
languagegroovy
void exec(@DelegatesTo.Target ex, @DelegatesTo Closure c) {
    c.delegate = ex
    c()
}

class Executor {
    void launchvoid launch() {}
}

def ex = new Executor()

exec(ex) {
    launch()
}

We’ve seen that the @DelegatesTo helps documenting, tooling, and checking Domain-Specific Languages in the specific context of closure delegate based methods, but we hinted at the fact we can go beyond, in terms of static type checking for your DSLs.

For more details take a look at the @DelegatesTo documentation.

Type checker extensions

Static type checking was introduced in Groovy 2.0, but Groovy 2.1 goes beyond built-in type checks and offers a way to create type checker extensions. This is great news for Groovy scripts, configuration files, or Domain-Specific Languages implementations as they can can be “type checked” with more advanced, domain-specific rules. As an example, it would be possible to create a custom DSL type checker that throws compilation errors when certain verbs of the DSL are not recognized, or tells this other noun is allowed even if it’s a dynamic name bound at runtime, or type checks literal strings containing SQL code to see if the syntax is correct, and more.

...

The two examples are just the tip of the iceberg, but we will work out more complete documentation of the various extension points and utility methods going forward.

For more details take a look at the type checking extensions documentation.

Compile-time Meta-annotations

...

Code Block
languagegroovy
@NotNull
@Length(13)
@Pattern(/\d{12}(\d|X)/)
@groovy.transform.AnnotationCollector
@interface ISBN13@interface ISBN13 {}

@ISBN13 as a single annotation can now be applied on code elements, instead of applying the entire annotation gang::

...

Code Block
languagegroovy
@interface Service {}

@interface Transactional {
    String propagation() default "required"
   
}

We define the meta-annotation combining both the above annotations:

Code Block
languagegroovy
@groovy.transform.AnnotationCollector([Service, Transactional])
@interface TransactionalService@interface TransactionalService {}

But we want to change the propagation strategy for the underlying @Transactional annotation, we do so by passing the parameter to the meta-annotation:

Code Block
languagegroovy
@TransactionalService(propagation = "mandatory")
class BankingServiceclass BankingService { }

Note that if two combined annotations share the same parameter name, the last annotation declared wins and gets the parameter passed to the meta-annotation.

...

The full example can be found in this Gist on Github: https://gist.github.com/4563430

Additional details can be found in the meta-annotations documentation.

Compilation customization

...

Code Block
languagegroovy
import static java.lang.Math.*

assert sin(PI/2) == 1

For evaluating such math expressions, you wish to make the static import implicit, so that the final script will actually look like this:

Code Block
languagegroovy
assert sinassert sin(PI/2) == 1

If you’d run it as is, you’d get an error message saying:

...

Code Block
languagegroovy
import org.codehaus.groovy.control.customizers.ImportCustomizer

def importCustomizer = new ImportCustomizer()
customizerimportCustomizer.addStaticStar('java.lang.Math')

configuration.addCompilationCustomizers(importCustomizer)

...

Code Block
languagegroovy
import org.codehaus.groovy.control.customizers.*
import groovy.transform.ToString

def importCustomizer = new ImportCustomizer()
customizerimportCustomizer.addStaticStar('java.lang.Math')

configuration.addCompilationCustomizers(
    new SourceAwareCustomizer(new ASTTransformationCustomizer(ToString)) {
        boolean acceptBaseName(baseName) { baseName ==~ 'MyDomain' }
    },
    new SourceAwareCustomizer(importCustomizer) {
        boolean acceptBaseName(baseName) { baseName ==~ 'mathFormula' }
    })

...

The configuration code is easier to read and maintain, thanks to the clarity brought by the builder approach. But we’ve only seen a couple examples of customization, and you should have a look at the other customizations available in the org.codehaus.groovy.control.customizers.builder package to learn more about them.

More details can be found in the advanced compiler configuration documentation.

Other Minor Enhancements

...

Additional DGM methods

There are now leftShift and withFormatter methods for Appendable objects.
There are now methods for creating temporary directories and determining the total size of all files in a directory.
There is now a collectMany for maps (has been backported to earlier versions of Groovy too).
There is now a closeStreams() method for Process objects.

...

There is a method for escaping / encoding XML entities in Strings.
There is a convenience method for serializing Elements objects. 
You ca can now clone Node and NodeList objects. 
The name() method now works for all Node objects, not just Element objects. 

...

You can now specify knownImmutables. When This is useful when you know you are using an immutable object, but its type isn't one of the known immutable types.

...