Getting to Know Groovy

   
By John Zukowski, May 17, 2005  

Groovy. No, this isn't a review of the latest Austin Powers movie. Instead, it is about an evolving new language for the Java 2 platform. Yes, new language. The Java platform is that, a platform, not just a programming language. What Sun Microsystems provides is a complete platform: a programming language, a core set of libraries, and a runtime environment, where the last bit is also known as the Java virtual machine 1 or JVM. The instruction set of the JVM is a set of operational codes or opcodes as defined by the Java Virtual Machine Specification. The virtual machine doesn't care what programming language those opcodes started as, as long as what the JVM sees is the appropriate opcodes. And, that's where Groovy comes in. Through JSR 241, the Java Community Process is helping to standardize a new language for the Java platform. According to Richard Monson-Haefel, a Sr. Analyst of Burton Group and former specification leader, "The Java programming language is excellent for large complex systems, but it can be overkill when it comes to small jobs." And, that's what Groovy offers, a scripting language that runs natively on the JVM and works with Java objects, APIs, and tools.

According to James Strachan, expert group lead and Groovy co-founder (with Bob McWhirter), Groovy started with a desire for "an alternative to javac, which had the power and expressiveness of Ruby/Python but generated regular Java classes (at runtime or build time) and that worked directly with Java classes without some other layer. So I wanted a Groovy object to descend from java.lang.Object, with collections being java.util.Collection, lists being java.util.List, support for Java arrays, Java beans, and for all the APIs in the system to be based on Java 2 Platform, Standard Edition (J2SE) and Java 2 Platform, Enterprise Edition (J2EE)."

Getting Started

Enough about the origins for now, let's learn how to get started with the new language. The Groovy project is housed at the open-source project repository, Codehaus. To get started, grab the latest binary distribution by following the Download link. You'll need to unpack the .zip or .tar.gz file. Groovy programs will run under both J2SE versions 1.4 and 5.0, but don't expect the extra language features like generics in the latter case.

After unpacking, you need to configure your environment. First, set the GROOVY_HOME environment variable to the directory where you unpacked things.

Under Microsoft Windows, that command is:

set GROOVY_HOME=c:\groovy-1.0-beta-9

replacing groovy-1.0-beta-9 with the proper location.

Next, add [GROOVY_HOME]\bin to your PATH environment variable:

set PATH=%PATH%;%GROOVY_HOME%\bin
 

For Linux Korn shell users, comparable commands are as follows:

export GROOVY_HOME=/home/groovy/groovy-1.0-beta-9
PATH=$PATH:$GROOVY_HOME/bin
 

If the scripts don't have their execute permission set properly, you'll need to add in one extra command:

chmod +x $GROOVY_HOME/bin/*
 

And, finally, check to see if your JAVA_HOME environment variable is set to your current JDK installation directory. For many people, this will be already set, as it is a standard variable used by other Java development tools.

If you've done everything correctly, at this point if you type the 'groovysh' command, you'll start up the Groovy Shell:

groovysh


Lets get Groovy!
================
Version: 1.0-beta-9 JVM: 1.4.2_06-b03
Type 'exit' to terminate the shell
Type 'help' for command help
Type 'go' to execute the statements
 

From here, you can type Groovy commands. After entering the statements, you would type 'go' to execute the statements. For instance, enter the statement 'println "Hello, World"' (without the single quotes) followed by the word go. Notice that the quoted string is repeated.

groovy> println "Hello, World"
groovy> go
Hello, World
 

You can also place Groovy statements in a script file and run them with the groovy command, instead of groovysh. If the hello.groovy file contains:

 println "Hello, World"
 

Then, you could run it with 'groovy hello.groovy' to get the following:

 Hello, World
 

The groovy command is itself a shell script, configuring the necessary command-line options for your platform. There is also groovyConsole which gives you a graphical way to execute Groovy statements.

 
Why Bother With Groovy?

A common question when someone first hears about Groovy is, why bother with another scripting language for the Java platform? Aren't languages like Ruby and Python sufficient? If you know those languages and are comfortable with them, then by all means use them. But, when you modify these to work with the Java platform, you get variants like JRuby and Jython. The area that Groovy is going after are the Java developers who wants to stick to a Java-centric syntax for their scripting needs, typically while prototyping or testing. Not only do you get a Java-centric syntax, though, but you also get Java-centric semantics. The object model, in particular, is based squarely on that of the Java platform's, not imported from another scripting language and force-fitted into the Java VM. To demonstrate, a Groovy script that checks a java.util.List for all words that contains an 'a' is relatively short.

aList = ["Jim", "Joan", "James"]
aWords = aList.findAll { it.contains("a") }
aWords.each { println it }
 

A comparable Java class would be considerably larger.

import java.util.*;

public class AStrings {
 public static void main(String args[]) {
   List<string> aList = new ArrayList<string>();
   aList.add("Jim");
   aList.add("Joan");
   aList.add("James");

   List<string> aWords = new ArrayList<string>();
   for (String item : aList) {
     if (item.contains("a")) {
       aWords.add(item);
     }
   }
   for (String item : aWords) {
     System.out.println(item);
   }
 }
}
 

This isn't meant to show that less is necessarily better, but, when prototyping or writing test cases, sometimes the Java programming language isn't always the most convenient choice. Hence why so many different scripting options have shown up.

According to Strachan, "languages like Jython, JRuby, and Rhino are ports of other languages to the JVM, which means they end up not being real Java objects. They are in a kind of different universe, where native Ruby/Python/JavaScript objects are in one world and real Java objects are in another world and there's a bridge between the two with wrappers. When you use JRuby/Jython, the idea is to port Ruby/Python code so it runs on the JVM. I didn't really want that, I wanted just some power and expressiveness for working inside the JVM with existing Java APIs in a clean way, but also in a way that was 'Java-like' in that, clearly it is different from the Java programming language. But, it shouldn't have too many differences, so that it is pretty easy for Java developers to pick up and use."

 
JSR 241 Update

About a year ago in March 2004, JSR 241 was born. With a unanimous vote of 16-0, the JSR passed the initial hurdle of the Java Community Process and an Expert Group was formed. With origins in the original Groovy language definition, the group has been updating the language, reimplementing the parser, and pounding away to form a solid release candidate. According to the Roadmap, it looks like we're at least six months away from a reference implementation. However, the first JSR version of Groovy was made available April 6, 2005.

James Strachan describes the whole JSR process as a difficult but worthwhile endeavor:

"We started the Groovy JSR to try get as much feedback and ideas on Groovy as possible so folks could poke holes in Groovy, find the smelly parts and help fix it up so we had a great, powerful, expressive scripting language for the JVM that was very easy to read (we read more code than we write) and use. Languages are very personal, subjective things and so someone is always going to dislike any choice you make. (Indeed, folks seem to openly discuss their dislikes more than their likes). You've only got to have a discussion on { } bracket placement, indentations and whitespace use in most large teams and all-out war breaks out. So forming consensus is pretty hard. Also many people want quite different things. I've always said that I wanted something with the easy-to-read and expressiveness of Ruby/Python for the JVM. Others have very different ideas; some wanting something like Perl, others like JavaScript, some wanting something very much like Java but with one or two minor bits of syntax sugar, so balancing those different views is quite hard. Also the JSR has slowed down Groovy progress by a fair amount; it takes a lot of time to mull stuff over. These are hard choices. We've various avenues for discussions; public mail lists, IRC (where the core team tend to hang out and have high-bandwidth chats), on the JSR and Groovy wikis and occasionally in person at conferences or the 2 day JSR conference we had last November. It's quite hard, for volunteers, to disseminate information, maintain the open source project, document on the wiki and create the TCK. This has also lead to lots of frustration among the Groovy JSR and developer community both on the progress of the project and the documentation of the JSR. However, we're starting to get over the top of the hill now, and we should have the first EA release of the JSR version of Groovy this month, so hopefully those frustrations should start to go away soon. Its also worth saying that the time taken, and the JSR process, have made a massive difference to the cleanliness, simplicity and semantics of the language - Groovy is all the better for it. I'm certainly really looking forward to getting 1.0 done and delivered, so we can start thinking of 2.0."

For those who had time to play with Groovy before, the syntax coming out of the JSR is slightly different. See the Migration From Classic to JSR syntax document for assistance.

 
Groovy Features

While you learned how to get started with Groovy before, let us take a deeper look into what Groovy offers and how to use it to its full advantage. From a language perspective, the feature set looks like when "Java" was first announced back in 1995, a list of the latest buzz-words of the day:

  • Agile
  • Static and dynamic typing
  • Native syntax for lists, maps, arrays, and JavaBeans
  • Closures
  • Regular Expressions (regex)
  • Operator overloading
  • Autoboxing and polymorphism across lists, arrays, maps, JavaBean components, and iterators

When people say something is agile, they typically mean quick and nimble. For Groovy, its agility is its rapid prototyping model and in its flexibility at building shorthand notations for common Java operations.

As far as static and dynamic typing goes, Groovy variables aren't required to be typed, or, can change types as a program evolves. In the following example, the "name" variable starts out as a java.lang.String, and ends as a java.lang.Integer. Primitives in Groovy are treated as objects, so the number 4 is an Integer, not an int, which is the autoboxing feature of Groovy.

 name = "John"
 println "Name: " + name
 println name.class

 name = 4
 println "Name: " + name
 println name.class

Output:

 Name: John
 class java.lang.String
 Name: 4
 class java.lang.Integer
 

Groovy includes built-in support for list, map, array, and JavaBean components. As shown in the early example, a List (or array) is represented by an enclosed set of square brackets:

 aList = ["Jim", "Joan", "James"]
 

Maps work the same way with key-value pairs separated by colons:

 ['Red Sox':4, 'Cardinals':0]
 

JavaBean component support allows one to access a bean property by name, instead of explicitly specifying the getter method name. The java.util.List class has an isEmpty method (empty JavaBeans property). Thus, you can access its value as shown here:

println aList.empty
 

A more interesting one is the use of the Date class, which has methods like getHours and getMinutes to get the time.

i = new java.util.Date();
println "The time is ${i.hours}:${i.minutes}"
 

Notice the string substitution that automatically happens for you with Groovy.

Closures are Groovy's answer to methods. In a way, they are similar to anonymous inner classes.

 method = { |name| println "Hello, ${name}." }
 method("Jill")
 method("Ed")
 

For output, this displays:

 Hello, Jill.
 Hello, Ed.
 

Regular expression support seems to be everywhere today, including as part of the standard Java libraries. Instead of accessing that library directly, you can use the matching mechanism in Groovy. A statement like the following would report true:

 println("foo" ==~ "f.*")
 

Even though the Java programming language doesn't support operator overloading, Groovy does. By defining magically named methods, you get support for this behavior with your own classes:

* a + b     --- a.plus(b)
* a - b     --- a.minus(b)
* a++ / ++a ---         a.next()
* a[b]      --- a.getAt(b)
* a[b] = c  --- a.putAt(b, c)
* a == b    --- a.equals(b)
* a === b   --- a == b
* a <=> b   --- a.compareTo(b)
* a << b    --- a.leftShift(b)
 

Finally, there's autoboxing and polymorphism. Here, the autoboxing was already mentioned. And, indirectly, polymorphism, as object types can be determined at runtime. Another aspect of autoboxing and polymorphism can be demonstrated with the iteration and looping support offered. Even with different types, you get similar behavior:

 for (i in 1..10) {println i}
 for (ch in "string") {println ch}
 for (entry in ['Red Sox':4, 'Cardinals':0])
   {println "${entry.key} = ${entry.value}" }
 

The results of which follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 s
 t
 r
 i
 n
 g
 Cardinals = 0
 Red Sox = 4
 

Notice that the map returned the results in an order other than originally presented. This is the typical behavior of a HashMap.

For a more complete look at the language, the Groovy User Guide should help.

 
Groovy Does Swing

While Groovy is good at non-graphical programs, you can also build rich Swing User Interfaces, with minimal effort. Through the help of the groovy.swing.SwingBuilder class, you can package up your test screens very easily. The following example offers a frame with a menu bar offering a File menu with Exit under it. The screen itself includes a label with tool tip text, an input field, and a selectable button. Both the menu item and button respond to selection.

import java.awt.BorderLayout
swing = new groovy.swing.SwingBuilder()
myFrame = swing.frame(title: 'Sample Frame',    location:[100,100], size:[300,200]) {
 menuBar {
   menu(text: 'File') {
     menuItem(text: 'Exit', actionPerformed:{System.exit(0)})
   }  }
 panel(layout: new BorderLayout()) {
   label(text: 'Input:', constraints: BorderLayout.WEST,
     toolTipText: 'Tool Tip')
   textField(constraints: BorderLayout.CENTER)
   button(text: 'Hello', constraints: BorderLayout.SOUTH,
     actionPerformed:{println("World")})
 }
}
myFrame.visible = true
 
 

The way this works is primarily through the JavaBean properties. In this snippet of the above code, the text and toolTipText properties of the JLabel are configured. The constraints attribute is passed along for when the component is added to the container.

   label(text: 'Input:', constraints: BorderLayout.WEST,
     toolTipText: 'Tool Tip')
 
 
Summary

Scripting languages for the Java platform seem to appear every once in a while. How long they last one can never know, until they've been around for awhile. Whether Groovy will survive, only time will tell. By going through the JSR submission process, one can only hope that this will help give it some legs, once it gets to completion. Probably the biggest weak area with Groovy is with tool support, or lack thereof. While in the past there were plugins for IntelliJ, they no longer work with the 4.5 version of the IDE. There is a plug-in for Eclipse, but none for NetBeans (yet). And error messages from the parser are cruel to try to debug with. Hopefully, once the JSR matures, performance will improve, too. The nice thing about the whole project is it is open source, so if you want to, you can dig into the source code and fix problems yourself, or at least see how the different tasks are done.

If you're in the market for scripting test cases, connecting web services, or just for quickie throwaway applications that glue preexisting components, libraries, and tools together, you can do that quickly with Groovy. You get binary compatibility with the JVM and can reuse the entire set of standard Java platform libraries. Overall, Groovy is an easy way for the Java developer to jump into the scripting game, without learning a whole new new set of APIs.

 
Resources

Groovy Home

Groovy Roadmap

Groovy User Guide

JSR 241

Groovy Review at TheServerSide.com

Virtual Machine Specification

 



1 As used on this web site, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.
 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.