The Groovy language, version 1.7, was recently released supporting refinements to the language itself as well as library enhancements. In short succession, SpringSource has announced the Groovy Eclipse IDE 2.0, which brings debugging, refined content-assist, and stub-less compilation to Eclipse's formerly poor Groovy support. This release brings with it a raft of updates to the core Groovy language and libraries. It debuts a syntax for Java-integration-friendly anonymous inner classes and nested classes. Anonymous inner classes are used in Java where closures or method delegates might be used in other languages, as they have been in Groovy. These new features make it easier to integrate with libraries in Java that use anonymous inner classes (and can't be made to work using closures). This is an improvement over having to write a class any time an anonymous inner class is needed and can help keep the code more self-documenting. The implementations, it's warned, are not strictly compatible with the Java implementation.
One irksome aspect of anonymous inner classes in Java requires that variables in the containing scope that are accessed from inside an anonymous inner class need to be final. This restriction is lifted in Groovy; you can change the values of variables in a containing scope from within an anonymous inner class.
To best illustrate this, let's work through an example, both in Java and in Groovy. This example is taken (roughly) from the release notes. First, the Java version:
int counter = 0 ; final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { counter+=1; } },0);
In the example, we create a Timer object in Java and then attempt to create a TimerTask
, which will run and – we hope – update an integer. Unfortunately, this doesn't compile (much less work). The counter
variable is not final. The compiler won't let us access it. So, we make it final:
final int counter = 0 ; final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { counter+=1; // compiler error! } },0);
Now we can access it (i.e., read it) but we can't update it because the variable is final; another compiler error! So, we try something “cute” like wrapping the integer in an object. We might try using java.lang.Integer
, but it is not mutable, and as the variable would also have to be final, you would have no way to reset the variable. So, you try something else. You could use a java.lang.ThreadLocal
to store the Integer and update it. You might also try using a java.util.concurrent.atomic.AtomicInteger
.
final AtomicInteger atomicIntegerCounter = new AtomicInteger(0); final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { atomicIntegerCounter.incrementAndGet(); } }, 0);
This works, but at what cost? You've complicated a very simple construct with threading-related imports and (in addition) forced awareness of threading on the user of this code.
Now, let's look at how we might do this using Groovy:
int counter = 0 Timer timer = new Timer() timer.schedule(new TimerTask() { void run() { counter += 1 } }, 0)
The code runs as expected, no compiler errors or issues and – most usefully – the code is self-documenting: the intention is clear.
The new iteration also supports inner classes. The recommended approach is to use static inner classes, if you must use an inner class at all. Accessing values from containing scopes using inner classes is slightly different than in Java. In Java, inner classes are given an implicit reference to the containing class as a synthetic parameter to the constructor. This is an implementation detail, and you can simply refer to variables in the containing class as though they were values in the current class. In Groovy, you must pass in the reference explicitly; you don't need to code this constructor, just use it when instantiating the inner class from within the outer class.
Groovy sports support for the use of annotations on a wider set of language elements than Java. While Groovy's annotation support has long since been on par with Java 5's support for annotations, the Groovy 1.7 release takes it even further with support for annotations on import statements, package declarations, and on variable declarations.
The placement of annotations on import statements may not seem an obvious use case until you consider Grape (The Groovy Adaptable Packaging Engine or Groovy Advanced Packaging Engine). Grape is like an enhanced, code-level implementation of Maven or Ivy. Other build systems externalize dependencies in build artifacts (such as a Maven pom.xml
, or an Ant build.xml
file). Grape lets you annotate code with the dependency. This in turn triggers the download of the dependency and makes your code's build more self-documenting. In previous Groovy iterations, using annotations was an awkward task: the annotations were only permitted where Java 5 annotations were permitted (classes or methods, for example) and not where they might seem more natural (on import statements, for example).
The update includes more expressive assertions, compile time meta programming with the abstract syntax tree (AST) of the language itself (to achieve things you might otherwise only be able to achieve in Java using a byte code manipulation library), and upgrades to the Groovy Sql
class to support batch updates and transactions.
Grails 1.2 was concurrently released with Groovy 1.7. Grails is a web framework that uses the Groovy language on top of existing, popular open-source components like Spring MVC and Hibernate to enable a RAD, Ruby on Rails-like development environment. It has seen tremendous growth in recent years. The latest release is the first release to enjoy this tight a collaboration between the SpringSource, Tomcat, and SpringSource Tool Suite teams.
The new version features tighter support for, and integration with, Spring (including the use of Spring MVC @Controller
annotations), named query support in the Groovy Object Relational Mapping (GORM, an ORM solution built on top of Hibernate) tool, pluggable web containers for development (with out-of-the-box support for Jetty and Tomcat), and markedly improved performance / memory consumption in Grails' view layer technology (Groovy Server Pages). The release announcement cites 2-3 times increased throughput. Grails too supports dependency management, no matter which version of Groovy you're using, with an Ivy-based mechanism for automatically downloading dependencies. This support is made available with a domain specific language for declaring dependencies.
InfoQ did an interview with Guillaume Laforge and Graeme Rocher - the Groovy and Grails leads - about the then impending Groovy 1.7 and Grails 1.2 releases in December.
The Groovy language, and surrounding ecosystem, have benefited from the November 2008 SpringSource acquisition of G2One. While the momentum behind the language has always remained steady, there was a void in the tooling support. Eclipse, in particular, had no good support for the language. The Groovy Eclipse IDE 2.0 release changes this. While the tool suite doesn't yet have support for the recently released Groovy 1.7 compiler versions, it does sport a debugger and compatibility with Eclipse 3.5. The plugin now supports a more responsive content-assist feature, a stub-less compiler, incremental joint compilation (supporting compilation of Java code in Groovy projects, for example) mechanism, cross language refactoring, and more. All these new features are built on an almost entirely rewritten Eclipse plugin foundation. To find out more about the release, visit the SpringSource release announcement.