The ability to execute pretty much any bash statement embedded in a Groovy script is great, don’t get me wrong, but with the advent of Grape – and provided that you’re an Ivy/Maven user – adding the abilities of just about any Java library to your scripting language is easy.
So what does Groovy add to the mix to make it an attractive option on top of(or instead of) bash on its own? Dependency management, lean distribution and testability all jump to mind.
Dependency Management
Grape gives you the same stability that Maven provides. Any script can load any Java library is wants to utilize into the classpath at runtime using your existing repository or an available internet connection.
Lean Distribution
Because Grape utilizes a central repository, all dependencies are shared across the entire system. Scripts with extremely small footprints can do some pretty big things. Recently I’ve seen examples of parsing html using TagSoup(I swear I originally saw that example somewhere else but for the life of me can’t find it now), Apache Camel integration(and again) and even spawning a local HSQL database, complete with Hibernate. Within a very sparse number of lines, you can do more than you could ever imagine with plain Java, and I’m more than willing to admit that I wouldn’t know where to start with bash to do any of the stuff I just mentioned.
Testability
The only thing that separates a stand-alone Groovy script from a Groovy class on the command line is the #!. If you’re willing to launch the script on the command line explicitly using the ‘groovy’ executable you can abandon that. So now the difference becomes ‘./groovyScript’ versus ‘groovy groovyScript’. But…. that same script is now ripe and ready to be included in the test framework you use everyday for regular project development. You can easily compose it into unit-testable methods and treat it like any other part of a large and rapidly evolving software project – things that I’ve always found inherently difficult with a command line script. Mostly I find that the truly useful scripts and snippets – the ones that are used regularly by developers on a day to day basis – are the ones that also never end up under source control, and don’t get the benefit of evolutionary change that most code gets.
Building upon the example included in the InfoQ Groovy 1.6 launch notice, here’s the quick and dirty addition of a JXTable component for showing the results of parsing all links from an html page with TagSoup. A text field is used to bind the url and a click of the button starts it off. It’s not pretty, but it did take less than 10 minutes to do so judge for yourself. Run this script from the command line using the groovy command (V1.6+).
[groovy language=”true” smarttabs=”true”]
import org.jdesktop.swingx.JXTable
import javax.swing.*
@Grab(group=’org.swinglabs’, module=’swingx’, version=’0.9.3′)
@Grab(group=’org.ccil.cowan.tagsoup’, module=’tagsoup’, version=’0.9.7′)
def getHtml(url) {
def parser = new XmlParser(new org.ccil.cowan.tagsoup.Parser())
parser.parse(url)
}
def data = [ ]
def my = groovy.swing.SwingBuilder.build {
frame = frame(title:’Groovy Grab Test’, size:[800,500], show:true, pack:true, defaultCloseOperation: WindowConstants.DISPOSE_ON_CLOSE) {
actions(){
action(name:’Fetch’, id:’fetchAction’)
{
data.clear
getHtml(urlField.text).body.’**’.a.@href.each{ data << [url:it] }
frame.repaint()
}
}
boxLayout(axis: BoxLayout.Y_AXIS)
scrollPane() {
myTable = table(new JXTable(columnControlVisible:true)){
tableModel(list:data){
propertyColumn(header: ‘URL’, propertyName: ‘url’)
}
}
}
textField(id:’urlField’)
button(fetchAction)
}
}
[/groovy]
Since I work for an organization that uses maven extensively for dependency management, most of the libraries that come to mind as handy bash replacements are already available in my local repository. Apache commons, Google collections, and most importantly – any libraries that are specifically dealing with your own products – all are at your fingertips! Even better, since most of the tasks that commonly fall to scripting are pretty low level (moving files around, etc), there are easy alternatives.
AntBuilder, for instance, is baked into Groovy, and provides a great abstraction around most of the desired functionality you want in a scripting environment. Moving files, doing text replacement,tarring files, sending mail – anything that Apache Ant can do, AntBuilder can do. But without all of that infuriating and frustating xml. An example(complete with exception handling!) courtesy of Andrew Glover, in this article.
[groovy language=”true”]
ant = new AntBuilder()
ant.mkdir(dir:"/dev/projects/ighr/binaries/")
try{
ant.javac(srcdir:"/dev/projects/ighr/src",
destdir:"/dev/projects/ighr/binaries/" )
}catch(Throwable thr){
ant.mail(mailhost:"mail.anywhere.com", subject:"build failure"){
from(address:"buildmaster@anywhere.com", name:"buildmaster")
to(address:"dev-team@anywhere.com", name:"Development Team")
message("Unable to compile ighr’s source.")
}
}
[/groovy]
Where you REALLY need it, you of course are still able to call on any and all of the *nix powertools you might like in a Groovy script. Personally, more and more I find that building and testing the script in my chosen IDE, and using the libraries I’m most comfortable with to do it, is a much more productive and enjoyable experience.
P.S. Gotta apologize about the code formatting – if anyone knows a wordpress syntax highlighting plugin that DOESN’T blow away your formatting or randomly replace the text with html entities, gimme a shout please!