Table of Contents
The 1.8 release of Groovy comes with many new features that greatly enhance
These features have undergone the Groovy developer process with formal descriptions, discussion, and voting (GEP - Groovy Enhancement Proposal) for core parts and less formal developer discussions and JIRA voting for additional parts.
Our goal has stayed the same, though: to give the Java developer a tool that makes him more productive, allows him to achieve his goals faster and with a smaller margin of error, and extend the scalability of the Java platform from full-blown enterprise projects to everyday "getting things done" tasks.
Thanks to its flexible syntax and its compile-time and runtime metaprogramming capabilities, Groovy is well known for its Domain-Specific Language capabilities. However, we felt that we could improve upon the syntax further by removing additional punctuation symbols when users chain method calls. This allows DSL implementors to develop command descriptions that read almost like natural sentences.
Before Groovy 1.8, we could omit parentheses around the arguments of a method call for top-level statements. But we couldn't chain method calls. The new "command chain" feature allows us to chain such parentheses-free method calls, requiring neither parentheses around arguments, nor dots between the chained calls. The general idea is that a call like
a b c d will actually be equivalent to
a(b).c(d). This also works with multiple arguments, closure arguments, and even named arguments. Furthermore, such command chains can also appear on the right-hand side of assignments. Let's have a look at some examples supported by this new syntax:
It is also possible to use methods in the chain which take no arguments, but in that case, the parentheses are needed:
If your command chain contains an odd number of elements, the chain will be composed of method / arguments, and will finish by a final property access:
This new command chain approach opens up interesting possibilities in terms of the much wider range of DSLs which can now be written in Groovy. This new feature has been developed thanks to the Google Summer of Code program, where our student, Lidia, helped us modify the Groovy Antlr grammar to extend top-level statements to accept that command chain syntax.
The above examples illustrate using a command chain based DSL but not how to create one. You will be able to find some further examples of "command chains" on the Groovy Web Console but to illustrate creating such a DSL, we will show just a couple of examples - first using maps and Closures:
Or if you prefer Japanese and a metaprogramming style (see here for more details):
As a second example, consider how you might write a DSL for simplifying one of your existing APIs. Maybe you need to put this code in front of customers, business analysts or testers who might be not hard-core Java developers. We'll use the
Splitter from the Google Guava libraries project as it already has a nice Fluent API. Here is how we might use it out of the box:
It reads fairly well for a Java developer but if that is not your target audience or you have many such statements to write, it could be considered a little verbose. Again, there are many options for writing a DSL. We'll keep it simple with Maps and Closures. We'll first write a helper method:
now instead of this line from our original example:
we can write this:
Groovy's flexible metaprogramming model involves numerous decision points when making method calls or accessing properties to determine whether any metaprogamming hooks are being utilized. During complex expression calculations, such decision points involved identical checks being executed numerous times. Recent performance improvements allow some of these checks to be bypassed during an expression calculation once certain initial assumptions have been checked. Basically if certain preconditions hold, some streamlining can take place.
Groovy 1.8.0 contains two main streams of optimization work:
Those two areas of optimization are only the beginning of further similar improvements. Upcoming versions of the Groovy 1.8.x branch will see more optimizations coming. In particular, primitive types other than integers should be expected to be supported shortly.
The GPars project offers developers new intuitive and safe ways to handle Java or Groovy tasks concurrently, asynchronously, and distributed by utilizing the power of the Java platform and the flexibility of the Groovy language. Groovy 1.8 now bundles GPars 0.11 in the libraries of the Groovy installation, so that you can leverage all the features of the library for
Fork/Join, Map/Filter/Reduce, DataFlow, Actors, Agents, and more with all the Groovy goodness.
Closures are a central and essential piece of the Groovy programming language and are used in various ways throughout the Groovy APIs. In Groovy 1.8, we introduce the ability to use closures as annotation parameters. Closures are also a key part of what gives Groovy its functional flavor.
In Java, there's a limited set of types you can use as annotation parameters (String, primitives, annotations, classes, and arrays of these). But in Groovy 1.8, we're going further and let you use closures as annotation parameters – which are actually transformed into a class parameter for compatibility reasons.
Closure annotation parameters open up some interesting possibilities for framework authors! As an example, the GContracts project, which brings the "Design by Contract" paradigm to Groovy makes heavy use of annotation parameters to allow preconditions, postconditions and invariants to be declared.
If you recall your math lessons, function composition may be a concept you're familiar with. And in turn, Closure composition is about that: the ability to compose Closures together to form a new Closure which chains the call of those Closures. Here's an example of composition in action:
To see more examples of Closure composition and reverse composition, please have a look at our test case.
When writing recursive algorithms, you may be getting the infamous stack overflow exceptions, as the stack starts to have a too high depth of recursive calls. An approach that helps in those situations is by using Closures and their new trampoline capability.
Closures are wrapped in a
TrampolineClosure. Upon calling, a trampolined Closure will call the original Closure waiting for its result. If the outcome of the call is another instance of a
TrampolineClosure, created perhaps as a result to a call to the
trampoline() method, the Closure will again be invoked. This repetitive invocation of returned trampolined Closures instances will continue until a value other than a trampolined Closure is returned. That value will become the final result of the trampoline. That way, calls are made serially, rather than filling the stack.
Here's an example of the use of
trampoline() to implement the factorial function:
Another improvement to Closures is the ability to memoize the outcome of previous (ideally side-effect free) invocations of your Closures. The return values for a given set of Closure parameter values are kept in a cache, for those memoized Closures. That way, if you have an expensive computation to make that takes seconds, you can put the return value in cache, so that the next execution with the same parameter will return the same result – again, we assume results of an invocation are the same given the same set of parameter values.
There are three forms of memoize functions:
memoize()which caches all the invocations
memoizeAtMost(max)call which caches a maximum number of invocations
memoizeAtLeast(min)call which keeps at least a certain number of invocation results
memoizeBetween(min, max)which keeps a range results (between a minimum and a maximum)
Let's illustrate that:
Currying improvements have also been backported to recent releases of Groovy 1.7, but it's worth outlining here for reference. Currying used to be done only from left to right, but it's also possible to do it from right to left, or from a given index, as the following examples demonstrate:
With the ubiquity of JSON as an interchange format for our applications, it is natural that Groovy added support for JSON, in a similar fashion as the support Groovy's always had with XML. So Groovy 1.8 introduces a JSON builder and parser.
JsonSlurper class allows you to parse JSON payloads, and access the nested Map and List data structures representing that content. JSON objects and arrays are indeed simply represented as Maps and Lists, giving you access to all the GPath expression benefits (subscript/property notation, find/findAll/each/inject/groupBy/etc.). Here's an example showing how to find all the recent commit messages on the Grails project:
If you want to see some more examples of the usage of the JSON parser, you can have a look at the JsonSlurper tests in our code base.
Parsing JSON data structures is one thing, but we should also be able to produce JSON content just like we create markup with the
MarkupBuilder. The following example:
Will create the JSON output:
You can find some more usages of the JSON builder in our JsonBuilder tests.
When given a JSON data structure, you may wish to pretty-print it, so that you can more easily inspect it, with a more friendly layout. So for instance, if you want to pretty print the result of the previous example, you could do:
Which would result in the following pretty-printed output:
The Groovy compiler reads the source code, builds an Abstract Syntax Tree (AST) from it, and then puts the AST into bytecode. With AST transformations, the programmer can hook into this process. A general description of this process, an exhaustive description of all available transformations, and a guide of how to write you own ones can be found for example in Groovy in Action, 2nd Edition (MEAP), chapter 9.
Below is a list of all new transformations that come with Groovy 1.8. They save you from writing repetitive code and help avoiding common errors.
You can annotate your classes with the @Log transformation to automatically inject a logger in your Groovy classes, under the
log property. Four kind of loggers are actually available:
Here's a sample usage of the @Log transformation:
You can change the name of the logger by specifying a different name, for instance with
Another particularity of these logger AST transformations is that they take care of wrapping and safe-guarding logger calls with the usual
isSomeLevelEnabled() calls. So when you write
log.info 'Car constructed', the generated code is actually equivalent to:
When defining variables in a script, those variables are actually local to the script's run method, so they are not accessible from other methods of the script. A usual approach to that problem has been to store variables in the binding, by not def'ining those variables and by just assigning them a value. Fortunately, the
@Field transformation provides a better alternative: by annotating your variables in your script with this annotation, the annotated variable will become a private field of the script class.
More concretely, you'll be able to do as follows:
The @PackageScope annotation can be placed on classes, methods or fields and is used for turning off Groovy's visibility conventions and reverting back to Java conventions. This ability is usually only needed when using 3rd party libraries which rely on the package scope visibility. When adding the
@PackageScope annotation to a field, Groovy will assign package scope access to the field rather than automatically treating it as a property (and adding setters/getters). Annotating a class or method with
@PackageScope will cause Groovy to revert to Java's convention of leaving the class/method as package scoped rather than automatically promoting it to public scope. The class variant can also take one or more parameters to allow nested setting of visibility of attributes within the class - see the Javadoc for more details. Recent releases of Groovy 1.7 have had a more limited version of this annotation.
@AutoClone annotation is placed on classes which you want to be
Cloneable. The annotation instructs the compiler to execute an AST transformation which adds a public
clone() method and adds
Cloneable to the classes implements list of interfaces. Because the JVM doesn't have a one-size-fits-all cloning strategy, several customizations exist for the cloning implementation:
clone()method will call
Cloneableproperty of the class. Example usage: Which will create a class of the following form:
Cloneableyou should set
style=COPY_CONSTRUCTORwhich will then use the copy constructor pattern.
Externalizableinterface, you might like to set
style=SERIALIZATIONwhich will then use serialization to do the cloning.
See the Javadoc for
AutoClone for further details.
@AutoExternalizable class annotation is used to assist in the creation of
Externalizable classes. The annotation instructs the compiler to execute an AST transformation which adds
readExternal() methods to a class and adds
Externalizable to the interfaces which the class implements. The
writeExternal() method writes each property (or field) for the class while the
readExternal() method will read each one back in the same order. Properties or fields marked as
transient are ignored. Example usage:
Which will create a class of the following form:
When integrating user-provided Groovy scripts and classes in your Java application, you may be worried about code that would eat all your CPU with infinite loops, or that call methods like
System.exit(0) (for the latter, check the section on compiler customizers, and particularly the
SecureASTCustomizer). It would be interesting to have a wait to control the execution of that Groovy code, to be able to interrupt its execution when the thread is interrupted, when a certain duration has elapsed, or when a certain condition is met (lack of resources, etc).
Groovy 1.8 introduces three transformations for those purposes, as we shall see in the following sections. By default, the three transformations add some checks in at the beginning of each method body, and each closure body, to check whether a condition of interruption is met or not.
Note that those transformations are local (triggered by an annotation). If you want to apply them transparently, so that the annotation doesn't show up, I encourage you to have a look at the
ASTTransformationCustomizer explained at the end of this article.
Cédric Champeau, our most recent Groovy committer, who implemented those features, has a very nice blog post covering those code interruption transformations.
You don't need to write checks in your scripts for whether the current thread of execution has been interrupted or not, by default, the transformation will add those checks for you for scripts and classes, at the beginning of each method body and closure body:
You can specify a
checkOnMethodStart annotation parameter (defaults to true) to customize where checks are added by the transformation (adds an interrupt check by default as the first statement of a method body). And you can also specify the
applyToAllClasses annotation parameter (default to true) if you want to specify whether only the current class or script should have this interruption logic applied or not.
@TimedInterrupt, you can interrupt the script after a certain amount of time:
In addition to the previous annotation parameters we mentioned for
@ThreadInterrupt, you should specify
value, the amount of time to wait, and
unit (defaulting to
TimeUnit.SECONDS) to specify the unit of time to be used.
An example of
@ConditionalInterrupt which leverages the closure annotation parameter feature, and the
@Field transformation as well:
You can imagine defining any kind of condition: on counters, on resource availability, on resource usage, and more.
Provides your classes with a default
toString() method which prints out the values of the class' properties (and optionally the property names and optionally fields). A basic example is here:
And here's another example using a few more options:
Provides your classes with
hashCode() methods based on the values of the class' properties (and optionally fields and optionally super class values for
Provides a tuple (ordered) constructor. For POGOs (plain old Groovy objects), this will be in addition to Groovy's default "named-arg" constructor.
Allows you to combine
@TupleConstructor. For those familiar with Groovy's
@Immutable transform, this provides similar features but for mutable objects.
@Canonical gives you vanilla versions for each of the combined annotations. If you want to use any of the special features that the individual annotations give you, simply include the individual annotation as well.
You will find a great write-up on @Canonical, @ToString, @EqualsAndHashCode and @TupleConstructor on John Prystash's weblog.
Sometimes, when you want to subclass certain classes, you also need to override all the constructors of the parent, even if only to call the super constructor. Such a case happens for instance when you define your own exceptions, you want your exceptions to also have the constructors taking messages and throwable as parameters. But instead of writing this kind of boilerplate code each time for your exceptions:
Simply use the @InheritConstructors transformation which takes care of overriding the base constructors for you:
Those two transformations, combined together, simplify the usage of
java.util.concurrent.locks.ReentrantReadWriteLock, are safer to use than the
synchronized keyword, and improve upon the
@Synchronized transformation with a more granular locking.
More concretely, with an example, the following:
Will generate code as follows:
If you annotate a Collection type field with @ListenerList, it generates everything that is needed to follow the bean event pattern. This is kind of an EventType independent version of what @Bindable is for PropertyChangeEvents.
This example shows the most basic usage of the @ListenerList annotation. The easiest way to use this annotation is to annotate a field of type List and give the List a generic type. In this example we use a List of type MyListener. MyListener is a one method interface that takes a MyEvent as a parameter. The following code is some sample source code showing the simplest scenario.
Groovy 1.9 will be the version which will align as much as possible with the upcoming JDK 7, so beyond those aspects already covered in Groovy (like strings in switch and others), most of those "Project Coin" proposals will be in 1.9, except the "diamond operator" which was added in 1.8, as explained in the following paragraph.
Java 7 will introduce the "diamond" operator in generics type information, so that you can avoid the usual repetition of the parameterized types. Groovy decided to adopt the notation before JDK 7 is actually released. So instead of writing:
You can "omit" the parameterized types and just use the pointy brackets, which now look like a diamond:
withDefault. So instead of writing code like below: Thanks to the new method (also backported to 1.7), you can write the example as follows:
Slashy strings are now multi-line:
This is particularly useful for multi-line regexs when using the regex free-spacing comment style (though you would still need to escape slashes):
A new string notation has been introduced: the "dollar slashy" string. This is a multi-line GString similar to the slashy string, but with slightly different escaping rules. You are no longer required to escape slash (with a preceding backslash) but you can use '$$' to escape a '$' or '$/' to escape a slash if needed. Here's an example of its usage:
This form of string is typically used when you wish to embed content that may naturally contains slashes or backslashes and you don't want to have to rework the content to include all of the necessary escaping. Some examples are shown below:
The compilation of Groovy code can be configured through the
CompilerConfiguration class, for example for setting the encoding of your sources, the base script class, the recompilation parameters, etc).
CompilerConfiguration now has a new option for setting compilation customizers (belonging to the
org.codehaus.groovy.control.customizers package). Those customizers allow to customize the compilation process in three ways:
ImportCustomizer: so you don't have to always add the same imports all over again
SecureASTCustomizer: by allowing/disallowing certain classes, or special AST nodes (Abstract Syntax Tree), filtering imports, you can secure your scripts to avoid malicious code or code that would go beyond the limits of what the code should be allowed to do.
ASTTransformationCustomizer: lets you apply transformations to all the class nodes of your compilation unit.
For example, if you want to apply the @Log transformation to all the classes and scripts, you could do:
This will log the two messages, the one from the script, and the one from the Car class constructor, through java.util.logging. No need to apply the @Log transformation manually to both the script and the class: the transformation is applied to all class nodes transparently. This mechanism can also be used for adding global transformations, just for the classes and scripts that you compile, instead of those global transformations being applied to all scripts and classes globally.
If you want to add some default imports (single import, static import, star import, star static imports, and also aliased imports and static imports), you can use the import customizer as follows:
When you want to evaluate Math expressions, you don't need anymore to use the
import static java.lang.Math.* star static import to import all the Math constants and static functions.
Given a String or a GString, you can coerce it to Enum values bearing the same name, as the sample below presents:
Maps now support
isCase(), so you can use maps in your switch/case statements, for instance:
When you need to specify a special grab resolver, for when the artifacts you need are not stored in Maven central, you could use:
Groovy 1.8 adds a shorter syntax as well:
@Grab annotation has numerous options. For example, to download the Apache commons-io library (where you wanted to set the
force attributes - not strictly needed for this example but see the Grab or Ivy documentation for details on what those attributes do) you could use a grab statement similar to below:
The compact form for grab which allows the artifact information to be represented as a string now supports specifying additional attributes. As an example, the following script will download the commons-io jar and the corresponding javadoc jar before using one of the commons-io methods.
rows methods in the
groovy.sql.Sql class now support paging. Here's an example:
Which will start at the second row and return a maximum of 2 rows. Here's an example result from a database containing numerous projects with their URLs:
When developing AST transformations, and particularly when using a visitor to navigate the AST nodes, it is sometimes tricky to keep track of information as you visit the tree, or if a combination of transforms need to be sharing some context. The
ASTNode base class features 4 methods to store node metadata:
public Object getNodeMetaData(Object key)
public void copyNodeMetaData(ASTNode other)
public void setNodeMetaData(Object key, Object value)
public void removeNodeMetaData(Object key)
GroovyDoc uses hard-coded templates to create the JavaDoc for your Groovy classes. Three templates are used: top-level templates, a package-level template, a class template. If you want to customize these templates, you can subclass the
Groovydoc Ant task and override the
getClassTemplates() methods pointing at your own templates. Then you can use your custom GroovyDoc Ant task in lieu of Groovy's original one.