What Makes Groovy So…Groovy?
Ever since attending the No Fluff Just Stuff symposium last month, I've been digging into Groovy, and have frankly been blown away. As I watched the presentations, and as I have done my own research, I have been blown away by Groovy's power. I'm convinced. I have to use Groovy. It's that good. I am, however, having a little trouble convincing others of its coolness. Maybe this will help others. Please leave your comments and let me know what you think. I wrote a blog about it. Here it goes!
As I dig deeper, I find that features of the language fall in to four basic categories:
- Wow! That's really groovy!
- Wow! That's really useful!
- Hmmm...that's good to know.
- Nice...but will I use it?
I will focus on the really useful, much of which is also very groovy, but as my boss might say, "groovy don't pay the rent." (He's kind of weird like that.)
Top 10 Grooviest Groovy Features
10 - Brevity (Less is More!)
brev∑i∑ty (br?v'?-t?) 
n.
- The quality or state of being brief in duration.
- Concise expression; terseness.
Yeah. Definitions are cool! And that pretty well sums up what Groovy gives you in terms of coding. By eliminating some of the scaffolding we normally put in our Java classes, Groovy can cut down that amount of code we have to write substantially. I'm not sure that this is typical, but I recently converted a fairly complex Java class to Groovy. The Java class had 1,800 lines of code. The Groovy equivalent was down to only 1,100 lines of code. I'm not real good with statistics, but that seems to be about a 40% reduction.
This is more of a "Wow! That's groovy!" than useful, but it certainly is nice to have. For me typing less per method means more functionality in the same amount of time. And this is with only about 1 week worth of experience. I look forward to what I can do when I learn the ins and outs of the language.
9 - Ranges
OK, fess up. How many times have you written code that looked a little something like this?
-
for (int i = 0; i < upperBoundry; i++) {
-
// Do something interesting
-
}
or tried to figure out if a number is between two other number by doing something like this:
-
if (x > 3 && x < 10) {
-
// Do something else
-
}
Well, Groovy makes this easier, and it's really pretty intuitive. The range format is
[lowerBound..upperBound], [upperBound..lowerBound]or [lowerBound..<upperBound]
So can you guess what this does?
Yep, it prints the numbers 1 through 10. Easy, right? Ok, how do you like this?
That simple little bit of code could be used to see if a letter is between 'a' and 'z'. (Note: you probably wouldn't use ranges to figure out if a character was a letter, that's just here for illustration purposes. More likely you'd use the "~", "=~", or "==~" operators, which let's you evaluate regular expressions. Make sure you check out Groovy's Regular Expression support page.)
Now falling right in to the groovy and useful category is how you can use these ranges in switch statements. Let's say, for example, that you have an insurance company that has different rates depending on the age range of the policy holder. That code might look a little something like this:
-
default : insuranceRate = 0.10
-
}
Ranges aren't limited to predefined goodies like numbers and letters. You could also create an array, or dates, or any other comparable objects, and use those in your range statements.
8 - GroovyBeans
Much more "groovy" than useful, but certainly does cut down substantially on the extra scaffold code you need to write, GroovyBeans are just like JavaBeans, but a lot smarter.
In Java, you might create a simple Person class with a first name, a last name, and an email address. You create the private variables for each of these, and then getters and setters for each. You do the same thing time after time...or usually let your IDE do it for you. Your code for this Person object would probably look almost exactly like this:
Ho hum...how monotonous. How boring! If the IDE can generate those getters and setters for us, why can't Java? Well, because Java's not Groovy (though Groovy is Java). The Groovy equivalent of the above class skips all of that getter/setter silliness and you are left with this:
I know, you're saying, "but I need my getters and setters!" Don't worry sport, they're still there, at least as far as your code is concerned. How would Java call each of the methods in the Java class? Maybe...
And how would Java call each of the methods in the Groovy class? Would you guess...
Exactly the same. How would Groovy access each of these? Either using the property name or the getter/setter.
Notice the last line. This introduces something called GStrings (I'm not making this up). It's a way to include the variable values right within the screen. This same methodology is used in Maven, Ant, JSF, and other technologies, so it's nothing new. Just new to your Java code.
How do you set the values? Pretty much like you'd think:
-
emailAddress = "sample@example.com"
7 - Expando
The Expando class is fashioned off the real-life file folders that expand to fit whatever you put inside them. These fit more into the "groovy" than "useful" category, at least on the surface, but this capability opens the door for some huge dynamic possibilities. Within your code, you can create methods as needed. Here's a trivial example that I borrowed from an excellent book, "Groovy in Action" (buy it now!)
-
boxer.takeThis = 'ouch!'
This example shows the creation of a "boxer" Expando, and then shows that the "takeThis" method didn't exist. The "takeThis" method is then created and accessed, as is a fightBack method. This shows one use for Closures, which I'll get to later. While the use for Expando classes may not seem immediately evident, the power of the Expando enables some of Groovy's grooviest features.
6 - Grep
To most geeks, grep is a very useful UNIX command. Groovy brings this kind of power to Java. Here's another example from "Groovy in Action":
Grep here is used to find all of the 4-letter words in the array. A full array of options, and regular expressions, are available to the grep command.
5 - Spring Integration
Spring is a very cool technology, which allows you to dynamically include classes in your classes at runtime. On the downside, Spring configuration is a pain in the butt. From the SpringFrameworks web site:
-
<?xml version="1.0" encoding="UTF-8"?>
-
<beans xmlns="http://www.springframework.org/schema/beans"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
-
-
<bean id="..." class="...">
-
<em class="lineannotation"><span class="lineannotation"><!-- collaborators and configuration for this bean go here --></span></em>
-
</bean>
-
-
<bean id="..." class="...">
-
<em class="lineannotation"><span class="lineannotation"><!-- collaborators and configuration for this bean go here --></span></em>
-
</bean>
-
<em class="lineannotation"><span class="lineannotation"><!-- more bean definitions go here... --></span></em>
-
-
</beans>
Using Groovy's builder classes, we are able to use Spring within Groovy without a single bit of XML configuration. (I would put an example below, but I can't find one
)
UPDATE:† Ok, my Spring portion was lame.† So, special thanks to Paul King for pointing me to this link.† Told you this Spring stuff was Groovy!† http://groovy.codehaus.org/Using+Spring+Factories+with+Groovy†
Speaking of builders...
4 - Builders
In Groovy, the Builder classes provide an easy way to narrow down repetitive tasks and build non-Groovy items, such as XML and HTML documents, Swing GUIs, and pretty much anything else you can think of that follows a pattern. Let's take a really simple XML example:
-
<?xml version="1.0">
-
<people>
-
<person>
-
<firstName>John</firstName>
-
<lastName>Doe</lastName>
-
<emailAddress>john.doe@example.com</emailAddress>
-
</person>
-
<person>
-
<firstName>George</firstName>
-
<lastName>Bush</lastName>
-
<emailAddress>prez@whitehouse.gov</emailAddress>
-
</person>
-
</people>
In Java in order to create such a document, you'd have to create DOM object, create an element for each person in the tree, and child elements for each attribute, all in some really ugly, hard to read code that I refuse to put here (that exercise is left to the reader...I've been there, and it sucks). In Groovy, to build this XML object, you would do something like this:
-
builder.people {
-
person {
-
firstName { "John" }
-
lastName {"Doe" }
-
emailAddress {"john.doe@example.com" }
-
}
-
person {
-
firstName { "George" }
-
lastName { "Bush" "
-
emailAddress { "prez@whitehouse.gov" }
-
}
-
}
-
Can you tell what that does? Easy right?
I put Swing behind me years ago, 'cause it's such a nightmare, but here's a blog post that gives a quick look at building a simple Swing application in both standard Swing, and using Groovy's SwingBuilder class.
http://codetojoy.blogspot.com/2007/08/groovy-swingbuilder-and-secret-methods.html
Builders are not limited to what the guys at Groovy imagined. Through the magic of the Expando classes mentioned earlier, Groovy allows you to create your own builders with ease. More on these builders can be found on the Groovy web site.
3 - Unit Testing, Mocks, and Stubs
Unit testing in Groovy is so useful, and, well, groovy, that the "Groovy in Action" book mentioned earlier has an entire chapter devoted to it. Because I feel this is important, I am going to include a boatload of links, and an example or two for your convenience. Groovy makes unit tests, mock classes, and stubs much easier than standard JUnit tests. Almost easy enough to encourage developers to actually write tests. Here are some important reads:
- Groovy - Unit Testing
- Practically Groovy: Unit Test Your Java Code Faster with Groovy (IBM)
- Groovy Unit Testing
- Groovy Mocks
- Groovy Testing Guide
The gist of it is that you can create you unit tests, to test your Java classes, in Groovy. Or, if you are testing your Groovy code, you can create in-line stubs and mocks to test your code. Jeff Brown gave some good examples at his NFJS presentation.
-
class GroovyFileHelper {
-
"$pathToFile already exists.")
-
}
-
}
-
}
This class simply writes a message to a file in reverse. How would you unit test this in Java. Well, in reality, you really couldn't, not with a unit test. Maybe an integration test, because in Java you'd end up testing the file system (using the file.exists and file.write methods), not just your code. That's an integration test, my friend. Unless you can somehow throw a mock or stub at the problem. But how, oh how when the file object is inside the method? Groovy makes mocks and stubs easy.
Let's take a look at using the StubFor class to stub out the file object.
-
def messageWrittenToFile
-
messageWrittenToFile = data
-
}
-
stubFile.use {
-
def path = '/Users/jeffbrown/someFile.txt'
-
helper.populateMessageBackwards(path, 'this is some data')
-
}
-
assertEquals 'wrong message was written to file',
-
'atad emos si siht',
-
messageWrittenToFile
-
}
-
stubFile.use {
-
def path = '/Users/jeffbrown/someFile.txt'
-
helper.populateMessageBackwards(path,
-
'this is some data')
-
}
-
}
-
assertEquals 'incorrect exception message',
-
'/Users/jeffbrown/someFile.txt already exists.',
-
msg
-
}
Here we are telling the JVM to use our stubFile in place of the File object within our stubFile.use block. How easy is that?
Mocks work the same way, but it's more of a white box test, where you can specify which methods are to be called while testing.
2 - Closures (and Delegates)
On the surface, closures seem a whole lot like Java's anonymous inner classes, though they are easier to use, and much more flexible. They have been shown in previous example without any explanation. Closures are basically blocks of code that take parameters. Sound a little bit like a function? Yep. A function that you can pass around, and which continues to have access to the local variables of where it was created, even when passed around. Like anonymous inner classes without the need to worry about that ugly "final" keyword.
This simple concept can be used in unit tests, pretty much anywhere else you can think of that it might be useful to pass a function around.
Then there's the idea "delegates". Pretty cool stuff. You can define a closure, and then delegate all calls within that closure to any given class. For example, I might have a closure that looks like this:
This closure could work with many different classes. Anything that has an "append" method. the StringBuffer comes to mind. So how do I get the appender to use the StringBuffer? Something like this:
-
Closure appender = {first, second ->
-
}
-
appender.delegate(buffer)
Here the closure will call the append method on the buffer class. The possibilities here are endless!
1 - ExpandoMetaClass
The ExpandoMetaClass allows you to do the impossible. Add methods to existing classes. The String class, by design, can not be extended. So how in the world would you go about adding a "swapCase" method to the String class? (An incredibly useful method that would return a reverse-cased representation of a given String.) Easy. Use the ExpandoMetaClass from Groovy. (From the Groovy Web Site)
-
delegate.each {
-
}
-
sb.toString()
-
}
This actually changes the byte code for the String class, making the swapCase method available for the entire life of the JVM. Imagine being able to dynamically change any class you want to, on the fly.
This same methodology can be used to override methods in otherwise un-overridable files. Let's say you find a bug in some open source software you are using. You can either wait for the bug to be fix, fix it yourself and submit it back to the project, or override the method in your own code to make use of a quick fix.
I'm sure I'll look back at this post a few short months from now and have different options, and a different order, but as of right now, this stuff just rocks.
Nice post Joe! This made sense to me and I don’t even know anything about Java. You’ve managed to get me interested in it too
Thanks, Rob.
I kind of consider it a first draft, but not too shabby. I need to work on the CSS on those code boxes a little bit, that’s for sure. Ick!
Good luck!
Joe
Ok, this layout may work a little better.
Nice article joe. Another cool thing is invoking web services. Just point a groovy class to the ?wsdl for example and you can dynamically call the operations. http://docs.codehaus.org/display/GROOVY/Groovy+SOAP
Also I see ExpandoMetaClass being very useful to replace mock classes in unit tests.
If you want to start playing with groovy in your current projects that use maven2, check out the maven-groovy-plugin: http://mojo.codehaus.org/groovy/.
If you want to see an example, checkout this pom.xml file in our open source project for the RSS Binding Component: http://tinyurl.com/269k4o
Thanks. I took one of our projects and was tinkering with Groovy inside it. I was amazed at how little I needed to do to use Maven 2 transparently. Just two changes, adding the plugin, and adding the Groovy jar dependency.
I haven’t tinkered with the web service stuff yet, but browsing the book, it looks like RESTful web services are just as easy.
I like easy
Great post Joe. I think you’ve wrapped up our brown bag into one blog post.
Wow. I can tell I definitely need to check out Groovy
Here’s the Groovy page on maven 2 integration. http://mojo.codehaus.org/groovy/guide-groovy-development.html Very easy.
And don’t forget that the Hudson (https://hudson.dev.java.net/) developers added a groovy scripting console right in the web UI. How’s that for cool?
I’ve had a lot of folks ask me for a follow-up post, so taking some of the suggestions in these comments, and a few new things I learned about, look for more groovy Groovy soon.
[...] I’m a geek, and apparently full of myself, ’cause I actually think that you might be interested in what I have to say. Feel free to point and giggle. « What Makes Groovy So…Groovy? [...]
Re: using Spring within Groovy without a single bit of XML configuration
Check out the Groovy documentation:
http://groovy.codehaus.org/Using+Spring+Factories+with+Groovy
Look for Annotation Approach and BeanBuilder Approach – both let you leave the XML at home.
Awesome. Thanks Paul!
Amazing post! (I know i’m late reading it; but i found it while surfing around. Every point you hit on is why I love groovy… Awesome job!
Hi, great post. When you quote example from the Groovy in Action book literally, you should give credits.
cheers, Dierk
Thanks, Dierk,
Very true. I tried to give credit where credit was due, but may have missed a couple. If you can let me know what I missed, I’ll be happy to site your work.
Groovy In Action is an excellent book, one you should be proud of, as I mentioned in the “Expando” section.
< http://www.amazon.com/Groovy-Action-Dierk-Koenig/dp/1932394842/ref=sr_1_1?ie=UTF8&s=books&qid=1251226100&sr=8-1>
Buy it! Now!
The link didn’t show up…let’s try that again:
http://www.amazon.com/Groovy-Action-Dierk-Koenig/dp/1932394842/ref=sr_1_1?ie=UTF8&s=books&qid=1251226100&sr=8-1
Excellent post.
Groovy designer said Scala is better so why not Scala
10.Brevity: a 40% code reduction for Groovy from Java, but what about the slowdown in execution time?
9.Yep, ranges are cool! Makes Groovy code look more like Python.
8.Beans: do you really need properties? Why not just code directly to the field?
7.Expando: Wow, just like Ruby open classes.
6.Grep: just use Unix (or call it from Perl)
5.Spring integration: better than Java.
4.Builders: Groovy truly innovated here, though Ruby long ago copied them.
3.Unit tests, mocks, stubs: better than Java.
2.Closures: many languages have them. Use Scala if you also want variable hiding!
1.ExpandoMetaClass: better than Java. In fact, if you’re a Java programmer and need to stay on the JVM, then Groovy could be for you. But after a while, you might get itchy fingers and try out Python/Ruby, Scala, Haskell, Smalltalk, Scheme/Lisp, APL/J/K, etc, then wonder why you stayed with Groovy for so long!
thank you