Java Development News:

Groovy: First Contact

By Mike Spille

29 Mar 2004 | TheServerSide.com

As I mentioned in my Chunky Bacon blog entry, I've decided that I've been chugging along with Java/C/C++/perl for far too long. I'm stagnating, and I need to go out and learn something new. As much as I enjoy coding in Java, constant contact with it has dulled my enthusiasm and hardened too many neural pathways for it to really be fun anymore. I was doing C as a friggin' teenager, C++ is giving me ulcers, and perl - well, you know about perl. So it's high time I get off my bum and learn something new.

The initial candiates were Ruby, Groovy, and Python. Ruby seemed interesting from a conceptual standpoint, but in many ways it was just plain alien in its approach and syntax. I'm not married to the ancient syntax codified originally by C, but it is a famililar landmark that I've grown comfortable with. Ruby may be great, but I don't think I have the time to bend my mind around something so radically different. It all seems to hang together in a well-designed way, but I don't have the brain power to devote time to it right now. And besides, I don't need the Chunky Baconettes haunting my dreams.

Looking at Python, there's an amateurish feel about it. I'm sure this will piss off Python people immensely, and the fact that I can't give concrete examples will piss them off even more, but that's the first impression I got after looking at it for a few hours. Put in the simplest terms, it feels like a very annoying language to me. Writing 'lambda' all of the place seems the height of silliness. They can keep their 'self'. Double underscores get real old real fast - even in just a few hours. "def"? "DEF"? WTF? I don't think I can use a language that defines methods with a keyword "DEF" (aside: And I'm pissed that Groovy requires DEF, but at least its only in one specific case).

Ruby and Python both also seem to have issues with runtime speed, which just goes further to reduce my warm fuzzies. I want my warm fuzzies, damn it, and these guys aren't giving them to me!

That leaves Groovy. Based on extensive past experience in encountering and learning new things, I was fully prepared to be wildly disappointed. In the real world the stars of the show seem to never live up to their billing. The handsome lead looks fabulous in his stage makeup, but after the show you find that the makeup was covering 37 zits; he's really 5'2"; his last bath was probably in the Nixon era; he was wearing a girdle to hold in his 48-inch belly; and he's got bits of chunky bacon stuck in his teeth. There's alot of people out there making alot of fancy talk, painting a pretty picture to give the illusion of their hero being a a virile leading man. But almost always it's all smoke and mirrors, it's a coverup aimed at making a smelly short fat man with bad complexion look good.

In Groovy's case, I was pleasantly surprised. Maybe there is a smelly short fat man buried in there somewhere with chunky bacon rotting in his teeth, but I haven't found him yet.

The following are my first impressions of learning Groovy, and my experiences in trying to use it for the past week. To give you a bit of context, I'm using Groovy to script the configuration of my XALogging implementation, and to also script the performance and stress tests.

Please keep in mind that this is the result of only a week's worth of experimentation, reading, and trying to use the language in real world work. I am in no way a Groovy expert, or even an intermediate Groovy user - I should be considered a bare novice who's still has a stupid look on his face most of the time. As such it's a certainty that I've gotten some things wrong here. In those cases, I hope the true experts will stand up and show me the error of my ways.

Getting Started

Downloading the Groovy 1.0 Beta 4 distribution was 3 clicks from the main Groovy web site. This may be some kind of record. Perhaps someone's been reading the Bile Blog, or maybe a virulent form of common sense has broken out in the open source community.

The installation itself is a .tar.gz file. Perhaps lack of a Windows .zip file or InstallAnywhere will piss some dire-hard Windows GUI people off, but as an old time Unix guy this warmed my heart. After download you must follow this incredibly involved installation process:

  • gunzip it
  • tar -xvf it
  • set GROOVY_HOME to your groovy distribution directory
  • Add $GROOVY_HOME/bin to your PATH (Windows weenies will have to do some fake batch file hackery similar to this, I suppose).
  • Optionally add some jars from $GROOVY_HOME/lib to your CLASSPATH. If you just want to mess with the Groovy shell or compile some scripts, this isn't necessary
I'm sure the same Windowsites who gasped at lack of a .zip file or .exe will be in cardiac arrest over this installation procedure; I for one found it refreshing. Now you're ready to rock'n'roll with Groovy. You can play around with the groovy shell ('groovysh') to grok the most basic syntax and semantics of the language. You can use 'groovyc' to compile your groovy scripts. Or you can use Groovy scripts from your Java code using the GroovyShell and Binding classes.

Getting down to brass tacks

It's a little harder than it should be to jump into learning and really using Groovy. Despite what I said in the intro, there is a bit of smoke and mirrors going on here. In this case it's mostly harmless, and fortunately quite shallow - only the superficial information is written in Fleury speak. The bulk of the material is very straightforward and candid. But it gets in the way of trying to dive in quickly.

The home page blurb states:

Groovy Home: Groovy is a new agile dynamic language for the JVM combining lots of great features from languages like Python, Ruby and Smalltalk and making them available to the Java developers using a Java-like syntax.

Groovy is designed to help you get things done on the Java platform in a quicker, more concise and fun way - bringing the power of Python and Ruby inside the Java platform.

Groovy can be used as an alternative compiler to javac to generate standard Java bytecode to be used by any Java project or it can be used dynamically as an alternative language such as for scripting Java objects, templating or writing unit test cases.

The main purpose of the above quote is apparently to stun the user into a stupor by firing alot buzz words at you, and to avoid telling you what Groovy is at all costs. What it probably should say is, were I the publicist for the team, would be:

The Spille Version Groovy is a new scripting language built on top of the standard Java 1.4 JVM. It combines features from languages like Python, Ruby, Smalltalk, and Perl in a very Java-like syntax which has full interoperability with Java classes and code. The language looks like a close cousin to Java, but implements decidedly non-Java constructs such as Closures, regular expressions, here-documents, and optional relaxation of static typing as first class language constructs.

You might say that Groovy feels an awful lot like Ruby, but looks far more like Java - and most importantly Groovy code can directly call Java code, and vice versa, and Groovy itself compiles down to plain old Java bytecodes.

Over the effort of doing some document and source diving into Groovy, I came to realize a few things that were fundamental to getting the right mindset, including:

  • Groovy should first and foremost be thought of as a scripting language. It has alot of power that belies the "scripting" moniker, and since it compiles quite naturally down to bytecodes probably is very scalable to development, but I think scripting is where it's going to be most powerfully felt. At least for now - perhaps over the years Groovy will be seen more as a direct Java competitor, as Cedric has predicted. But the big bang for the buck you'll see right now is in the scripting arena.
  • Groovy doesn't grok Java syntax. This threw me for awhile. Groovy in many aspects looks very Java like, but it's not a backwards compatible language when it comes to source like the C/C++ relationship. Groovy has full Java bytecode functionality, but it will barf quite spectacularly if you try to feed Java code into the compiler or eval() method. So your Java stuff can naturally get to Groovy stuff, and your Groovy stuff can naturally call Java stuff, but don't try to pass Foo.java to Groovy (or Foo.groovy to javac!).
  • Groovy is still evolving very heavily. Alot of the feeatures are very much in flux, and new things are being considered on the development lists and IRC even as I type. I think it's achieved a core of stability, but there's still alot of chaos out on the edges. Keep that in mind if you want to do some serious heavy lifting with Groovy.
Once I had the above firmly implanted in my brain, I found groking Groovy fundamentals to be alot easier.

What I like about Groovy

Lists and Maps are first-class citizens in the language
I first saw the power of native language auto-growable arrays in perl, and how Hash-specific syntax there likewise made simple mappy-tasks a breeze. Of course other languages now also do this, and Groovy is no exception, although it does it in a more Java-like manner. Hmm, I wonder if it's possible to take something like the old Perl Getopt::Long module and do the equivalent in Groovy, something like:
cmdArgs = [
    "filePrefixes=s" : filePrefixes,
    "size=i" : logSize,
    "verbose" : verbose,
    "doRecovery!" : recover,
    "help" : { printHelp(); },
];
result = GetOptions (cmdArgs);
It's a simplistic example, but still - that'd be cool :-). I haven't seen such a beasty around, and if none really exists I might just have to create one. Isn't command line argument processing like the first utility library that anybody writes in a new language?

On other Collectiony subjects, of course, arrays (oops, sorry, Lists) and maps syntactically very close, which is a nice convenience:
actions = [
   "open" :   { println ("opening"); },
   "close" :  { println ("closing");},
   "swizzle" : { println ("Swizzling"); },
   "dance" :   { println ("Disco stu is dancing for you"); },
];
actions["dance"].call();

orderedStuff = [ 1, 3, 4, 5, 6];
orderedStuff[0] = 0;
This is sweet. Lists and Maps (or Arrays and Hashes, for you Perlites) are so important and such a fundamental part of the developer's toolkit that they really should be first class citizens. Note: The above examples show some simple uses of Closures. More on that in a bit.

Regexes are first-class citizens in the language
The old Perl syntax is back again, this time for doing regular expressions the easy way. But of course, it's not quite Perl-like. What we've got is the following. We've got '~' to create a regexp (as in "myPattern = ~"wow"). We've got '=~' to create a bound matcher (as in "matcher = "wowzers" =~ "wow"). And we've got '==~', which apparently is a shortcut for determining matches. The big downside for regular expressions is that the docs on this are really, really thin.

Closures
I don't see how anyone can not like closures, particularly when they're syntactically so easy to specify in Groovy.

The only downside here for me is that closures use the yicky Ruby syntax for parameters e.g. from the docs:

 c = { a, b, c | println("Hello ${a} ${b} ${c}") }

Yucky poo. Would it be possible to make this more Java-ish? It's been a couple of geological ages since I've analyzed parser ambiguities, but something like this would be nice as a more Java-like alternative:

 c = (a, b, c) { println("Hello ${a} ${b} ${c}") }

But, like I said, I don't know if this would require too much look-ahead or possibly be too ambiguous or make the parser excessively fugly. The only other problem here is calling them "Closures". In my experience, about 50% of software developers go cross-eyed when you use the word "Closure". They start thinking of bizarre Lisp programs, seas of parenthesis, something to do with spices in Indian food, and computer scientist PhDs with pointy glasses and really dirty hair spewing language theory. The end result is that the simplicity and elegance of the notion is lost on many people. It'd sure be nice if someone could come up with a simple word that doesn't have the negative baggage associated with "Closure".

Groovy swings both ways - you can go statically typed or not
Groovy lets you, the developer, choose when you want static typing and when you do not. For heavy duty lifting I always prefer static typing (for reasons I won't expound on here), but for many, ah, scripty tasks static typing just gets in the way. Groovy lets you pick and choose on a case by case basis whether you want to specify the type of something or not. This is one of the core features of Groovy that I absotively, posalutely love.

The Groovy JDK
Groovy has added a bunch of new methods to old standbys in the Java JDK - various array types, Object, Streams, and other classes have brand new Groovy-oriented methods. Some (rather obvious) favorites of mine include Object.every(), Object.each(), Process.waitForOrKill(), pretty much all of the Collection methods, and some cool things like "String BufferedReader.getText()", and "InputStream.eachLine(Closure)" and "List InputStream.readLines()". Check out the JDK docs here.

Switch-on-anything
Groovy let's you use anything in the 'case' clause of a switch statement - ints, Objects, and various Groovy language features. This is most excellent.

HERE docs!
Yep, old perl grizzlies will be happy to see that Groovy supports HERE documents. From the Groovy docs:
name = "James"
text = <<FOO
hello there ${name}
how are you today?
FOO

assert text != null
println(text)
HERE-documents are invaluable when you need to spit out alot of text and spot-substitute certain pieces. And while I'm talking about spot-substitution...

Embedded expressions in Strings
Groovy lets you embed expressions in Strings (note: IIRC this may not be 100% operational for arbitrary expressions). So you can say something exactly like the HERE-doc example above:
name = "James"
text = <<FOO
hello there ${name}
how are you today?
FOO
assert text != null
println(text)
You can of course also do this with normal strings e.g "Hello there ${name}". This is a monumental relief for me - sometimes my fingers have cramped up into hooked claws from all the '"string" + var + " string " + var2...' crap you have to do in Java.

Named parameters
Groovy let's you use named parameters. Some people aren't too into these, but for me I think it's a great idea. It's one of the ideas from Smalltalk that I was sorry not to see make it into Java.

What I don't like so much

Semicolons are optional
You don't have to use semicolons in Groovy, unless you're putting multiple statements on a line. I personally think this is taking scripting minimalism too far. IMHO whenever a language decides some syntax is optional, it invariably breeds confusion among people. It's one of the things that makes Perl so hard to remember, doubly so when reading someone else's code. Make semis mandatory!

Parenthesis are optional for method invocations
As the Groovy docs state, "Method calls in Groovy can ommit the parenthesis if there is at least one parameter and there is no ambiguity.". This falls into the same category of optional semicolons - it seems nice, but it's overall effect is to confuse the shit out of people. Alot of this is visual parsing. In the Java world, as elsewhere, your brain gets used to parsing:


  foo.logIt (XAStates.XA_START, myData, false, false);

...and knowing intuitively what this thing is. But now you can do:

  foo.logIt XAStates.XA_START, myData, false, false;


...and you can also do:


  foo.logIt XAStates.XA_START, myData, false, false

...and lastly you can also do:

  foo.logIt (XAStates.XA_START, myData, false, false)


That's four forms my poor overworked brain has to parse. This is a very, very bad idea. When writing code, it's nice to be able to type as little as possible; but everyone knows most coding actually has to do with _reading_ code, not writing it, and optional syntax makes it harder to read code. Give me back my parenthesis!!!

A return statement is optional
As you can do with perl, you can use a return statement, or you can omit it and the last evaluated statement's value becomes the return value. So you can do the old Java thing:

   int goForItMama (value) {
     doSomething();
     return 5;
   }

Or you can do something that looks quite different - this is a combination of the various Groovy "optionalities":
   int goForItMama (value) {
     doSomething
     5
   }

There are many other permutations and combinations, but I'll spare you. Please, please, please - these seem like trivial things, but this optional stuff is the first step towards write-only code.

Groovy Properties

I like the notion of properties. I really do. I despise writing getter() and setter() methods. I like Eiffel's idea of hiding details like fields vs. methods. But I think Groovy has botched it. In particular, when you _don't_ want a getter or setter generated (write only or read only fields), the mechanism feels very clunky to me. Also, it looks like they're going for Eiffel's notion of unifying fields and methods from an external viewpoint, but they don't quite get there. This may be tied into the optional-parenthesis things with methods (or maybe not). I realize my thoughts on this particular topic are a bit rambling and confusing, but the best I can say is that Groovy properties do not feel right to me in their current form. The semantics and syntax do not have that natural, well-designed feel to them. As I said in the opening, I like the idea in the abstract, but the implementation here just doesn't do it for me.

Invoking other Groovy scripts is awkward
If you want to call another Groovy script, you have to do something like this:

script = new GroovyShell()
script.run(new File("src/test/groovy/script/HelloWorld.groovy"), [])


Yuck. I realize that fundamentally, Groovy is Java (in the end it's all just bytecodes), but when you're in a scripty sort of world you want scripty things to be as easy as possible. There should be language support for invoking another script for people who want to conveniently forget about bytecodes, and focus on the script source. This may be a case of basing everything on the bytecode and JVM taking precedence over how things were done in the past - or maybe not. But it feels to me like the underlying technology is unnecessarily constraining the language in this case.

You can't intermix Java and Groovy source in one file
At the source level, Groovy really is a different language than Java. Different enough that if you feed a typical Java source file to Groovy, Groovy will barf very nicely all over the place. This isn't too serious at this point in time, but sometime in the future I could see this being a desirable future. James Strachan has indicated (somewhere - was it the Wiki?) that this may be a possibility at some point.

It's not Java enough in syntax
I've touched on this in a few places. In several areas, like closures, Groovy seems to throw Java syntax conventions to the wind and do something completely different (most often, doing it in a Rubyish or Pythonesque manner). This is very much a matter of opinion, but I personally favor doing things as closely as possible to Java when in doubt, particularly in light of the target audience (Java developers). Several of the key Groovy people see differently on this, but I think they're unnecessarily making Java people uncomfortable in some areas of the language for no real gain.

The docs are inconsistent
At the time of this writing, the Groovy documents are kind of all over the place. Some features documented pretty well, others, like regular expressions, are pretty incomplete or even confusing. This is exacerbated somewhat by the torrid pace of development of the language: the language is still under design and is flowing around users over time. I hope that the docs will improve over time, and there are indications that they in fact will. I can say that the docs are a great improvement over most open source efforts, and there are real gems in there if you're willing to click around alot. I'll leave this alone now except for one comment: Wikis are great for collaboratively recording random bits of information and building consensus, but they suck donkey privates when an outsider is trying to decipher them. I hope the Groovy team mines the Wiki for valuable information, but please don't link into it from the user guides!!!

Operator Overloading
Ack! Yuck! Pthuii! I despise operator overloading in all its forms and guises. Please remove this pox, this disease, this abomination, from anotherwise respectable language.

Seperation of language from libraries.
This may be a documentation issue more than a technical one, but right now the notion of Groovy, the language, is tightly tied to another of features I feel are extraneous such as Groovy SQL, Groovlets, and the like. This may be just how the documentation evolved over time, but it's confusing as hell for me. IMHO there needs to be a clear seperation, in code and docs, between "core Groovy" and groovy extensions, libraries, frameworks, and various other efflusia. This isn't 100% clear cut - things like the Groovy JDK need to be considered as part and parcel of the core, but I think a better effort could be made to sort out the obvious bits.

Making files first class citizens?

I'm conflicted on this one. One of the cool things about Perl is that it has built-in support for things like reading to and from files. You know, stuff like the old:

@allLines = <FILE>;

Now, Groovy does go to good lengths to make I/O easier than it is in Java. InputStream and its cousins have been extended with a number of extra methods to make it easy to use things like Closures with I/O. But as I said, I'm conflicted. My perl experience tells me that making file handling a first class language item is a good thing, but Groovy's support doesn't require much more typing than perl's. This could be a fight between perl's ancient procedural roots vs. Groovy's more OO way of doing things (and particularly leveraging the Java JDK as much as possible). I don't know - what does the rest of the world think? Would native file reading/writing support be worthwhile, or is it useless sugar that's better handled Objectively?

Peeking at the source

I haven't had the time to really get into the Groovy source code in-depth, but I did have a chance to peek around a bit. Overall, the source looks pretty good. As a newbie poking my head in for the first time, the code made sense, I understood the gross design, things were seperately out logically, and there are actually comments in the code (I know - shocking!). Looking at the parser and lexer also brought a tear of nostalgia to my eye - many moons ago I did alot of stuff with compilers and languages and the like, and Lexers in particular are old familiar friends. Looking at the Groovy Lexer brought a pang of old times past - it's by God a real Lexer and handles reasonably all those things that Lexerites know about but the general public probably has no clue about (what to tokenize and what not to, look ahead, pushing tokens back, consuming tokens, priming the lexer pump, etc).

It's still a newbie's viewpoint, but my eye's been fairly well trained to grok source code quickly. Unlike some other open source efforts I can name, Groovy's source looks like code written by professionals. It's got its quirks and quagmires and "There be dragons here", but all reasonably complex code does. The important thing is that a quick run through tells you that the people who wrote it have been there and done that. I can think of no higher complement. Now excuse me while I go grab a tumbler and a bottle of Jameson, and toast Old Lexers that have passed on, and new ones just coming into the world.

The Bottom Line

Overall, if I was the grading type, I'd give Groovy a B+, with a strong possibility of evolving into a solid A. The team has put together something that I feel is unique and of great value to the Java community. A highly Java-oriented scripting language, with full interoperability with Java objects is a very, very powerful thing. In my own PyraLog work it's becoming invaluable. My biggest concern is the fact that the language still is very much in flux, and it's not 100% clear to me where it all will lead a year or three down the road. The new JSR only serves to make the future murkier. Hopefully the Groovy team will settle on the core feature set soon, and we can start banging on a relatively unchanging language for an extended period of time to see how well it really hangs together on real projects.

Beyond the language itself, one of the great things are the possibities that sitting on top of the JVM give Groovy. In particular, Groovy may be an impressively speedy scripting language that can benefit directly from JVM research without having to lift a finger for itself. This isn't 100% given - in particular, Groovy, the language, relies on key pieces of the Groovy runtime for Groovy code to operate properly. While Groovy code compiles down to bytecodes, it's not pure Java bytecode with no external dependencies. Your code needs to jump into the Groovy runtime jar to execute many language basics like Closures. As such, the efficiency of these classes will play a part in how speedy Groovy is overall.

On a closing note, I would very much like to see the ultimate test of language usability and expressability applied here: implement the Groovy compiler in the Groovy language itself. This is a classic feasibility test of how good a language is, how well it performs, etc. Seeing Groovy bootstrapping itself, seeing how a Groovy-written Groovy compiler looks in source form compared to the existing Java one, would be a very cool milestone for the language. This sort of approach also is an excellent way to gauge new language features: you know a new feature is hot when the compiler team bitches that they can't use it (because a compiler is always written in a version of the language one or two versions behind what the compiler itself will support).

In fact, I haven't had enough time to sift through the source to determine to this, but how much of Groovy (if any) is written in Groovy? As I mentioned, the more of Groovy that is Groovy will be a very interesting measurement of the language feasibility.

Comments from around the web

There has been a lot of noise on this subject in various blogs, including:



About the author

Mike Spille mike@krisnmike.com
Blog: http://jroller.com/page/pyrasun

Mike Spille is an enterprise developer who has been living in the development world for a long time. He has written very interesting articles on topics such as distributed transactions.