How about a simple GUI where you could type in (or even choose from drop downs, if possible) required properties and run the build by clicking one button? Yes, why not, but we don't want to waste two weeks or more writing such a tool, in Swing for example. Ok, how about Groovy and its brilliant features, like SwingBuilder, AntBuilder and closures? Hmm, that sounds much better!
Recently I have developed such a GUI build tool using Groovy. It took me 2 days to code it. Now guess what features it has:
- full checkout from SVN to a local directory
- project update before each build
- running the old Ant build, written in XML
- intercepting build output for error messages
- reading tool properties from an external XML config
Defining external svn ant task
To get that to work some additional jars are needed. Assuming they are under local lib directory, the svn ant task can be defined like that:
def PATH = "task.path"
ant.path(id:PATH) {
ant.pathelement(location:"lib/ganymed.jar")
ant.pathelement(location:"lib/svnkit.jar")
ant.pathelement(location:"lib/svnant.jar")
ant.pathelement(location:"lib/svnClientAdapter.jar")
ant.pathelement(location:"lib/svnkit-javahl.jar")
}
ant.taskdef(
resource:"org/tigris/subversion/svnant/svnantlib.xml",
classpathref:PATH)
Accessing SVN
Now, having the svn ant task defined, accessing svn (checkout, update etc.) is as easy as:
where the task can be svn checkout:
def svnCall = { task ->
ant.svn(username:USER, password:PASS) {
task()
}
}
or svn update:
svnCall {
ant.checkout(url:url, destpath:dest)
}
svnCall {
ant.update(dir:dest)
}
As you can see there is no code duplication. The ant.svn call is common for all svn tasks. I am passing a closure as a parameter into it, which then can call ant.checkout or ant.update. Closures - it's brilliant, isn't it?
Running an external Ant build and reading output info.
The XML ant build needs to be started from command line (no, we are not going to rewrite it using Gant, not yet ;-) ). How do we do this in Grooovy?
The build variable is actually a Process instance, so we can now intercept the in and err streams:
def build = "cmd /c ant -f build.xml
-propertyfile build.properties target".execute()
build.in.eachLine { line ->
//consume each line
}
build.err.eachLine { line ->
//consume each line
}
Why intercepting the err stream? Well, if the build fails Ant writes BUILD FAILED + the error to that stream. Then I can show an info message using JOptionPane as MsgBOX:
import javax.swing.JOptionPane as MsgBOX
...
MsgBOX.showMessageDialog(gui, message, title,
MsgBOX.INFORMATION_MESSAGE)
The build tool
To give you an idea what the build tool looks like, here is a screenshot (I have removed real labels/data) :
Title borders, drop downs, text fields, labels and box layout - all in 2 days? Yep, plus event handling for all the combo boxes, which make up some sort of hierarchy, actually. This makes the tool a bit complicated, but not the code! Event handling is as easy as clicking a button (actionPerformed as a closure):
and the hierarchy is read from an external XML file, using Groovy's XML parser:
def comboBox = swing.comboBox(items:items,
actionPerformed:action)
Nice and simple, isn't it?
def XML = new File(xmlFile).getText()
root = new XmlParser().parseText(XML)
Summary
It was such a pleasure writing the tool, in no time actually. I have to admit that it was my first bigger piece of Groovy code, which now really works fine in my company! What else can I say - thank you, Groovy! You saved me at least a week of swing coding in Java!
4 comments:
Cool post. I am writing a very similar GUI (to read info from an XML file, and generate Servlet Requests). While my functionality isn't the same, my GUI component layout is very similar. I am struggling getting the layout working for me (I am not very Swing competent). I would love to see your code (not sure if you can share). When I try to put multiple panels on a Frame, only the last one displays. I realize you aren't a support group for Groovy GUI, but you have done exactly what I want to do. At any rate. I found this post very interesting, and wanted to thank you for that. If you can share how you did the layout, it would be cool.
MSW (Phoenix, AZ, USA)
Firs of all, thanks for your comment. In fact, that was the first one on my first post, which I wrote over a year ago! ;-)
Unfortunately I can't share the code, but I think I can show you how to get the right layout. All you need is the BoxLayout, which does the trick of laying out in rows or columns, as in my example. And here is another one, which I've just hacked for you :) It's a simple frame with 3 titled panels with labels and text fields inside, and the panels placed one under the other.
//-------------------------------------------
import groovy.swing.SwingBuilder
import javax.swing.BoxLayout
import javax.swing.JFrame
import javax.swing.border.EtchedBorder
import javax.swing.border.TitledBorder
def swing = new SwingBuilder()
def frame = swing.frame(title:'Frame', size:[300, 200], defaultCloseOperation:JFrame.EXIT_ON_CLOSE) {
boxLayout(axis: BoxLayout.Y_AXIS)
border = new TitledBorder( new EtchedBorder(), 'Titled border')
panel(border: border, preferredSize:[100, 30], size:[100, 30]) {
label(text: "Enter some text: ")
textField(columns: 4)
}
panel(border: border, preferredSize:[100, 30], size:[100, 30]) {
label(text: "Enter some text: ")
textField(columns: 4)
}
panel(border: border, preferredSize:[100, 30], size:[100, 30]) {
label(text: "Enter some text: ")
textField(columns: 4)
}
}
frame.show()
//-------------------------------------------
And that's it!
Hope that helps. Please feel free to drop me a line if you have any trouble getting the right thing.
Thanks,
Marcin
You can also write something like "task.delegate = ant" in your svnCall closure.
Thus you will be able to write innner tasks without need to specify "ant." prefix.
For instance:
svnCall {
update(dir:dest)
}
Thank you, I've recently been looking for info approximately this topic for a while and yours is the best I have came upon till now. But, what concerning the conclusion? Are you sure concerning the source?
Have a look at my website; Florida directory white pages
Post a Comment