Powerful Groovy

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.

Comments (10)

  1. James Lorenzen - Reply

    May 30, 2008 at 3:58 am

    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.

  2. Lars Vonk - Reply

    May 30, 2008 at 8:20 pm

    Thanks James, I'll keep my eye on NetBeans.
    btw you hit the nail on the head when you say that is amazing how much fun programming in Groovy is. I recommend to everyone 🙂

  3. Elissandro Mendes - Reply

    June 18, 2008 at 5:45 am

    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

  4. Elissandro Mendes - Reply

    June 18, 2008 at 5:46 am

    Oh...sorry

    GREAT ARTICLE !!!!

  5. Lars Vonk - Reply

    June 18, 2008 at 1:23 pm

    Hi Elissandro. Thanks!
    To add the methods I just call Bootstrapper.boot() as first statement in my Groovy script.
    Note that the method boot() in this case should declared as static in the Bootstrapper class.

  6. More Groovy power | Xebia Blog - Reply

    July 6, 2008 at 11:38 am

    [...] 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 [...]

  7. Tony Nassar - Reply

    April 7, 2009 at 7:26 pm

    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()
    }
    }

  8. Groovy Code Sample » iHenk - Reply

    February 21, 2010 at 7:46 pm

    [...] Thanks to : powerful groovy [...]

  9. Ankita Jiwan - Reply

    August 30, 2012 at 7:10 am

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

    • Age Mooij - Reply

      August 30, 2012 at 9:15 am

      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.

Add a Comment