The Kaptain on … stuff

19 Apr, 2009

Groovy and Glazed Lists with Grape

Posted by: TheKaptain In: Development

So today while I was cleaning out the garage, I finally got a chance to the listen to the Java Posse podcast on Google Collections and GlazedLists. Google Collections has come in handy a few times, the MultiMap extension most notably. It solves essentially the same kind of problem that I described way back in this little Groovy post.

And recently I had read an article about GlazedLists over on Andres’ blog, so it was great to get some more context around them, especially on how they can greatly simplify development of responsive and scalable Swing tables. It inspired me enough to visit their developer tutorials page and spend an hour watching screencasts. The examples are clear and concise, and the developer, James Lemieux, does a fantastic job of explaining how the different pieces in the GlazedList architecture fit together. If you have a spare hour, well worth watching.

So in the spirit of my last post, it occurred to me how to put this to use on the command line as an example. I chose to do a quick and dirty script for sorting a subset of the results from an ‘svn st’ command run in the current directory. Not terribly useful in its present form, but I think it shows that with a little more effort, you can add some handy utility methods when consuming command line output – namely sorting.

Essentially this is a demonstration of creating a table binding dynamically and baking automatic sorting across multiple columns right into the model. Grape is used to incorporate the GlazedLists functionality, but otherwise all of the dependencies required are available in Groovy 1.6.1. So you can run this directly on the command line of a *nix machine(execute permissions required of course) with very little additional setup. I did have an initial problem with Grape being unable to resolve the GlazedList dependency, but through the magic of Google I found this article which explains how to configure repositories using a grapeConfig.xml file and the problem went away. With no further ado, here’s the entire code.
[groovy language=”true” smarttabs=”true”]
#!/usr/bin/env groovy
import ca.odell.glazedlists.*
import ca.odell.glazedlists.gui.*
import ca.odell.glazedlists.swing.*
import groovy.swing.*
import javax.swing.*

@Grab (group = ‘net.java.dev.glazedlists’, module = ‘glazedlists_java15’, version = ‘1.8.0’)
public class SVNGlazedListExample
{
public static void main(args)
{
def columnNames = [‘Code’, ‘Revision’, ‘Filename’]
def sortedRevisions

//execute on the command line and populate buffers with the output
def sout = new StringBuffer()
def serr = new StringBuffer()
def Process process = "svn stat -u".execute([], new File(‘.’))
process.consumeProcessOutput(sout, serr)
process.waitFor()

SwingBuilder builder = new SwingBuilder();

/**
* closure returns a JComponent showing the buffered output
*/
def getTableModel = {out, err ->
if (err) //Groovy truth FTW
{
//create error output table
return builder.textPane(size: [500, 500], text: err)
}
else
{
//create three column table
def lines = out.toString().split(‘\n’)
def data = []
lines.each() {
def tokens = it.tokenize() //Groovy add which abstract away spaces vs tabs
//a hack to be sure, but let’s just get trebles for now
if (tokens.size() == 3)
{
//rows in the data are just a map
data << [code: tokens[0], revision: tokens[1], filename: tokens[2]]
}
}
//passing in null gives us default String comparator
sortedRevisions = new SortedList(new BasicEventList(data),null)

//this little trick courtesy of Andres Almiray – Thanks!
final EventTableModel model = new EventTableModel(sortedRevisions, [
getColumnCount: {columnNames.size()},
getColumnName: {index -> columnNames[index]},
getColumnValue: {object, index ->
object."${columnNames[index].toLowerCase()}"
}] as TableFormat)

return builder.table(id: ‘revisions’, model: model)
}
}

//the ‘show it’ code
builder.frame(title: ‘SVN Change List’, size: [500, 500], pack: true, show: true,
defaultCloseOperation: WindowConstants.DISPOSE_ON_CLOSE) {
scrollPane {
def component = getTableModel(sout, serr)
//I’m sure this could be more elegant
if(component instanceof JTable){
def tableSorter = new TableComparatorChooser(revisions,
sortedRevisions, AbstractTableComparatorChooser.MULTIPLE_COLUMN_MOUSE)
}
}
}
}
}

[/groovy]

UPDATE: A long time coming, but here’s a screenshot for you Sho.
svnglazedlistexamplescreen

19 Apr, 2009

Twitter Weekly Updates for 2009-04-19

Posted by: TheKaptain In: TweetTweet

  • Cooking conundrum of the day: parsley, is it a vegetable or just a food decoration? #
  • I just entered to win a FREE copy of TweetStack for the iPhone: http://bit.ly/tweetstack You can too! Follow @iphoneincanada and RT! #
  • @ajordens HA. That $2.99 freebie is MINE buddy 😉 in reply to ajordens #
  • I’m wondering how it can possibly be snowing in Victoria in the middle of April? And hailing. Where’s my spring already? #
  • @kerrywright I was pretty sure I saw your name pop up on http://cursebird.com/ in reply to kerrywright #
  • RT @iphoneincanada: RT @VanCanucks: #canuckstix Retweet this message by Apr14th @ 5pm for your chance to win a pair of tickets to Wed’s … #
  • RT @VanCanucks: #canuckstix Retweet this message by Apr14th @ 5pm for your chance to win a pair of tickets to Wed’s playoff game! #
  • If I happen to win Canucks tickets? I can auction them off at work 🙂 #
  • How bad does Jimmy Fallon have to be before you change to the last 15 minutes in Groundhog Day? You didn’t see tonite’s show 🙁 #
  • Epic fail upgrading to Seam 2.1.2.CR1. Nice – they changed some concrete classes into abstract ones. New conrete class is package-private:( #
  • @ChantelleJoytwt sign me up for a chance to win the white Acoustibuds please #
  • @mosabua How’s the happy daddy? Missing you back at work – lots of good tooling discussions going on! in reply to mosabua #
  • Grails has a GAE plugin already! These boys just can’t wait to play in the clouds. http://bit.ly/1aBOYa #
  • Great day for a walk. The fresh air feels good after a morning of meetings. now back to work. #

Powered by Twitter Tools.

Tags: ,

14 Apr, 2009

Groovy and Bash – can scripting get much easier?

Posted by: TheKaptain In: Development

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!

12 Apr, 2009

Twitter Weekly Updates for 2009-04-12

Posted by: TheKaptain In: TweetTweet

  • Tis a beautiful day in Victoria. Time to take the dogs out for a nice long walk. #
  • SwingLabs site is open for business again with a brand new point release http://swinglabs.org/downloads.jsp #
  • @mosabua Congratz Manfred and Yen! #
  • Up WAY too late, but with Griffon+SwingX+FEST I was just having way too much fun. #
  • @alexRuiz My pleasure. It’s a great tool so far, very versatile + intuitive. in reply to alexRuiz #
  • Jumping on the bandwagon. Just got my GAE account confirmation
    🙂 #
  • Good offsite for the dev team today. Fixin bugs is always nicer w/ cookies, Rockband and beer #
  • Bonus holiday today – got the lawn mower #
  • R #
  • @kerrywright Scala/java/groovy – bring it on! That’s a cloud I would like work on anyway u cut it. #

Powered by Twitter Tools.

Tags: ,

10 Apr, 2009

More Groovy/Griffon/FEST Testing

Posted by: TheKaptain In: Development

In my continuing exploration of FEST testing using Groovy and the Griffon framework, I’ve added some tests for the ability to change the JXBusyLabel coloration on the fly.

Since FEST allows you to alter the properties of the widgets directly, I didn’t have to do anything special to trigger actions on the JXColorSelectionButton. At first look, I thought that specifying mouse click point locations would be necessary, but after digging a(very little) bit I discoveregroovyd that FEST exposes the underlying Component its’ Fixture classes wrap as an internal ‘target’. Simply grabbing that Component and settings the background color directly was sufficient.
Here is the new definition of the JXBusyLabel and the 3 buttons which controls its color changes. You can see that two of the three color changes happen automagically due to Groovy binding – setting the background color of the label didn’t appear to work for some reason that I have yet to puzzle out, so it gets a PropertyChangeListener ‘old school style’.

[groovy language=”true” smarttabs=”true”]
baseColBtn = colorButton(name: ‘baseColBtn’, background: model.baseColor)
highColBtn = colorButton(name: ‘highColBtn’, background: model.busyColor)
backColBtn = colorButton(name: ‘backColBtn’, background: PaintUtils.BLUE_EXPERIENCE.getColor1())
backColBtn.addPropertyChangeListener("background", {PropertyChangeEvent evt ->
label.setBackground((Color) evt.getNewValue())
label.setOpaque(true)
} as PropertyChangeListener)

label = jxbusyLabel(name: ‘busyLabel’,
preferredSize: new Dimension(model.W / 2 as int, model.H / 2 as int),
busyPainter: busyPainter(
highlightColor: bind { highColBtn.background }, baseColor: bind {baseColBtn.background},
points: bind {slider.value}, trailLength: bind {tSlider.value}),
opaque: false,
horizontalAlignment: JLabel.CENTER,
delay: bind {speedSlider.value},
background: bind{backColBtn.background})
[/groovy]

The three associated tests are essentially using the same recipe, so here’s just one of them to give you the idea.

[groovy language=”true” smarttabs=”true”]
/**
* Test that changing the ‘baseColBtn’ background color simultaneously
* changes the busy label’s base color.
*/
@Test void testBaseColorChange() {
startAnimation()
def button = window.button(‘baseColBtn’)
def busyLabel = findBusyLabel()
Color start = button.target.background
Color busyStart = busyLabel.busyPainter.baseColor
Assert.assertEquals(busyStart, start)

button.target.background = Color.RED

Assert.assertFalse(button.target.background == start)
Assert.assertFalse(busyLabel.busyPainter.baseColor == busyStart)
Assert.assertEquals(busyLabel.busyPainter.baseColor, Color.RED)
}
[/groovy]

Running the test suite takes less than a minute, and most of that time is spend dragging sliders. Those tests are presently going through the entire range of the slider, which is reassuring when actually watching the tests run, but probably overkill in terms of testing. Considering that, running the test suite is pretty painless and quick(the new tests execute in < 1s for instance). And of course the test results are available in the standard, pleasing, and hopefully all green, TestNG output. Which has, by the way, just announced another release thanks very much to its creator Cedric Beust.

I am still having some difficulties in responding to change events on the other sliders in the demo, but I think that I just need to decompose the parts into the MVC structure a little more coherently. In particular, when some sliders are moved, it should trigger some calculations and a repaint of the busy label to reflect the changes(not simple properties that can utilize binding directly). While the original code declares the method inline, I’ve moved it to the controller class and run into some circular dependency problems between the components referenced therein – Component A needs Component B but it hasn’t been instantiated yet in the view, etc. It looks like what is happening is that the change listener is being triggered once when it is assigned to the component, which might be a problem anywhere in Swing/Groovy/Griffon/my implementation. My money is on my own impl, mostly based on the common sense that when you’re writing code in an unfamiliar area you’re bound to meet problems that don’t immediately suggest a solution.

We’ll just have to keep digging and see. 🙂

[nggallery id=2]

08 Apr, 2009

Griffon SwingX Fest testing

Posted by: TheKaptain In: Development

This is the third installment of my Griffon SwingSet experiment. If you’re coming late to the party (and would like to know just what the heck I’m talking about) you can catch up by reading this and this.

So the SwingX demo has 3 sliders that affect integer values on the JXBusyLabel. Using the Groovy ‘bind’ syntax, responding to changes in these events is simple to say the least.

And as promised in the last post, I’ve written some FEST tests to validate that everything is working as expected. Stay tuned to the end of the post to see a video of the running tests 🙂

FEST provides some convenience wrappers for UI elements that allows easy access to common operations. Looking up a JSlider in the UI for instance, returns a JSliderFixture object with a nice little ‘slideTo’ method.
First off, here are the UI components under test. Yes, this is the entire code, including all necessary wiring to trigger updates automagically as the sliders are changed.
[groovy language=”true” smarttabs=”true”]
speedSlider = slider(
name: ‘speedSlider’,
sliderModel: boundedRangeModel(
min: 1, max: model.SPEED_MAX – 1, value: model.SPEED_MAX – 1, extent: 0),
opaque: true)

slider = slider(
name: ‘slider’,
sliderModel: boundedRangeModel(
min: 1, max: 50, value: 8, extent: 0), opaque: true)

tSlider = slider(
name: ‘tSlider’,
sliderModel: boundedRangeModel(
min: 1, max: 20, value: 4, extent: 0), opaque: true)

label = jxbusyLabel(name: ‘busyLabel’,
preferredSize: new Dimension(model.W / 2 as int, model.H / 2 as int),
busyPainter: busyPainter(
highlightColor: bind { model.busyColor }, baseColor: bind {model.baseColor},
points: bind{slider.value}, trailLength: bind{tSlider.value}),
opaque: false,
horizontalAlignment: JLabel.CENTER,
delay: bind{speedSlider.value})
……..
buttons.addLine(button(name: model.START_NAME, action:startAction))
[/groovy]

And then the tests run against them. Each test moves a slider sequentially from the minimum to the maximum values and checks at each change to ensure that the same change is reflected on the bound JXBusyLabel property. Because the JXBusyLabel does not have a ready corresponding FEST built in fixture class, we just look it up as a Component by inspecting the UI for the appropriate named Component. The Groovy dynamic type system makes accessing its internal properties trivial after that.

[groovy language=”true” smarttabs=”true”]
/**
* Start the animation and then ensure that changing the speed slider changes the delay.
*/
@Test void testSpeedSlider() {
def button = window.button(JXBusyLabelDemoModel.START_NAME)
button.click()
def JSliderFixture slider = window.slider(‘speedSlider’)
ComponentFinder finder = BasicComponentFinder.finderWithCurrentAwtHierarchy();
def busyLabel = finder.findByName(app.appFrames[0], ‘busyLabel’)
Assert.assertNotNull(slider)
Assert.assertNotNull(busyLabel)
(1..JXBusyLabelDemoModel.SPEED_MAX – 1).each { speed ->
slider.slideTo(speed)
Assert.assertEquals(busyLabel.delay, speed)
}
}

/**
* Start the animation and then ensure that changing the points slider changes the
* number of points.
*/
@Test void testPointsSlider() {
def button = window.button(JXBusyLabelDemoModel.START_NAME)
button.click()
def JSliderFixture slider = window.slider(‘slider’)
ComponentFinder finder = BasicComponentFinder.finderWithCurrentAwtHierarchy();
def busyLabel = finder.findByName(app.appFrames[0], ‘busyLabel’)
Assert.assertNotNull(slider)
Assert.assertNotNull(busyLabel)
(1..50).each { points ->
slider.slideTo(points)
Assert.assertEquals(busyLabel.busyPainter.points, points)
}
}

/**
* Start the animation and then ensure that changing the trail slider changes
* the trailLength.
*/
@Test void testTrailSlider() {
def button = window.button(JXBusyLabelDemoModel.START_NAME)
button.click()
def JSliderFixture slider = window.slider(‘tSlider’)
ComponentFinder finder = BasicComponentFinder.finderWithCurrentAwtHierarchy();
def busyLabel = finder.findByName(app.appFrames[0], ‘busyLabel’)
Assert.assertNotNull(slider)
Assert.assertNotNull(busyLabel)
(1..20).each { trailLength ->
slider.slideTo(trailLength)
Assert.assertEquals(busyLabel.busyPainter.trailLength, trailLength)
}
}
[/groovy]

It’s particular amusing to note that the test code is more verbose than the Swing component setup. Man, after all of the Swing code I’ve written, WHY WAS NONE OF IT EVER THIS EASY!
Sorry for the shouting, but it’s late and updating this code to use binding instead of change listeners AND writing the tests AND writing this blog post took all of about 45 minutes. So you’ll have to forgive me for getting excited and all.

Here is the promised video showing the FEST test suite being run.. Give it a second as the first round of tests(not shown in the code above) do a bunch of assertions to make sure that all of the expected Components can be found. Not terribly interesting to watch, but a great win for Java GUI testing!