Release notes for Groovy 2.3

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:

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.

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:

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:

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):

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
(GROOVY-6570).

Here’s a slightly rewritten factorial implementation, that is friendly
to tail-call transformation:

@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
(GROOVY-6484).

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

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
(GROOVY-6329).

@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
(GROOVY-6592) 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
(GROOVY-6585
and GROOVY-6615).

Given the following custom base script class, where we implement the
default run() method, we also create a new abstract method called
internalRun():

Performance improvements

Miscellanous improvements

Various minor performance improvements across the board, for static
compilation, the invokedynamic backend, as well as "normal"
dynamic Groovy, have been worked on.

Drastic JSON parsing and serialization performance improvements

Groovy JSON support has been refactored and tailored towards
performance, making Groovy 2.3’s JSON support usually
faster than all the JSON libraries available in the Java ecosystem.

Rick Hightower and Andrey Bleschestov covered the performance gains,
both in parsing and seralization, in
a benchmarks on Rick’s blog
and on Andrey’s JSON benchmark project on Github.
The results are impressive, as the parsing is generally roughly 2x to 4x faster with Groovy’s new
parsers compared to existing libraries, and ~21x faster than pre-Groovy 2.3 parsing.
On the serialization front, Groovy’s
new serialization is also ~17x faster than before, and at the same
level as competing libraries.

JSON slurper and builder enhancements

Beside the performance improvements of the JSON module, other updates
have taken place.

With JsonSlurper,
you’ll be able to set
different parser types
depending on the kind of input you wish to parse, particularly if
you know the size of the payload you expect to parse, or whether you
want a more tolerant parser which accepts elements like comments which
are not normally supported by the JSON specification.

Closure parameter type inference

We closed a gap which forced you to type your closure parameters to get
correct type inference with static type checking or static compilation
enabled. In situations like the following, you would have to explicitly
give the type of the parameter, but it’s no longer required:

['a','b'].each { it.toUpperCase() }

In the signature of your methods taking closures as arguments, you’ll
also be able to annotate the closure parameter
with @ClosureParams
to give additional hints to the type checker to infer the type of the
parameters passed to your closure.

New markup template engine

Groovy now has an additional template engine, in the form of the Markup
template engine, which gives you a very fast template engine (thanks to
static compilation), based on the familiar Markup builder approach and
notation, but also offering formatting options (indentation, escaping),
internationalization, includes, as well as proposing type checked
templates and models.

More details about the
new Markup template engine
in the documentation, as well as in Cédric’s blog, if you want to learn more
about the "behind the scenes" stories!

To illustrate the basic usage, consider you have the following template:

Note that this template engine is super fast as it’s statically
compiled.

JUnit 4 GroovyAssert class

The
venerable GroovyTestCase
(JUnit 3 based approach) has often been used as a base class for your
test classes — unless you’ve been using
the Spock testing framework, of course.
One of the drawback of this class is that your test classes can’t extend
your own classes, but must derive from GroovyTestCase to benefit from
the additional assertion methods.

In earlier versions of Groovy we introduced the JUnit
4-friendly GroovyAssert,
which is a convenient class offering the usual assertion methods of
GroovyTestCase, but in the form of static methods that you can static
import in your test class. In Groovy 2.3 we’ve enriched GroovyAssert
with additional features. There should be no reason to move on from
JUnit 3 if you haven’t already done so. We didn’t include all of the
myriad of assertEquals methods from GroovyTestCase as they are typically
less useful than Groovy’s built-in power assert, but it provides some
handy shouldFail() and assertScript() methods
(GROOVY-6588).

For instance, if you want to leverage the shouldFail(String) and
assertScript(String) methods, you can do so as follows:

ConfigSlurper

ConfigSlurper has previously supported a single "environments"
non-configurational conditional block, but you couldn’t define your own.
With Groovy 2.3 you can also create your own such blocks. For instance
if you wanted to support "flavors" like OS variants
(GROOVY-6383).

In addition, the isSet() / hasSet() combo methods
(GROOVY-4639) have been
added so you can double check if a given node of your configuration has
been defined. Before, whether the node wasn’t defined or containing
null, you couldn’t differentiate either case easily.

Tools enhancements

Groovysh

Along with a slightly reduced startup time, Groovysh has seen new
improvements in its code-completion capabilities:

Commands are now prefixed with ``:''
(link:https://jira.codehaus.org/browse/GROOVY-6397).

GroovyConsole

It is now possible to configure the font used by the console
(GROOVY-6303, although
without a UI dialog yet), and also to be able to run a selected snippet
of code reusing the imports defined in your script making it easier to
just run quick snippets of your script. The ability to comment or
uncomment selected code by pressing Ctrl + was added
with GROOVY-6459.

Documentation

New documentation

We are still working on the
brand new documentation for Groovy
(in Asciidoc(tor) format), so you can already
have a glimpse at what’s already covered or not.

We’re looking forward to your help for fleshing out the various TBD ("To
Be Done") sections of the documentation, as it’s a gigantic task to
re-document each and every aspect of the language and its libraries! So
please shout if you want to contribute to the new documentation! All
help is warmly welcome!

Refreshed GroovyDoc documentation style

GroovyDoc has been updated with a new fresh and modern skin that will be
part of the future visual identity of the Groovy website. Those style
updates are also available by default for your own usage of GroovyDoc,
making your own documentation nicer on the eye.

Refreshed Groovy GDK documentation style

We also took the opportunity to apply the same stylesheet to our
DocGenerator tool which is responsible for the generation of the GDK
documentation, showing the methods the Groovy library adds on top of the
JDK classes.

Breaking changes

Groovy 2.3.0 introduces a limited list of breaking changes.

First of all,Groovy 2.3.0 now requires JDK 6 as its minimal JDK
requirement. Some parts of Groovy 2.3.0 might still run under JDK 5 but
no testing has been done on that platform and some parts are known not
to work. We encourage everyone to move to at least JDK 6.

In Groovy 2.3.0, we reworked our implementation of generics handling.
Although we don’t know of any particular breakage so far, the static
type checker might report new errors as it can be stricter than before.
If ever you encounter such new errors in this area, please report them
as soon as you encounter them.

With the introduction of "traits" in Groovy 2.3, the trait keyword
is an addition to the list of keyword of the languages, with the
consequence that variables or fields that would use trait as name
with yield a compilation error. So you would have to change the name of
your variable and recompile your code.

A few updates have been made to the XML support around whitespace
handling, and text node handling:

With the new default methods on interfaces in JDK 8, there was
particularly one,
a List#sort(Comparable) method, which conflicted with one of the GDK,
so we had to remove ours to stay compliant with JDK 8.