I recently inherited a bit of code written in Groovy. It does a lot of XML processing and fiddling with maps, and the author chose Groovy because it has handy facilities for such tasks. My job was to use that bit of demoware as a starting point to write a more substantial blob which would run as part of a servlet under Tomcat.
It was painful. Every time I misspelled an identifier or tried to access a variable that was out of scope or got a method name wrong or forgot to type “def” before the first assignment to a variable or just about anything else, I had to redeploy the servlet. Perhaps JavaRebel would have helped here, but I didn’t have it or know how to use it and I wasn’t sure it would work with Groovy anyway, so I didn’t invest the time to find out.
Also, the support for Groovy in the NetBeans IDE seems to be poor. Of course you can’t expect it to do nearly what it can with a strongly typed language — showing you inferred types, suggesting completions, doing refactoring. But there were other problems on top of that, like breakpoints not firing for code that clearly must have executed, and occasionally I would find myself stopped inside the Groovy runtime. And NetBeans’s “Apply Code Changes” feature, which sometimes allows you to change the code in a running program (kind of a poor man’s JavaRebel) didn’t work when I changed Groovy code.
Furthermore, Groovy didn’t seem to like anonymous classes; I was unable to anonymously extend a Java class I extend in Java all the time.
Ultimately I tried to rewrite some of the code in Java. But the code I rewrote extended a Groovy class, and apparently extending a Groovy class in Java is not allowed, or at least not workable. The Java subclass could not access inner classes defined in the Groovy superclass. The Java class could not access the superclass’s fields. The compiler complained that some mystical method required by the Groovy runtime was not written. I ended up having to make the Java class unrelated to the Groovy class and give each object a reference to the other — a bit ugly.
And finally, I got some really obtuse error messages, like this one:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'null' with class 'null' to class 'java.lang.Number'
The line in question was
if (save_file) saveMetricsInput(xml_metrics_text);
- What is “object null”? Neither of the variables used in that line was null.
- And what is “class null”? I had no idea.
- And where is anything being cast to java.lang.Number?
When I get errors like this I begin “flailing” — making semi-random changes to the code to see what effect, if any, they have on the error messages produced, in the hopes of getting clues about what is really going on. Flailing is never pleasant.
Eventually I figured out that the return type for the method was (erroneously)
long, and the above line was the last executable line in the method, so Groovy was trying to coerce that last line to a long value. I puzzled over other errors as well, but that one was probably the worst.
I enjoy Groovy for standalone scripting — it’s pleasant for that, especially when you need some dynamic behavior. I used Groovy for a framework for updating a database, and it worked out quite well — each update is itself a bit of Groovy code that gets invoked by the framework. But I really wish I had just rewritten this Tomcat-based thing in Scala the day I got it. I’ll stick with statically typed languages inside heavyweight containers from now on. And actually, Scala feels pretty dynamic itself, even having the moral equivalent of duck typing, missing-method handling, and a REPL.
It occurs to me that I might have had a better experience with Groovy if I had used a different IDE, perhaps Eclipse. In fact I’ve been wanting to get to know Eclipse better anyway since it appears to be the best-supported IDE now for Scala. But I think a big part of the draw for Groovy is that it is very Java-like, and that isn’t very important to me — I’ll happily invest the time to learn a different way of doing things if the result is better.
Finally, I’m working on a Griffon (which is based on Groovy) app right now, and I have to say I’m pretty impressed so far. I don’t generally like GUI work, but Griffon removes a lot of the pain. @Bindable and other features remind me of JavaFX. I am starting to see the power of Groovy’s AST transformations.
Groovy and Ruby/JRuby seem similar; both have interesting metaprogramming facilities. I have yet to get a feel for where I would choose Groovy vs. Clojure; my gut feel is that using Scala for statically typed code and Clojure for more dynamic work would be a dynamite combination. Now with ClojureScript on the client, Clojure is even more interesting!