A Few Ribbons Around The Griffon's Tail

Following on from my earlier experiment with Griffon, I thought I'd have a play with a few more plugins.

First ribbon to hang around the Griffon's tail was the CodeNarc Groovy-oriented static analysis plugin.

Installation was a little rough: the usual magic invocation:

griffon install-plugin codenarc

didn't work. I had to download the plugins's zip by hand and install it as:

griffon install-plugin griffon-codenarc-0.1.zip

Once that minor hurdle was overcome, however, it was a smooth as silk!

Running:

griffon codenarc

produced a simple report called "CodeNarcAntReport.html" in the project's root directory:

The code looks pretty good…a few "no-no's" there, but otherwise things are OK.

Although I didn't change any options for this little investigation, it's worthwhile noting that the plugin is configurable through a number of entries in griffon-app/conf/Config.groovy.

The second ribbon to adorn my increasingly-beautiful Griffon was the splashscreen plugin.

This time, installation went brainlessly well:

griffon install-plugin splash

The plugin adds a couple of lines of code to griffon-app/lifecycle/Initialize.groovy:

def splashScreen = SplashScreen.getInstance()

// Setting a splash image
//URL url = this.class.getResource("mySplash.jpg")
//splashScreen.setImage(url)
//
// Setting Status Text
// SplashScreen.getInstance().showStatus("Initializing the Controller")
splashScreen.splash()
splashScreen.waitForSplash()

It's pretty clear how this works, 'nuff said?

It's pretty early days for Griffon, so there isn't (yet) an extensive list of plugins. It's a great facility, though and I am sure that people will bring more to the table as time goes by.

My Griffon's a bit more beautiful now. What bells and whistles are you going to add to yours?

Tags: Griffon, Groovy, Programming

Converting Legacy Rails Apps To Grails

Gotta love the title! And the chutzpah!

There's a series over on Alex Kotchnev's Blog that aims to convert a Rails app to a Grails one.

Here's the opening paragraph:

It is hard to describe the pleasure of writing the title above, especially the "legacy" part :-) Although lately the jumping up and down of Ruby & Rails fanboys has subsided a little, after people started realizing that Rails is not going to kill anything (much less Java, hell if PHP people start going back to PHP that says A LOT!!!).

He uses Netbeans to assisst.

So, now that you have all this good info, START MIGRATING THAT RAILS APP THAT YOU'VE BEEN EYEING, WOULD YA !!???!!!

Tags: Grails, Programming

GroovyMag June Issue…Now 80% Bob Brown Free!

Another GroovyMag article.

This time I'm blathering on about using Groovy with Spring Batch.

Worth every cent of the USD$4.99.

[edit]
Some feedback from one happy reader:

Hi Bob,

Thanks for the hint. This is an excellent article.

It should not be to difficult now, to integrate spring-batch with grails-apps…

Tags: Groovy, GroovyMag, Programming

Absolutely!

(http://www.overclock … newspics/5jun/14.jpg)

Nicely skewers the "CSS positioning is the best technology since sliced bread" brigade!

There must be tens of millions of pages out there that look just like this…

Tags: Rant

National "Change Your Password Day"

Today.

Just do it.

The Australian Federal Government has a site promoting National E-security Awareness Week 2009.

A Little Griffon Tip

I just want to ensure that I remember this tip. How better to do it than to post it here…

import java.awt.Graphics
import groovy.swing.SwingBuilder
import javax.swing.JPanel
import java.awt.Color

class CanvasPanel extends JPanel {
   Closure draw

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g)
      if(draw) draw(this,g)
   }
}

Usage is as simple as:

new SwingBuilder().edt {
  frame( title: "RED", size: [200,200], visible: true ) {
    panel( new CanvasPanel(draw: { p, g ->
       g.color = Color.RED
       g.fillRect 0, 0, p.width, p.height
    }))
  }

Here's the result:

I know it is extremely simple, but it's the sort of thing that can be very useful and is also just the sort of thing that slips one's mind!

Thanks to Andres Almiray!

Tags: Griffon, Groovy, Programming

Riding The Griffon

Here's a first for this website: a real, (hopefully) useful desktop application for you to take home and play with!

Here it is, all zipped up and ready to go. See the enclosed README.txt for wise words regarding how to use it.

I had the brilliant idea of using my MFC device (an HP OfficeJet 7410) to scan multiple happy snaps in one go. While this idea would undoubtedly save me scanning time, it leaves the problem of how to extract these multiple images from a single scan, such as the one shown here:

You can see the major problem with this idea: the various 'real' images will be placed on the scanner bed haphazardly and so will be rotated at odd angles. Processing with a 'normal' application (such as the excellent Paint.NET) would require too much grunt work for my taste, quickly leading to boredom and possible RSI.

I couldn't find anything out there in the GoogleVerse that did what I wanted so I took this as a challenge and did what any self-respecting programming nerd would do: wrote my own application. 'GT' lets me select the boundary of an embedded image within a scan file, and then extract and automatically rotate the desired image ready for saving as a PNG file.

Since I am quickly becoming a GR8 (Groovy/Grails/Griffon/Gant/…) tragic, Griffon was the natural choice for this little project.

Although it is early days yet for the project, Griffon aims to bring the same "Configuration by Convention" goodness to desktop GUI development that Grails has brought to Web development. In fact, Griffon 'borrows' heavily from Grails: many of the build scripts, etc. are straight carry-overs, meaning that anybody familiar with Grails can get started easily.

This is all that is needed to get started:

griffon create-app GT
cd GT
griffon run-app

These three shell commands give a simple immediately runnable application:

As with Grails, Griffon imposes a clear MVC structure for the code and also creates a standrd project filesystem heirarchy:

Simplicity is the watchword, as can be seen by looking at the code statistics for the finished application:

Note that the bulk of the application lies in the 3rd party Java graphics-processing code and this is what inflates the lines of code statistics.

While I'm here, a big "thank you" is due to prometheuzz for making the code for the "Rotating Calipers" algorithm available (see the Java package bk.geom.rotatingcalipers). This algorithm is used to find the bounding box of a polygon, regardless of whether that polygon is absolutely aligned with the XY axes or not. There is a good demonstration applet of this at http://www.iruimte.nl/calipers/.

Enough background. Time to take a short ramble through (the most important parts of) the MVC triad…

models/GTModel.groovy

import groovy.beans.Bindable
import javax.swing.ImageIcon

class GTModel {
  [...elided...]
  @Bindable boolean saveAsEnabled = false
  @Bindable String file
  @Bindable ImageIcon image
  @Bindable ImageIcon destinationImage
  @Bindable String labelText = 'Welcome!'
}

In a typical Swing application, bits of model typically get spread through various components. By bringing everything together, Griffon makes it much easier to understand what's what.

This excerpt also shows one of the nicest things about Griffon: the @Bindable annotation, which encapsulates the observerable/observer pattern. We'll come back to this in a while.

views/GTView.groovy

Simple! A thing of beauty…

import static java.awt.BorderLayout.*
import javax.swing.JSplitPane
import java.awt.Color

build(GTActions)

application(title: 'GT',
            pack: true,
            locationByPlatform: true,
            iconImage: imageIcon('/griffon-icon-48x48.png').image,
            iconImages: [imageIcon('/griffon-icon-48x48.png').image,
            imageIcon('/griffon-icon-32x32.png').image,
            imageIcon('/griffon-icon-16x16.png').image]
) {

  menuBar(build(GTMenuBar))

  panel(border: emptyBorder(6)) {
    borderLayout()
    splitPane(id: "splitter",
              preferredSize: [1024, 768],
              dividerLocation: 512,
              orientation: JSplitPane.HORIZONTAL_SPLIT,
              constraints: CENTER,
              border: lineBorder(color: Color.BLACK, thickness: 1)) {
      panel(id: 'sourceImagePanel') {
        borderLayout()
        build(GTSourceImagePanel)
      }
      panel(id: 'destinationImagePanel') {
        borderLayout()
        build(GTDestinationImagePanel)
      }
    }
    label(id: 'status',
          constraints: SOUTH,
          border: emptyBorder(4),
          text: bind { model.labelText })
  }
}

For those familiar with plain Java Swing, this should be a complete breath of fresh air.

Very little glue code is required here; the Swing containment hierarchy is clear and the layout policies are easy to see.

Some may be happy to see that there are no anonymous inner classes in use: Groovy's closures allow for much a cleaner implementation. I've been teaching Java since about 1998 and I have observed that course participants often have trouble 'trusting' anonymous inner classes. Even though they are custom-designed for the sort of glue code required to join a button and its action together, I have observed that many participants' first instinct is to avoid them. It hasn't helped that many IDEs haven't worked well with them, either. Hopefully, closures will be more easily comprehended and thus better accepted.

The 'status' label shows how the model.labelText is 'automagically' bound to the 'text' property in the label component. Any changes to model.labelText (as will be seen in the controller code, later) will be reflected in the label's text value. Once again, this substantially helps to cleans up the code.

Griffon allows complex code to be broken into sub-scripts that are then included via the build() method. This technique is used to isolate action definitions and menu definitions and also to "break down" the various panel content GUIs into separate files for ease of comprehension.

Griffon allows Swing-style action definitions to be streamlined, as shown in this excerpt from views/GTActions.groovy:

actions {
  action(id: 'saveAsAction',
         name: 'Save As...',
         mnemonic: 'S',
         smallIcon: builder.imageIcon("/disk.png"),
         accelerator: shortcut('S'),
         enabled: bind { model.saveAsEnabled },
         closure: controller.saveAsActionClosure
  )
  action(id: 'mirrorYAction',
         name: 'Mirror on Y Axis',
         smallIcon: builder.imageIcon('/shape_flip_vertical.png'),
         enabled: bind { model.saveAsEnabled },
         closure: controller.mirrorYActionClosure
  )
[...elided...]
}

It is easy to see the Griffon 'goodness' here: the use of closures, the use of bindings, the use of the GUI builder facilies (to obtain an appropriate icon resource), and shortcut handling. Taken together, this gives a clean, declarative style that I find very valuable.

(By the way, for plain Swing, the Swing Action Manager provides somewhat similar capabilities…).

The use of the actions can be seen in this excerpt from views/GTMenuBar.groovy:

import static griffon.util.GriffonApplicationUtils.*

menuBar = menuBar {
  if (!isMacOSX) {
    menu(text: 'File', mnemonic: 'F') {
      menuItem(exitAction)
    }
  }
  menu(text: 'Source', mnemonic: 'S') {
    menuItem(openAction)
    separator()
    menuItem(extractAction)
    menuItem(clearAction)
  }
[...elided...]
}

return menuBar

It is also interesting to see that Griffon makes it easy to keep the various platform-specific foibles in mind.

To round off this tour through the view's code, here is the views/GTDestinationImagePanel.groovy file:

import static java.awt.BorderLayout.*
import javax.swing.JLabel
import java.awt.Color
import org.jdesktop.swingx.painter.PinstripePainter

jxheader(title: "Destination",
         description: 'Display and manipulate the isolated portion of the source image.',
         border: emptyBorder(4),
         constraints: NORTH)
scrollPane(id: 'scrollPane',
           constraints: CENTER) {
  jxlabel(id: 'destination',
          icon: bind { model.destinationImage },
          constraints: CENTER,
          horizontalAlignment: JLabel.CENTER_ALIGNMENT,
          border: loweredBevelBorder(),
          backgroundPainter: new PinstripePainter(Color.LIGHT_GRAY))
}
hbox(constraints: SOUTH, border: emptyBorder(4)) {
  button(rotate90LeftAction, text: '')
  hstrut(8)
  button(rotate90RightAction, text: '')
  hstrut(8)
  button(mirrorXAction, text: '')
  hstrut(8)
  button(mirrorYAction, text: '')
  hglue()
  button(saveAsAction)
}

The most interesting aspect of this code is the way that the facilities made available by the use of the SwingXBuilder Plugin (jxheader, jxlabel and the PinstripePainter background painter) are seamlessly incorporated into the view.

This is really quite pretty code; it would be beautiful but for the various import statements. I'd like Griffon (or perhaps Groovy itself: there's something similar afoot with respect to Grape, but this isn't quite the same thing…) to do something about them…they seem somehow 'ugly' and don't really add much to things.

controllers/GTController.groovy

This is the third major part of the MVC triumvirate.

Here's a fairly cut-down overview of the controller:

class GTController {

  def model
  def view
  def builder

  def saveAsActionClosure = {evt = null ->
    def file = selectFileForSave()
    if (!file)
      return
    ImageIO.write(view.destination.icon.image, "png", file)
    model.labelText = "Saved as $file.name..."
  }

  def mirrorYActionClosure = {evt = null ->
    doOutside {
      def img = toBufferedImage(model.destinationImage.image)
      AffineTransform transform = AffineTransform.getScaleInstance(1, -1)
      transform.translate(0, -img.height)
      AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR)
      img = op.filter(img, null)
      edt {
        model.destinationImage = new ImageIcon(img)
      }
    }
  }

  def exit = {evt = null ->
    app.shutdown()
  }

[...elided...]
}

Things worthy of notice here include: the injection of the builder, model and view components (note that views get the builder implicitly), the action closures (that are referenced from the actions shown earlier) and the 'exit' closure that directly references the implictly available 'app' instance.

It is also worth noting the assignment to the bound property 'model.labelText.'

Of particular note is the way that Griffon eases the burden of managing threading. Swing threading is (sadly!) probably the most misunderstood and mis-applied aspect of the whole of Java. Unfortunately, it is also the area that has the most effect on making an application 'feel' good. Bob's rule for Swing GUIs is: "GUI updates have to be on the Event Dispatch Thread (EDT), but you must never do any long-running non-GUI-related task on the EDT." Each action is executed on the EDT, in true Swing fashion. Griffon makes it easy to follow Bob's rule by providing the doOutside method that allows the single Swing GUI thread to remain 'live' while the actual work is done in another (background) thread. Griffon also supplies the edt method for when things (like GUI updates) simply have to be done on the EDT, and doLater which allows Swing to decide when it is free enough to handle a long-running GUI-updating activity.

There's more on Griffon and threading here.

Other
There's a lot more Good Stuff that Griffon gives you. For example, the Griffon Quick Start says:

The run-app script implies the execution of the package script. The package script creates file artifacts suitable for a Java application, a WebStart application, and an Applet, with code signed by a self-signed certificate

That's a significant piece of added value just there!

Griffon's plugins scheme is also a Real Good Idea and there are an ever-growing number of plugins to be had, from the SwingXBuilder plugin that I have used here, through to things like a standard "splash screen" facility and various testing/code coverage tools.

Don't forget the i18n support and standardized resource handling!

And don't forget testing…although I haven't actually used it in for this application (bad boy, Bob!), Griffon generates placeholders for integration/unit testing.

Griffon also creates an ant script (not Gant, shame!) for the project.

I may end up eating my words in future (wouldn't be the first time!) as Flash/Flex and Silverlight fade into obscurity, but I feel fairly safe saying that IMHO, Griffon beats the ill-conceived (and probably ill-fated) JavaFX technology hands-down. Even though JavaFX is technologically quite good, I'm not betting my house on it. In any case, the use of one doesn't preclude the use of the other, as this posting (to take but one simple example) shows.

Despite all protestations to the contrary, the JSR 269 Swing AppFramework work seems stillborn.

Griffon seems to me to have a much rosier future ahead of it than either JavaFX or AppFramework. If you haven't already done so, ride the Griffon, you won't be sorry!

Tags: Grails, Griffon, Groovy, Programming

The Bumper List Of Windows 7 Secrets

I learned a few useful tidbits from this MSDN Blog posting.

Check out numbers 3,4,6,7,19 and 20…

While I'm on the Windows 7 track: this posting showed me how to mount a VHD file. Useful!

Keep Taking The Valium, Guys

Just finished reading Extreme Programming Refactored: The Case Against XP:

And I thought I was a master of ranting! Compared to these guys, I am nothing! Nothing, I tell you!

There's actually some truth in the message here. There is a lot of thought-provoking material (the "XP From the Trenches" stuff tends to be quite interesting), and the book really does bear reading.

Getting to the end was hard though, not because I disagree with the what the authors are saying, but the way they say it rather destroys their credibility.

Shorts rants can be effective, but a book-sized rant is wearisome.

The authors come across as having massive chips on their shoulders…their dislike for pair programming seems boundless, and their disdain for XP's prediliction for "oral documention"…well:


(snapshot taken from amazon.com's "look inside" book review feature)

It's not often that one finds the phrase "What a load of crap!" in a technical book. Sadly.

I hope that the royalties from my purchase can gainfully contribute to the authors' pharmaceutical needs. Or rehab. Whichever is most beneficial.

Tags: Books

Oh The Pain!

To quote the legendary Dr. Zachary Smith.

Recently had a meeting with a colleague, talking about a customer's requirements and how best to fulfil them.

Both he and I are veteran Java-heads.

Imagine our pain when we pretty much settled on Joomla!

Neither Liferay nor dotCMS quite scratched the itch…

I feel unclean :-)

OTOH, looking for any positives that might be hanging around: it'll be good to see life on the other side of the tracks…