Improved tooling support
A common show-stopper when Groovy was a young language, was the lack
of good tooling support: both the tool chain and the IDE support
weren't up to the task. Fortunately, with the maturity and success of
Groovy and the Grails web framework, this situation has changed.
Introduction of the "joint" compiler
Groovy is well-known for its transparent and seamless integration
with Java. But this is not just about being able to call Java methods
from Groovy scripts, no, the integration between both languages goes
well beyond that. For instance, it is totally possible to have a Groovy
class extending a Java class which in turns implements a Groovy
interface, or vice versa. This is something other alternative languages
don't alway support, unfortunately. However, when mixing Groovy and
Java classes together, so far, you had to be careful when compiling
both type of classes by cleverly choosing the order of compilation, and
when cyclic dependencies were spanning both languages, you may have hit
a "chicken and egg" problem. Fortunately with Groovy 1.5, this is not
the case anymore, and thanks to a contribution from JetBrains, the
makers of the award winning Java IDE IntelliJ IDEA,
a "joint" compiler is available with which you can compile both Groovy
and Java sources together in one go without having to think about
dependencies between classes.
If you want to use the joint compiler from the command-line, you can
call the groovyc command as usual, but specify the -j flag which will
enable the joint compilation:
groovyc *.groovy *.java -j -Jsource=1.4 -Jtarget=1.4
For passing parameters to the underlying javac command, you can
prefix the flags with the J prefix. You can also use the joint compiler
through its Ant task from you Ant or Maven build files:
<taskdef name="groovyc"
classname="org.codehaus.groovy.ant.Groovyc"
classpathref="my.classpath"/>
<groovyc
srcdir="${mainSourceDirectory}"
destdir="${mainClassesDirectory}"
classpathref="my.classpath"
jointCompilationOptions="-j -Jsource=1.4 -Jtarget=1.4" />
Maven plugin for Groovy
For the Maven users, there is also a fully featured Maven plugin
hosted at Codehaus which allows you to build your Java / Groovy
applications: compile your Groovy and Java code, generate documentation
from the JavaDoc tags, or it even lets you write your own Maven plugins
in Groovy. There is also a Maven archetype to bootstrap your Groovy
project more rapidly. For more information, you may have a look at the
documentation of the plugin: http://mojo.codehaus.org/groovy/index.html
The GroovyDoc documentation tool
As a Java developer, you are used to documenting your code through
JavaDoc tags in the comments of your classes, interfaces, fields, or
methods. In Groovy, you can also use such tags in your comments, and
have them being used by a tool called GroovyDoc to generate the
equivalent JavaDoc documentation for all your Groovy classes.
There's an Ant task you can define then use to generate the documentation as follows:
<taskdef name="groovydoc"
classname="org.codehaus.groovy.ant.Groovydoc">
<classpath>
<path path="${mainClassesDirectory}"/>
<path refid="compilePath"/>
</classpath>
</taskdef>
<groovydoc
destdir="${docsDirectory}/gapi"
sourcepath="${mainSourceDirectory}"
packagenames="**.*" use="true"
windowtitle="Groovydoc" private="false"/>
New interactive shell and the Swing console
Groovy distributions always contained two different shells: a
command-line shell as well as a Swing console. Groovysh, the
command-line shell, has never been very friendly in terms of
interactions with its user: whenever you wanted to execute a statement,
you had to type 'go' or 'execute' after each one, so that it got
executed. For quick prototyping or playing with some new API, typing
'go' each time was very cumbersome. The situation has changed in Groovy
1.5, since a new interactive shell is born. No need to type 'go'
anymore.
This new shell features several enhancements, such as the use of the
JLine library which provides ANSI coloring, tab completion for
commands, line editing capabilities. You can work with different script
buffers, remember already imported classes, load existing scripts, save
the current script to a file, browse the history, etc. For detailed
explanations of the supported features, please have a look at the documentation.
The command-line shell isn't the only one that received some care,
the Swing console has also been improved, with a new toolbar, with
advanced undo capabilities, the possibility to increase or decrease the
font size, syntax highlighting. A lot of polishing has been applied to
the console.
IntelliJ IDEA JetGroovy plugin
I will save the best of tooling support till the end of this section
by mentioning the JetGroovy plugin: a free and Open Source IntelliJ
IDEA plugin dedicated to the support of both Groovy and Grails. This
plugin has been developed by JetBrains themselves, and provides
unmatched support for both the language and the web framework.
To list a few of the available features of the Groovy support:
- Syntax highlighting for all the syntax,
plus different warnings for types not recognized, or when static type
information is not known to help spot potential errors.
- Ability to run Groovy classes, scripts and JUnit test cases written in Groovy.
- Debugger: You can debug step by step across your Java and Groovy code, set breakpoints, show variables, the current stack, etc.
- Joint compiler: the compiler compiles both Groovy and Java classes together and is able to resolve dependencies between both languages.
- Code completion for packages, classes, properties, fields, variables, methods, keywords, and even specific support for the Swing UI builder.
- Advanced class search and find usage.
- Refactorings:
most of the usual refactorings you've come to love in Java are
available as well and work across Java and Groovy, like "surround
with", introduce, inline or rename a variable, renaming for packages,
classes, methods, and fields.
- Imports optimizations and code formatting.
- Structure view: to have a bird's eye view of your classes.
At the end of the day, you won't even notice whether you're
developing a class in Groovy or in Java, considering the level of
interplay and support offered inside IntelliJ IDEA. This is definitely
a plugin to install if you're considering adding some dose of Groovy in
your Java project, or if you plan to develop Grails applications.
More information can be found on JetBrains website.
Although I'm only mentioning the plugin for IntelliJ IDEA, for your
Groovy developments, you don't have to change your habits. You can also
use the Eclipse plugin which is regularly improved by the IBM Project
Zero developers, or Sun's brand new support of Groovy and Grails in NetBeans.
Performance improvements
Along with new features, this new release of Groovy brings
noticeable performance improvements as well as lower memory
consumption, compared to previous versions. In our informal benchmarks
measuring the duration of all our test suites, we noticed speed
improvements between 15% to 45% compared with our beta versions of
Groovy 1.5 - and certainly higher figures can be expected by comparing
with the now old Groovy 1.0. More formal benchmarks have yet to be
developed, but those figures have also been confirmed by developers
from an insurance company that is using Groovy to write the business
rules of their policy risk calculation engine, and from another company
who ran several tests on highly parallel machines. Overall, Groovy 1.5
should be faster and leaner in most situations. Your mileage may vary
depending on your own context of usage of Groovy.
Enhanced dynamic capabilities
Through the symbiotic relationships between the Groovy and Grails
projects, new dynamic capabilities have been introduced in Groovy,
after having matured in the heart of Grails.
Groovy is a dynamic language: put simply, it means that certain
things like method dispatch happens at runtime, instead of at
compile-time as it is the case of Java and other languages. There is a
specific runtime system, called the MOP (stands for Meta-Object
Protocol) that is responsible for the dispatching logic. Fortunately,
this runtime system is open enough so that people can hook into the
system and change its usual behavior. For each Java class and for each
Groovy instance, there is an associated meta-class which represents
this runtime behavior of your objects. Groovy offered various ways to
interact with the MOP by defining custom meta-classes by extending some
base class, but thanks to the contribution from the Grails project, a
groovier kind of meta-class is available: the expando meta-class.
Again,code samples are easier to help us understand the concept. In
the following example, the msg String instance has got a meta-class
that we can access through the metaClass property. Then we change the
meta-class of the String class to add a new method called up to the String class, to have a shortcut notation for the toUpperCase()
method. To do so, we assign a closure to the up property of the
meta-class which is created as we assign it the closure. This closure
takes no argument (hence why it starts with an arrow), and we call the toUpperCase()
method on the delegate of the closure, which is a special closure
variable which represents the real object (here the String instance).
def msg = "Hello!"
println msg.metaClass
String.metaClass.up = { -> delegate.toUpperCase() }
assert "HELLO!" == msg.up()
Through this meta-class, you can query the methods and/or properties which are available:
// print all the methods
obj.metaClass.methods.each { println it.name }
// print all the properties
obj.metaClass.properties.each { println it.name }
You can even check that a certain method or property is available, with a finer granularity than through any instanceof check:
def msg = 'Hello!'
if (msg.metaClass.respondsTo(msg, 'toUpperCase')) {
println msg.toUpperCase()
}
if (msg.metaClass.hasProperty(msg, 'bytes')) {
println foo.bytes.encodeBase64()
}
These mechanisms are extensively used in the Grails web framework
for instance to create dynamic finders: no need for DAOs in most
circumstances, as you are able to call a findByTitle()
dynamic method on a Book domain class. Through meta-classes, Grails
automatically decorates the domain classes with such methods.
Furthermore, if the method doesn't exist yet, it will be created and
cached on first use. This can be accomplished by other advanced hooks
as explained below.
Beyond those examples we've seen so far, expando meta-classes also
provide some complementary hooks. Four other kind of methods can be
added to an expando meta-class:
- invokeMethod() lets you intercept all methods calls,
- while methodMissing() will be called on last resort only of no other method is found.
- get/setProperty() intercepts access to all properties,
- whereas propertyMissing() is called when no property can be found.
With expando meta-classes, customizing the behavior of the types of
your application becomes easier and can save precious time of
development compared with the previous version of Groovy. Obviously,
not everybody needs to use those techniques, but they can be handy in a
number of situations where you want to apply some AOP (Aspect Oriented
Techniques) to decorate your classes, and when you want to simplify and
make more readable the business code of your application, by removing
some unnecessary boiler-plate code.
Swing on steroids
The Groovy project has the chance to have a team of talented Swing
developers who worked hard to enhance the capabilities of Groovy to
build user interfaces in Swing. The basic brick for building Swing UIs
in Groovy is the SwingBuilder class: at a syntactical level in your
source, you can visually see how Swing components are nested within
each other. A simplistic example from the Groovy website shows how to
simply create a little GUI:
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
def swing = new SwingBuilder()
count = 0
def textlabel
def frame = swing.frame(title:'Frame', size:[300,300]) {
borderLayout()
textlabel = label(text:"Clicked ${count} time(s).",
constraints: BL.NORTH)
button(text:'Click Me',
actionPerformed: {count++; textlabel.text =
"Clicked ${count} time(s)."; println "clicked"},
constraints:BorderLayout.SOUTH)
}
frame.pack()
frame.show()
In the novelties, the Swing builder concept has been extend to
provide custom component factories. There are additional modules, not
bundled with Groovy by default, which integrates the Swing components
from JIDE or from the SwingX project into the usual Swing builder code.
Although this topic would deserve a full article, I'm only going to
list some of the other improvements in this release, for instance, the
bind() method. Inspired by the beans binding JSR (JSR-295), you can
easily bind components or beans together to have them react upon
changes made on each other. In the following example, the size of the
insets of the button will be changed according to the value of the
slider component:
import groovy.swing.SwingBuilder
import java.awt.Insets
swing = new SwingBuilder()
frame = swing.frame {
vbox {
slider(id: 'slider', value:5)
button('Big Button?!', margin:
bind(source: slider,
sourceProperty:'value',
converter: { [it, it, it, it] as Insets }))
}
}
frame.pack()
frame.size = [frame.width + 200, frame.height + 200]
frame.show()
Binding components together is such a common task when building user
interfaces, that this task has been simplified through this binding
mechanism. There are also some other automatic binding options that can
be used, but again, a dedicated article would probably be better.
In other new and noteworthy features, a few handy new methods have
been added which leverage closures to call the infamous SwingUtilities
class, and to start new threads: edt() will call invokeAndWait(), while doLater() will call invokeLater(), and doOutside()
will just launch a closure in a new thread. No more ugly anonymous
inner classes: just use closures through those shortcut methods!
Last but not least, separating the description of the view and its
associated behavior logic has never been easier, thanks to the build()
method on SwingBuilder. You can create a separate script which only
contains the view, while the interactions or bindings between
components are in the main class, making a clearer separation in the
MVC model.