ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button
Java Cookbook, 2nd Edition

Groovy, Java's New Scripting Language

by Ian F. Darwin, author of Java Cookbook, 2nd Edition
09/29/2004

When some Java developers hear about Groovy, their first reaction often is, as mine was, "Oh, no, not another scripting language for Java." We already have, after all, JavaScript and Rhino, Jython, Jelly, BeanShell, JRuby, Tcl/Java, Sleep, ObjectScript, Pnuts, Judoscript, the Bean Scripting Framework (BSF)--which gives access to Perl, TK/Tcl, and more--and many others. But other developers have been hoping for a scripting language with the power of Perl, Python, or Ruby but without having to re-learn everything from the ground up. Whichever camp you're in, I hope to show you enough of Groovy in this article that you will be interested to try it and judge for yourself.

Why Groovy?

Why would Bob McWhirter and James Strachan create a new scripting language? Why would they call it Groovy? More importantly, what features would enable Groovy to succeed when others are already entrenched? Let's answer the third question with a look at Groovy's features.

When scripting languages that started elsewhere come to Java, they tend to bring a lot of their own API with them rather than using the "standard" (to us) Java API. Groovy is not guilty here--it provides very little special-purpose API; the entirety of the standard Java API is given to you in Groovy as it is in Java, and any third-party Java can be made available just by putting it in your CLASSPATH.

Quoting the Groovy FAQ:

Think of Groovy as a Ruby- or Python-like language that is tightly integrated with the Java platform (as opposed to the Unix/Posix command shell and C-libraries), allowing you the same powerful and concise coding syntax as Ruby or Python, but allowing you to stay on the JVM and protect your investment in J2SE, J2EE, and all the plethora of great useful Java code out there without any adapter layers or parallel API sets ...

Foreign scripting languages tend to have their own special syntax, based on what the original developers liked. Groovy is peachy here, too, because its syntax is based on Java's, with just a spoonful of syntactic sugar to help the medicine go down. For example, instead of having to write:

value = object.getItemCount();

you can just write:

value = object.itemCount

In other words, objects in Groovy are treated as JavaBeans, and setters/getters result in accessible properties. Because Groovy is generally much less restrictive than Java about declarations, most variables in Java can be assigned without declaring them, although at present you can't use the += operator on something that doesn't have a value.

In fact, you can create bean classes in Groovy without having to write accessors, as shown in the person.groovy example below. Groovy statements don't need to have a class statement and named methods if they are self-contained; but if you want to define one or more classes you can, and classes can have method definitions.

Example 1. person.groovy

class Person {
	firstName
	lastName
	address1
	city
	province
	postcode
}

p = new Person(firstName:'Ian', lastName:'Darwin', province:'Ontario')

println "Hello ${p.firstName} ${p.lastName}"

Related Reading

Java Cookbook
By Ian F. Darwin

Another bit of syntactic sugar is that semicolons are optional at the end of statements. You may, as I do, put them in out of habit and because it's easier to be consistent. But the Groovy language isn't Java, and if you want to leave off your semicolons, you can. And before you start denigrating "syntactic sugar," remember that J2SE 1.5 ("Java 5") provides auto-boxing and auto-unboxing, which automatically converts between primitives like ints and, whenever needed, their object-wrapper equivalents (like Integer). (Chapter 8 of my book, Java Cookbook, 2nd Edition, covers this and other new-in-1.5 features such as Generics; you can download this chapter from the book's catalog page.)

A third problem with some scripting languages has been performance, though this has become less of an issue as computers get faster. Somebody once wrote that software expands to use up all available increases in computing resources, and that doesn't seem far off the mark when you look at modern commercial operating systems and applications. Groovy wins here, too, because Groovy scripts can be compiled into .class files. These files are indistinguishable from those produced by javac or an IDE, and can therefore take advantage of speed improvements in, for example, Sun's HotSpot optimizing-Just-In-Time JVM.

Well, indistinguishable syntactically; they are well-formed Java bytecode files. That does not mean that you can compile any Groovy script into a standalone Java program--the Groovy runtime is required on your classpath, both to compile the Java code that uses Groovy, and to find the Java classes of the Groovy runtime. I'll give an example later.

Finally, some scripting languages tend to have ambiguous documentation, or multiple implementations (Jython versus Python, for example). Groovy again wins here--its language has a Java Standards Request, or JSR 241, that includes a precise Groovy Language Specification (GLS). The specification co-lead and main author of the GLS is Richard Monson-Haefel, well known as the author of the O'Reilly book Enterprise JavaBeans and member of the EJB2 JSR experts group. Richard is also the only person I know who wrote an entire EJB server for fun, and gave it away as open source. (He's also the original author of OpenEJB, which has been incorporated into Apple's WebObjects and Apache Geronimo.)

Why Use Groovy?

So, it's groovy that Groovy doesn't suffer from the problems above, but what is it actually good for? Well, any kind of scripting, really. People are starting to use it for prototyping; that is, get an algorithm working in Groovy, then convert it to Java. But often you can just write something in Groovy and keep it as a Groovy script. Just to give you one example, see the fixid.groovy example below, a script I wrote to ensure that all of the Java files in a project have a CVS ID string.

Example 2. fixid.groovy

# Make sure all the Java files in a collection have a CVS ID String.
# Don't apply to all files because it may damage binary files.

new java.io.File(".").eachFileRecurse({file | if (file.name.endsWith(".java")) {
   old = file.getText()
      if (!old.contains("$Id")) {
         println "Fixing file ${file.name}"
         out = file.newPrintWriter()
         out.println("// Next line added by fixid script; 
                     should move into doc comment")
         out.println("// $I"+"d$")   // + to hide from CVS
         out.print(old)
         out.close()
     }
  }
})

Getting Started

The only good way to learn a language (even a scripting variant of a language you know) is to download it and start applying it. (It's also a good idea to review the installation notes page.) And, if you don't want to type in my code examples, you can download them here.

You need JDK 1.4 or later; Groovy will not run on 1.3. When you unpack the archive, you should wind up with these subdirectories:

  • bin: Shell scripts/batch files to run it
  • docs: Documentation
  • lib: The .jar files: groovy and asm, plus a couple of dozen support .jars

To use Groovy, all you need to do is set GROOVY_HOME (and JAVA_HOME, but you probably have that set already). And you probably want to put GROOVY_HOME/bin onto your program path. For example, on my Mac with the Unix Korn shell, I have lines like these in my .profile:

export JAVA_HOME=/Library/Java/Home
export GROOVY_HOME=/home/ian/groovy
PATH=$PATH:$GROOVY_HOME/bin

There are several ways to invoke Groovy interactively. The groovysh terminal-based interpreter and the groovyConsole GUI interpreter let you try your hand at composing Groovy interactively. Using the present version (Beta 0.6.1) of groovysh consists of typing one or more Groovy statements, then typing "go" or "execute" to run them (though this is labelled as a "temporary command"). Here's an example of groovysh in action:

Example 3. groovysh

ian:61$ groovysh
Lets get Groovy!
================
Version: 1.0-beta-6 JVM: 1.4.2-38
Type 'exit' to terminate the shell
Type 'help' for command help

1> meaning = 42
2> println "Hello. Did you know that all it means is ${meaning}?"
3> go
Hello. Did you know that all it means is 42?

1> exit
ian:62$ 

Using the groovyConsole consists of typing Groovy statements in the bottom panel, then invoking the Action -> Run menu item and looking in the top panel for messages and the invoking console for standard output (Ctrl-R is the keyboard shortcut for Run). groovyConsole has the advantage that you can save a script file from its File menu. Here's an example of groovyConsole in action:

groovyConsole

groovyConsole

As well, the groovy command runs a set of Groovy statements entered on the command line (with -e), or stored in a text file whose name is given on the command.

groovy -e 'System.in.readLines().each { println it }'

This makes a simple "line count" program, for example:

ian$ ls | groovy -e 'c=0; System.in.readLines().each { ++c };println c'  
6
ian$

At least on Unix/Linux/BSD/Mac OS X, you need to put single quotes around the entire command to protect all "meta-characters" in it. Which you use is a matter of choice.

There are also Groovy plugins for popular IDEs, including Eclipse, IntelliJ, IDea (but its page is blank), and even vim. There is not yet support for Emacs or NetBeans, as far as I can tell. But given Groovy's similarity to Java, both of these should soon follow. And, once the JSR is a bit further along, I'd expect to see the commercial IDEs catching up.

Pages: 1, 2

Next Pagearrow