Blog

Powerful Groovy

25 May, 2008

For my current assignment I need to write a script that basically does the following: open war file, download and add files from internet, remove files, change xml and property files, re-package war file.
In pure Java, this would be quite some work to implement. Of course there are several libraries available that will make unzipping, downloading etc a bit easier. But still it would be too much effort for such trivial tasks.
Since it is in fact a script I want to create, why not use a scripting language like Groovy. After two days of coding I must say am very happy with the progress I made given the fact that it is actually my first real Groovy programming experience.
Here are some experiences and code I created so far:

IDE Support
I (used) to work with Eclipse, but the Groovy support for Eclipse is still in progress which was noticeable when using the Groovy Eclipse plugin. It was not really usable in my experience. Since I was already fed up with Eclipse this was actually the final push I needed to switch to IntellJ.
Coding
Now let’s start coding and see how you can implement zipping in Groovy. Groovy already added a lot of convenience methods to the default JDK classes. But wouldn’t it be great if there was also something like an extractTo(destination) method on ZipFile, and a method zip(destination) on File available in Java? Well with Groovy you can quite easily add it yourself using the metaClass and make it available through out your code.
Here is how I added zipping:

class Bootstrapper {
    void boot() {
        File.metaClass.zip = { String destination ->
            def result = new ZipOutputStream(new FileOutputStream(destination))
            result.withStream {zipOutStream->
                delegate.eachFileRecurse { f ->
                    if(!f.isDirectory()) {
                        zipOutStream.putNextEntry(new ZipEntry(f.getPath()))
                        new FileInputStream(f).withStream { inStream ->
                            def buffer = new byte[1024]
                            def count
                            while((count = inStream.read(buffer, 0, 1024)) != -1) {
                                zipOutStream.write(buffer)
                            }
                        }
                        zipOutStream.closeEntry()
                    }
                }
            }
        }
    }
}

What I really really like is the closures for working with streams… No more try-catch-finally-try-finally blocks for closing streams! This is something I really miss in Java.
To zip up a directory you can now just say:

new File("/home/lars/").zip("/tmp/home.zip");

Since I have several methods I added to the JDK classes I created a Bootstrapper class I load on startup of my main Groovy script. This way I have a good oversight on what methods I added myself.
Testing
Another cool thing in Groovy is the build-in JUnit support. You can create unit tests by extending GroovyTestCase and if that is not enough Groovy test cases are runnable out of the box so you can just run a test class using groovy com/xebia/ZipTest.groovy
Conclusion
After just two days of Groovy I started to really like it. One of the nice aspects is that if you don’t know how to do it in Groovy, just use Java and find a more groovy solution later on.
Another thing I noticed is that the lines of code you produce with Groovy is considerably less than the lines of code it would be using Java. Not the mention the fact that I actually included 0 dependencies for my Groovy code. How many would that have been for Java?
And on top of the Groovy icecream the Groovy metaClass gives you a very powerful tool to create more intuitive Java.
I am definitely going to use more Groovy in my future projects.
Lars
PS. All of the functionality I needed for this script are also already offered by Groovy’s build-in AntBuilder.

guest
11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
James Lorenzen
14 years ago

Great example of groovy’s metaprogramming abilities. It’s amazing how fun it is to write groovy code. I also am a IntelliJ Idea Groovy guy but you might also keep tabs on netbeans support for groovy. They are putting a lot of effort into making it just as good as idea.
I find myself in the same position when I don’t know the groovy way I just stick to java and look for a better solution later.
Thanks for the great article.

Elissandro Mendes
Elissandro Mendes
14 years ago

I’m a beginner java programmer, I’m curious how do this: “Since I have several methods I added to the JDK classes I created a Bootstrapper class I load on startup of my main Groovy script.”
Can you show explain and show how do ?
thanks

Elissandro Mendes
Elissandro Mendes
14 years ago

Oh…sorry
GREAT ARTICLE !!!!

trackback

[…] by Lars Vonk just before lunchtime: July 6, 2008 After my first real encounter with Groovy I got really excited about it and decided to spend some of my personal […]

Tony Nassar
13 years ago

It’s a matter of taste, whether you prefer to change the semantics of File or of ZipOutputStream. I’d prefer to add a leftShift() operator to the latter. In any case, you can use some Groovy sugar to make this code far *more* concise. Example:
import java.util.zip.*
def desktop = ‘C:\\Documents and Settings\\tnassar\\Desktop’
def z = new File(desktop + ‘\\test.zip’)
def folder = new File(desktop + ‘\\’ + ‘100_0000’)
new ZipOutputStream(new FileOutputStream(z)).withStream { zstream ->
folder.eachFile { f ->
zstream.putNextEntry(new ZipEntry(f.name))
new FileInputStream(f).withStream { istream ->
zstream << istream
}
zstream.closeEntry()
}
}

trackback

[…] Thanks to : powerful groovy […]

Ankita Jiwan
Ankita Jiwan
10 years ago

i wrote the same code in iIntelliJ but it gives missing function error. plz help

Age Mooij
10 years ago
Reply to  Ankita Jiwan

This blog was written 4 years ago so I’m not surprised you get errors. I suggest you have a look at the current Groovy docs.

Ibrahim
Ibrahim
6 years ago

Check out this gist@github zip & unZip in grooviest way:
https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681

Explore related posts