SpringOne Americas

Private Events

Blogs

View all Blogs >>
  • Howard Lewis Ship

    Creator of Tapestry and HiveMind

    It took a lot of ferreting out, but I eventually learned that you can put a <version/> tag in your site.xml, and Maven will put the... more»

  • Brian Pontarelli

    Founder of Inversoft

    Just figured out how to get git tab completion working in zsh on a Mac. Turns out that the completion scripts use a bunch of extra git... more»

  • Stuart Halloway

    CEO of Relevance

    Steve Yegge's most recent post takes more»

  • Mike Levin

    Software Developer specializing in Web2.0 websites

    more»

  • Erik Doernenburg

    Principal Consultant @ Thoughtworks

    If you are somebody who writes code you probably know that moment when you look at some code you didn’t write, or some code you wrote a... more»

  • Kirk Knoernschild

    Software Developer & Mentor

    more»

  • Richard Monson-Haefel

    VP of Developer Relations, Curl Inc.

    more»

  • Alex Miller

    Sr. Engineer with Terracotta Inc.

    Start your engines kids - the JavaOne 2009 more»

  • Brian Goetz

    Author of Java Concurrency in Practice

    I live in an AT&T-free state, so I have not had access to the cult that is iPhone. But recently, in preparation for AT&T moving... more»

  • Matthew Bass

    Software Developer & Entrepreneur

    Can Sphinx and foxy fixtures place nicely together? Due to the way Sphinx indexing works, foxy fixtures will often slow down the indexing... more»

  • Jason Rudolph

    Author of Getting Started with Grails

    I had the more»

  • Ryan Shriver

    Business and Technology Consulting

    more»

  • Neal Ford

    Application Architect at ThoughtWorks, Inc.

    One of the techniques I more»

  • Michael Nygard

    Agile technology leader and dynamicist

    Patrick Muellr has an interesting post about being more»

  • Nathaniel Schutta

    Author, speaker, software engineer focused on user interface design.

    Today we learned something important, the NTSB announced the more»

  • Jeff Brown

    SpringSource Engineering And Professional Services - Groovy and Grails Developer

    Strange enough title.Let's start with a hypothetical conversation between a geeky developer and his much less geeky wife: more»

  • Ted Neward

    Enterprise, Virtual Machine and Language Wonk

    ... Corey Vidal, you have outdone every YouTube video I've ever seen, and I was a hug more»

  • Pratik Patel

    Enterprise Architect

    SpringSource today announced that it has purchased G2One, the folks who have been driving the development of Groovy and Grails. The following... more»

  • Graeme Rocher

    Project Lead of the Grails Project & CTO of G2One

    You may have already read about it in the various news outlets and blogs covering the announcement, but if you haven’t I’m excited to spread... more»

  • Andrew Glover

    Co-author of "Continuous Integration"

    more»

  • Matt Raible

    Creator of AppFuse and author of Spring Live

    This morning, my co-workers and I discovered that Link edIn decided to trim 10% of its employees. The Denver Offi more»

  • Jared Richardson

    Agile coach and co-author of Ship It

    Jurgen Appelo has an ongoing interview series on his blog. He's published a lot of very smart people and I'm honored to squeak in too! ;) more»

  • David Bock

    Principal Consultant, CodeSherpas Inc.

    I have been setting up a rock-solid server cluster for a client and ran into an interesting issue trying to install Phusion Passenger onto... more»

  • Pramod Sadalage

    Co-author of "Refactoring Databases:Evolutionary Database Development"

    Consider this Hibernate mapping @Column(name = "qReferenceId") public Long getQReferenceId() { return qReferenceId; more»

  • Craig Walls

    Author of Spring in Action

    At one time not too long ago, I wasn't a big fan of annotations. But then I let my guard down and even started liking them. But now I'm... more»

  • Scott Leberknight

    Chief Architect at Near Infinity

    In late 2006 Neal Ford wrote about Polyglot Programming and predicted more»

  • Kenneth Kousen

    President of Kousen IT, Inc.

    In this entry in my “Making Swing Groovy” series, I want to talk about threading issues. Specifically, more»

  • Venkat Subramaniam

    Founder of Agile Developer, Inc.

    I wrote a four part article for Java World on creating DSLs in Java and Groovy. For your convenience, I decided to list the links to those... more»

  • Jason Harwig

    Senior Software Engineer at Near Infinity

    The most popular entry I've written at Near Infinity has been the more»

  • John Heintz

    Principal Consultant with New Aspects of Software

    In a recent discussion interview questions came up, here's my favorite one.To set some context this question is designed to gauge the abst more»

  • Mark Johnson

    Director of Consulting at CGI

    At the Columbus NFJS show held on July 25-27th during one of the BOF sessions Dave Bock, Scott Davis and I discussed unit tests vs functional... more»

  • Joseph Nusairat

    Author of Beginning JBoss Seam & Co-Author of Beginning Groovy & Grails

    Well i am assuming Apress has the most random site in the world at times.But today only they have our recent book, Beginning Groovy & Grai more»

  • Keith Donald

    Lead of Spring Web and Creator of Spring Web Flow

    I am pleased to announce that Developing Rich Web Applications with Spring, a three-day bootcamp lead by SpringSource engineers on web... more»

  • Vladimir Vivien

    Software Engineer / Consultant

    Judging from the list of features that will be included in NetBeans 6.5, more»

  • Pete Behrens

    Organizational Agility Coach

    Marti nig & Associates Methods & Tools group recentl more»

  • Brian Sam-Bodden

    Java author, Ruby geek and Open Source Advocate

    In this installment we are going to build the Dashboard page of the Tempo application. T more»

  • Mark Fisher

    Spring Integration Lead

    In my recent post, I had mentio more»

  • Ron Bodkin

    Chief Software Architect, Quantcast

    I'm looking forward to speaking at The Rich Web Experience conference in San Jose next month. The event runs from September 7th through 9th.... more»

  • Mark Goodwin

    Web Application Security Specialist

    We've already looked at one of the two big problems posed by anti DNS pinning on Java applets; because there's rebinding on the applet and... more»

  • Scott Davis

    Author of "Groovy Recipes" & TDD Expert

    Every time I see a live show at the Denver Botanic more»

  • Romain Guy

    Java User Interface expert.

    more»

  • Ramnivas Laddad

    Author of AspectJ in Action, Principal at SpringSource

    InfoQ.com has published my AOP myths and realities talk recorded at a No Fluff Just Stuff conference. InfoQ.com founded by Floyd Marine more»

  • David Geary

    Author of Graphic Java and co-author of Core JSF

    The 2006 NFJS tour kicked off t more»

  • Kito Mann

    Editor-in-chief of JSF Central and the author of JSF in Action

    One of the enhancements added for JSF 1.2 was update of the MethodExpression signature for the action attribute of h:command{Link,Button}. In... more»

  • Jason Hunter

    Author of Java Servlet Programming

    I just posted the JDOM 1.1 release for download. This release includes about 20 improvements and bug fixes. more»

In the Spotlight - Kenneth Kousen

Kenneth Kousen

President of Kousen IT, Inc.

Ken Kousen is the President of Kousen IT, Inc., through which he does technical training, mentoring, and consulting in all areas of Java and XML. He has been a tech reviewer for several books on software development. Over the past eight years he's taught hundreds of training courses involving thousands of developers in business and industry. He is also an adjunct professor at the Rennselaer Polytechnic Institute site in Hartford, CT. Academically, he has way too many degrees, including two Bachelor's, two Master's, and Ph.D.























Presentations by Kenneth Kousen

Groovy by Example

A good way to understand how a language works is to collect examples where it is used in practice. That makes it easy to see which features of the language are likely to arise naturally to simplify your work. "

Grails Plugins: A Free Library of Functionality

One of the best features of the Grails platform is that its modular architecture makes developing plugins very easy. As a result, many, many plugins have already been developed, with the number growing almost daily. "









Stuff I've learned recently...
I teach this stuff. I didn't say I could do it.


Kenneth Kousen's complete blog can be found at: http://kousenit.wordpress.com

Monday, October 13, 2008


In this entry in my “Making Swing Groovy” series, I want to talk about threading issues. Specifically, how to work with the Event Dispatch Thread. As a step along the way, let me first respond to a comment made about my first post in this series.

Kirill Grouchnikov collects interesting Swing-related links every week. He was kind enough to link to my first post, and rightly pointed out that in my Java example, I’d make some errors. As he said,

“… the Swing example is not the best one, violating the EDT rules, working with the content pane and not centering the frame in the monitor, and the author admits some of these points.”

Let me say up front that I’m grateful for his comments. That’s how I learn. Part of the reason I post here (other than just the joy of sharing what I’ve learned) is to find out what I’ve been doing wrong, or, if I’m okay, what I can do better. One of the principles I live by is, “I’m often wrong, but I don’t stay wrong.” So keep those cards and letters coming. :)

Here’s the code that Kirill addressed:


import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class EchoGUI extends JFrame {
	private JTextField input = new JTextField(20);
	private JLabel prompt = new JLabel("Input text: ");
	private JLabel echo = new JLabel("Echo: ");
	private JLabel output = new JLabel();

	private Container cp = this.getContentPane();

	public EchoGUI() {
		super("Echo GUI");
		cp.setLayout(new GridLayout(0,2));  // 2 cols, as many rows as necessary

		cp.add(prompt);
		cp.add(input);
		cp.add(echo);
		cp.add(output);

		input.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				output.setText(input.getText());
			}
		});

		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(300,100);
		setVisible(true);
	}

	public static void main(String[] args) {
		new EchoGUI();
	}
}

First, Kirill was right about my working with the content pane rather than adding my components directly to the JFrame instance. I remember way back in the Java 1.0 days (holy AWT, Batman), you added components directly to the instance of java.awt.Frame. Then, when Swing came along, you weren’t supposed to do that any more. Instead, you added to the content pane in front of the JFrame. That held true for Java 1.2, 1.3, and 1.4. Finally, in Java 1.5, you could go directly to the JFrame again, because now adding to the frame redirects to adding to the content pane. I need to retrain myself to do that.

Here is a link to a good post that explains why everything changed and then changed back.

Another of Kirill’s comments was that I didn’t center the frame on the monitor. I used to do that via code like


Toolkit tk = Toolkit.getDefaultToolkit();
Dimension screenSize = tk.getScreenSize();

From that I can get the width and height of the screen, and then using the width and height of the frame I can center everything. I can do that, but here it seems a bit like overkill.

Finally, we come to the real issue, which is also the subject of this post. As he said, I violated the EDT rules, and that’s bad.

Arguably Rule #1 of Swing GUI’s is “Only update GUI Elements in the Event Dispatch Thread (EDT).” From what I gather from frequent posts about that issue across the web, this is an error as common to Swing developers as forgetting to close database connections is when writing JDBC code. And again, this is one of those situations in Swing where the rules have changed multiple times, although maybe it’s more accurate to say that the rule hasn’t changed, but the way to implement it has.

First, some quick background. Every Swing program involves multiple threads. First, there are the initializing threads, which start up the GUI. In a Java application, that’s the main method. Then there is the Event Dispatch Thread, which maintains an Event queue that handles all the GUI updates, and finally there are any background threads that are used to manage long-running processes. If you make sure that non-GUI processes are off the EDT, then the GUI will remain responsive while the application is doing other work.

As of JDK 1.6, the standard library now has the class javax.swing.SwingUtilities, which contains the methods invokeLater and invokeAndWait. According to the concurrency lesson in the Swing tutorial, the proper way to create a GUI is


public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        void run() {
            \\  ... instantiate the GUI ...
        }
    );
}

The invokeLater method creates the Runnable object and gives it to the EDT to add to the event queue. The alternative method invokeAndWait does the same thing, but it blocks until the task is completed.

What does Groovy bring to this picture? As usual, Groovy simplifies matters. Groovy adds three helpful methods to groovy.swing.SwingBuilder: edt, doLater, and doOutside.

What do they do? One of the best things about using an open source API is that, well, you have access to the source code. For the edt method, the implementation looks like (paraphrased):


public SwingBuilder edt(Closure c) {
    if (SwingUtilities.isEventDispatchThread()) {
        c.call(this)
    } else {
        // ...
       SwingUtilities.invokeAndWait(c)
       // ...
    }
}

In other words, if we’re in the EDT already, invoke the closure. If not, call invokeAndWait to get to the EDT.

Likewise, for doLater:


public SwingBuilder doLater(Closure c) {
    // ...
   SwingUtilities.invokeLater(c)
   // ...
}

and for doOutside:


public SwingBuilder doOutside(Closure c) {
    // ...
   Thread.start(c)
    // ...
}

So what’s the bottom line?

  • edt: use the EDT through invokeAndWait
  • doLater: use the EDT through invokeLater
  • doOutside: create a worker thread and start it (off the EDT)

Incidentally, SwingBuilder also has a build method specifically designed to construct the GUI. How does it handle threading?


public static SwingBuilder build(Closure c) {
    SwingBuilder builder = new SwingBuilder()
    return builder.edt(c)
}

That’s the whole method — create the buillder and then build the GUI on the EDT, synchronously. That’s why all of our previous examples of SwingBuilder, which only used the build method on the builder, ran correctly. They’re doing the initial construction on the EDT, as they should.

Ultimately, practical examples of Groovy Swing code uses actions that take advantage of these methods, as in


swing.actions() {
    action(name:'myMethod') {

        doOutside {
            model.prop = textField.text
            // ... other model property updates ...
            def ok = someLongRunningService(model)

            doLater {
                model.ok = ok
}  }   }  }

And there you have it. Grab the data and update the model outside the EDT, then run the long running application. When it’s finished, update the GUI in the EDT. (Note that here we’re updating the model in the EDT because the model properties are bound to the GUI elements, so changes in model properties will result in a GUI update. See my previous post in this series for details.)

From here it’s only a short step to Griffon.

      

Friday, October 3, 2008


In my previous post in this series, I presented a trivial Echo GUI written in Groovy.  By using SwingBuilder and closures, the code for the GUI was dramatically simplified compared to the Java version.  But Groovy can go beyond that.  In this post, I’ll talk about the bind method and the @Bindable annotation, which help transform Swing development into the MVC structure of Griffon.

The code for the Echo GUI currently consists of:


import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC

SwingBuilder.build() {
    frame(title:'Echo GUI', size:[300,100],
        visible:true, defaultCloseOperation:WC.EXIT_ON_CLOSE) {
        gridLayout(cols: 2, rows: 0)
        label 'Input text: '
        input = textField(columns:10,
            actionPerformed: { output.text = input.text })
        label 'Echo: '
        output = label()
    }
}

The closure assigned to the actionPerformed property transfers the input from the text field to the output label.  In order to make that happen, both the field and the label were given names that could be referenced inside the closure.

Groovy 1.5+ includes a method called bind, which works with bound properties in the ancient JavaBeans specification.  For those whose only exposure to JavaBeans is through POJO’s on the server side, the original JavaBeans framework was designed to support GUI builders.  It looked and felt much like building GUIs in VB, in that you dragged these “beans” onto a palette, hooked them together, and set the values of their properties.  It was a way of writing Java user interfaces without writing any Java code, at least until you wanted the various widgets to actually do something.

I remember back around 1998, I convinced my boss at the time to purchase Sun’s proposed IDE based on beans.  I think it was called Sun Java WorkBench, or something like that.  It cost about $99, and it came with beans that you could drag and drop, and you could add your own jar files full of beans as well.  While it looked pretty cool, you didn’t have the source code for any of the beans, which limited their usefulness.

Java on the client side didn’t really take off, and the market for the IDE certainly didn’t pan out.  I do remember that the JavaBeans specification — written largely to support the client-side development model — brought us many aspects of Java that we take for granted now.  My first encounter with serialization came from there, as well as reflection, though they used the extremely awkward name introspection for it.  In addition to implementing java.io.Serializable, JavaBeans according to the spec were also supposed to have default constructors and the now-infamous naming convention for getters and setters for all the properties.  Actually, providing a getter method was sufficient to define a property of a JavaBean.

The spec also referred to various types of properties, like bound and constrained, and JavaBeans were also supposed to implement the PropertyChangeListener interface.

Very few Java programs were actually written using those JavaBeans, and the expected third-party market in JavaBeans libraries never seemed to develop.  I seem to recall that there were a couple of success stories (wasn’t IBM’s VisualAge for Java supposed to be written using the original JavaBeans spec?), but mostly the whole technology went away.

It wasn’t until a few years later that JavaBeans re-emerged, as the way to get Java code out of JavaServer Pages.  Sun’s Model 1 architecture consisted entirely of JSPs and JavaBeans, with no explicit servlets anywhere.  Model 2 changed all that by using servlets for controllers, but that came later.  By then, though, people used what we now call POJO’s for model classes, and you were still supposed to make your beans serializable, but all that stuff about property change listeners was largely ignored.

Groovy gives us a chance to use JavaBeans as model classes in an especially easy way.  First, here’s an illustration of a simple GUI that uses the bind method in Groovy.


import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC
import java.awt.BorderLayout as BL

SwingBuilder.build() {
    frame(title:'Binding to Slider', pack:true, visible:true,
        defaultCloseOperation:WC.EXIT_ON_CLOSE) {
        panel(constraints:BL.CENTER) {
          slider(id:'sl')
        }
        panel(constraints:BL.SOUTH) {
          label 'Slider value: '
          label(text:bind(source:sl, sourceProperty:'value'))
        }
    }
}

Here we’re taking advantage of the fact that all Swing widgets extend Component, which means they support property change listeners.  In this case, we have a slider with a property called value.  The bind method assigns the text of the label to the value property of the slider.  Dragging the slider immediately updates the label.

This is seriously cool, and means that the Echo GUI shown above can be made even more responsive by replacing the actionListener by binding the output label directly to the input text field.


import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC

SwingBuilder.build {
    frame(title: 'Regular Binding (Groovy)', size: [300,100],
        visible:true, defaultCloseOperation: WC.EXIT_ON_CLOSE ) {
        gridLayout(cols: 2, rows: 0)
        label 'Input text: '
        textField(columns:10, id:'tf')
        label 'Echo: '
        label(text:bind(source:tf, sourceProperty:'text'))
    }
}

The result is that now, any characters typed into the text field are immediately transferred into the label. Deletes work the same way. The text in the output label is bound to the value of the input text field.

While this is interesting and even useful, a true model-view-controller architecture wouldn’t always bind widgets to other widgets. Instead, input values would be transfered to a model class, and then the model values would be sent to the output view. What we need, therefore, is a way to bind the view elements to an actual Java bean.

If this was Java, we would introduce a class that supported property change capabilities. Consider such a model class in Java:


import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Message {
    private String text;
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public String getText() {
        return text;
    }

    public void setText(String text) {
        pcs.firePropertyChange("text", this.text, this.text = text);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(listener);
    }
}

The Message class has a single property, called text. It also relies on the PropertyChangeSupport class to enable it to add and remove property change listeners. When the text property is changed, the setText method fires a property change event to all the listeners, where the arguments to the firePropertyChange method are the name of the property, its old value, and the new value.

How does Groovy simplify this? The key is the @Bindable annotation, which is currently only in Groovy 1.6 beta 2. Fortunately, that version is included in Griffon, though I did go to the trouble to download and rebuild it myself (a post for another time).

Using Groovy 1.6b2, here’s the equivalent Groovy bean:


import groovy.beans.Bindable

class Message {
    @Bindable def text
}

Seems almost unfair, doesn’t it? Add an annotation to the field, and you’re done. It’s hard to get much simpler than that.

Now all you need is a listener. In Java land, the GUI would use something like:


//...
    private Message msg = new Message();
//...
    msg.addPropertyChangeListener(new PropertyChangeListener(){
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            output.setText((String) evt.getNewValue());
        }
    });
//...

again using an anonymous inner class to respond to the change. By contrast, here is the Groovy version (where in this case the code is sufficiently succinct that I can include the whole thing):


import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC

def model = new Message()

SwingBuilder.build() {
    frame(title:'Echo GUI', size:[300,100],
        visible: true, defaultCloseOperation:WC.EXIT_ON_CLOSE) {
        gridLayout(cols: 2, rows: 0)
        label 'Input text: '
        input = textField(columns:10,
            actionPerformed: { model.text = input.text })
        label 'Echo: '
        label(text: bind { model.text })
    }
}

Once again, this won’t work unless you’re using Groovy 1.6b2 or above. The bind method has been modified to take a closure as its last argument, and the closure in question refers to the text property of the model, rather than to another widget. Note that now I’ve gone back to implementing actionListener, because I have to get the text value from the view into the model, so it’s not quite as clean as before. That could be changed, but at the moment it seems reasonable to do it that way.

Of course, if we have a model and we have a view, what we need next is a controller. Griffon shows how to do that, but I’ll leave it for another post.

The bottom line is that by using Groovy’s bind method and @Bindable annotation, constructing a GUI based on a realistic MVC architecture is now viable, and even easy.

      

Sunday, September 28, 2008


I’ve been spending a lot of time lately trying to understand how much Groovy improves Swing user interfaces. Like so many Java developers, I rarely write client-side programs. Almost all of my time and effort with Java over at least the last five years has been on the server side, mostly with frameworks like Struts, and then open source projects like Spring and Hibernate. During all that time, the client-side interface was restricted to what HTML and CSS can handle.

Of course, the growth of Ajax changed a lot of that. I like several of the major Ajax libraries, like prototype, scriptaculous, jQuery, YUI, and so on. One of the interesting trends I’ve been watching in the industry is whether browser-based GUIs in the future will be written in a Java component library that renders in HTML (like JSF), or written in Java libraries that translate to Ajax/JavaScript (like GWT), or are written using JavaScript components directly (like in YUI or dojo).

Still, I used to write user interfaces in Swing. Several years ago I wrote a Jeopardy-like game that I still use in training classes, where the game board itself is a Swing UI and the clients all have “buzzers” that connect to the game board via RMI. One of my most interesting, and certainly most fragile, projects was about ten years ago when I had to put a Swing GUI on top of a Fortran program (shudder). In case you’re wondering, you can’t get there from here. You have to go Java to C via JNI, and then C to Fortran (even though they handle arrays differently). It’s basically like putting an notch in a beam and telling it to break right here.

But those are stories for another day. Suffice it to say that I feel quite comfortable writing Swing GUIs in raw code (as opposed to graphical drag-and-drop interfaces), complete with inner classes to implement ActionListeners or the like for each button, and so on. I still struggle a bit with the intricacies of GridBagLayout, but I can get pretty far with lots of JPanels and combinations of BorderLayout and FlowLayout.

So when it came time to see what Groovy brought to the table, I thought I was quite prepared. Imagine my surprise to find that, believe it or not, in the last several years the field actually moved on, despite the fact that I almost never get requests for training classes in Swing or related technologies. A lot of people (Andres Almiray, Danno Ferrin, Geertjan, and many more) have spent considerable time and effort applying Groovy to user interfaces and making all kinds of progress.

The culmination of all of this effort is the new, seriously cool, Griffon framework. Griffon promises to bring Grails-like productivity improvements to client-side Java applications. The more I learn about it, the more impressed I am. It’s been a bit disheartening, however, to find out how much I still have to learn before I really understand it.

No matter. I like to say that I’m often wrong, but I rarely stay wrong. My next few posts here will be dedicated to principles that I’ve been learning about user interfaces in Groovy. Hopefully, in addition to providing a nice record for me of what I’m learning, maybe this will help someone else avoid my mistakes.

In this first post, let’s get the really well-known stuff out of the way. That’s the wonderful elegance of Groovy’s groovy.swing.SwingBuilder. SwingBuilder is a great Groovy class, well-described in GinA, that let’s you create Swing interfaces almost declaratively.

Here’s a trivial Swing application in Java. All it does is take text typed in a text field and echoes it in the text of a label. It’s about a simple as Swing applications come.


import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class EchoGUI extends JFrame {
	private JTextField input = new JTextField(20);
	private JLabel prompt = new JLabel("Input text: ");
	private JLabel echo = new JLabel("Echo: ");
	private JLabel output = new JLabel();

	private Container cp = this.getContentPane();

	public EchoGUI() {
		super("Echo GUI");
		cp.setLayout(new GridLayout(0,2));  // 2 cols, as many rows as necessary

		cp.add(prompt);
		cp.add(input);
		cp.add(echo);
		cp.add(output);

		input.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				output.setText(input.getText());
			}
		});

		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(300,100);
		setVisible(true);
	}

	public static void main(String[] args) {
		new EchoGUI();
	}
}

First of all, this shows me to be an “old school” Swing developer, because I made my application extend JFrame rather than contain a JFrame instance. The trend these days is always to favor composition over inheritance, partly to reduce the coupling and partly to make testing easier (I’ll have more to say about testing Swing UIs in a future post). Still, this is the way I learned to do it, and I still fall into old habits, especially for trivial examples.

Second, I’m also arguably violating best practices because my main method instantiates the GUI directly, rather than calling SwingWorker.invokeLater to make sure all user interface updates are done in the Event Dispatch Thread (EDT). You can generally get away with this here, though, because until the GUI is actually rendered it isn’t much of a problem. Understanding the details of running on the EDT or not, however, is a big issue for later, too.

Also, I’m still in the habit of adding components to the content pane. I remember vividly when I had to rewrite all my existing Swing apps to add to content pane instead of directly to the frame itself, and I still do that, even though I don’t think it’s strictly necessary any more.

Finally, I did something here I generally don’t do, which is to use an anonymous inner class to handle the action listener for the button. Normally I create an actual (named) inner class for each component that generates events, and add an instance of each to the relevant component. Here, for example, I would normally write an inner class called something like EchoListener, and then add an instance of it to the button. Still, with only one button and an almost trivial inner class, it seemed easier to add it directly, even though arguably this is the ugliest syntax in all of Java, with the possible exception of generics.

Groovy’s SwingBuilder cuts this example down to practically nothing.


import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC

SwingBuilder.build() {
	frame(title:'Echo GUI', size:[300,100],
		visible:true, defaultCloseOperation:WC.EXIT_ON_CLOSE) {
		gridLayout(rows: 0, cols: 2)
		label 'Input text: '
		input = textField(columns:10,
			actionPerformed: { output.text = input.text })
		label 'Echo: '
		output = label()
	}
}

The SwingBuilder means that I can just write words like frame, label, and textField, and, through the magic of metaprogramming, they are interpreted by the builder as Swing components. The other great part is that Groovy doesn’t force you to create an inner class just to hold a method. Closures are perfectly valid objects in their own right, so I can just assign one to the actionPerformed property of the text field, and I’m all set.

That’s an amazing savings, and it’s just the beginning. The combination of builder methods and closures cuts the amount of code required in a typical Swing GUI by a huge amount.

(I don’t know exactly how much, but I’m going to say 80%, because, as you may have heard, 80% of all statistics are made up on the spot.)

For more details, see GinA (Groovy in Action for the uninitiated, and if you are uninitiated and find Groovy cool, get thee hence to a bookstore and buy thee a copy) and the wiki pages at groovy.codehaus.org.

Still, this much I knew when I started my recent adventure. I had no idea about Groovy’s cool bind method, which dramatically simplifies the use of PropertyChangeListeners and is a great step along the way to a pure MVC architecture. Then there’s the @Bindable annotation that’s part of Groovy 1.6 beta 2, which makes it even easier. Then there’s the elegant way that Griffon lets you handle scheduling tasks inside or outside the EDT. I also realized that Swing hasn’t been idle, too, with the creation of the whole SwingX project and its associated set of components.

It’s been a wild ride for me recently, and I don’t feel I’m anywhere near finished. My feeling, though, is that Griffon is eventually going to be a very big deal. I know it’s making a big difference in how I think about Swing, and I’m looking forward to playing with it more and more.

      

Wednesday, September 10, 2008


There is a minor bug in the selenium plugin for Grails. It has been discussed on the mailing list, but I thought I would also document it here. I’m using Grails 1.0.3 with version 0.4 of the selenium plugin, which wraps selenium core version 0.8.3.

If you install the plugin and try to run the new Grails tasks (create-selenium-test, create-selenium-domain-test, or run-selenium), the system fails with the error

Could not execute method appContext
No such property: appContext for class: …

It turns out that the way the appContext variable is handled in Grails has changed, and the plugin hasn’t yet updated to accommodate it.

The recommended fix is to go into the “plugins/selenium-0.4/scripts” directory in your Grails project, and replace ${appContext} with ${grailsAppName} in all the Groovy scripts.

If you use the Selenium IDE in Firefox to write your tests, then the fix doesn’t matter until you try to use the run-selenium target. Still, might as well fix it everywhere. This came up on the mailing list back in July, so I assume an updated plugin will be available as soon as the author gets around to it.

I also find that adding the path to firefox.exe to my system path (default is “c:\Program Files\Mozilla Firefox” — don’t you hate Windows paths with spaces??) makes it easier to run the test suite.

Incidentally, unlike Canoo Web Test, you have to make sure your web app is running before executing the test suite. Selenium fires up the browser and puts it through the proper sequence, so the app has to be running first.

I’ve decided that rather than choosing between Selenium and WebTest, I actually like using both. The Selenium IDE in Firefox is really slick and easy to use, while the output reports in WebTest are gorgeous.


Friday, September 5, 2008


I’ve been working on a Grails application for rating the popularity of Grails plugins.  Rather than just use a simple form with radio buttons or a drop-down list, I thought I’d use the star rating component of the RichUI plugin.

The initial set-up is easy enough.  First, install the RichUI plugin.

grails install-plugin richui

then go into any GSP page where you want to use star rating and add

<resource:rating />

and after that it’s just a question of using the <g:render /> tag appropriately.

Mine looks like this:


<g:each in="${pluginList}" var="plugin">
   ...
   <g:render template="rate"
      model='[plugin: plugin, rating: "${plugin.rating}"]' />

along with some other stuff.

The documentation says to add a RatingController which computes the new rate.  I considered just adding the rating method to my PluginController, but eventually decided to keep it separate.  My RatingController looks like


class RatingController {
    def rate = {
        def rating = params.rating
        def plugin = Plugin.get( params.id )
        def average = (rating.toDouble() + 
            plugin.rating*plugin.totalVotes)/
                (plugin.totalVotes + 1)
        plugin.rating = average
        plugin.totalVotes += 1
        plugin.save()
        session.voted[plugin.name] = true
        render(template: "/plugin/rate",
            model: [plugin: plugin, rating: average])
    }
}

That’s all pretty much taken from the sample, except for the session.voted[...] business.  I’ll come back to that in a moment.

The template I’m using is called _rate.gsp in the plugin view folder.  It consists of


<div id="plugin${plugin.id}">
    <% def dynamic = !session.voted[plugin.name] %>
    <richui:rating dynamic="${dynamic.toString()}" id="${plugin.id}" units="5"
        rating="${rating}" updateId="plugin${plugin.id}" controller="rating" action="rate"  />
    <p class="static">
        Rating ${java.text.NumberFormat.instance.format(plugin.rating)}
        based on ${plugin.totalVotes} vote<g:if test="${plugin.totalVotes != 1}">s</g:if>
    </p>
    <g:if test="${!dynamic}">
        <div style="color: green;" id="vote${plugin.id}">Thanks for voting!</div>
    </g:if>
</div>

And here we see some good stuff.  First, when you click on the star rating as it comes “out of the box”, it only updates the average value, which it optionally displays.  I wanted to show the number of total votes, too.  As it turns out, there’s an excellent blog post by Jan Sokol that deals with exactly this problem.  See the blog post for details, but essentially it involves changing update ID to that for a div wrapper, which allows you to update a whole section instead.

The <richui:rating> tag has an attribute called dynamic which determines whether you can vote or not.  If dynamic is false, you get a (naturally enough) static view.  If dynamic is true, you can mouseover the stars, highlighting them as you go, and then click to vote.

In most applications I’ve seen that use the star rating, you have to register and login in order to be able to rate anything.  I now believe that’s so they can render the rating tag as dynamic when you enter and then change it to static when you click.  The state is then kept in a user table, which remembers whether you’ve already voted or not.

My problem, though, is that I wanted to let anyone vote without having to register (a decision I’m currently reviewing).  So the question is, how do I keep a person from just voting over and over again?

I tried a couple of ideas, like a toggle or putting something in the page, but if someone browsed to a different page and came back they could vote again.  In the end, I found that I can use the session, even though nobody has logged in!

(That may be obvious to you, but even after teaching server-side Java courses for years now, I guess it never really hit me that a session exists even if you’re not logged in.  Whenever I visited a site with a shopping cart, I always had to log in.  It turns out that was only to buy the products, not to have a session at all. I guess in retrospect it seems obvious, but I never really thought about it until now.)

Anyway, that left me with the question of how to use the session for 90-some different plugins.  I decided to use a boolean array, where the index was the plugin name and the value was true if the person had voted and false otherwise.  As you can see from the RatingController code above, whenever anyone votes, I simply go

session.voted[plugin.name] = true

and I’m all set, because the rating template has

<% def dynamic = !session.voted[plugin.name] %>

and

<richui:rating dynamic=”${dynamic.toString()}” … />

in it.

The only remaining question was how to initialize that array for the session.  I decided that was a classic application of an interceptor, so in my controller for the plugins themselves, I have


def beforeInterceptor = {
    if (!session || !session.voted) {
        def voted = [:]
        def names = Plugin.list().collect { it.name }
        names.each { name ->
            voted[name] = false
        }
        session.voted = voted
   }
}

and there you have it.  Of course, it’s better if you test, and while I still struggle with that, I was able to come up with something effective in this case.  Here’s my PluginControllerTests class, which is, of course, an integration test.  (There’s no doubt a way to make it a unit test instead, but hey, at least it’s tested.)


class PluginControllerTests extends GroovyTestCase {
    def pc

    void setUp() {
        pc = new PluginController()
    }

    void testNoVotedArrayBeforeIntercepting() {
        assertNull pc.session?.voted
    }
  
    void testVotedArrayExistsAfterIntercepting() {
        pc.beforeInterceptor()
        assertNotNull pc.session
        assertNotNull pc.session.voted
    }

    void testVotedArrayHasAcegi() {
        pc.beforeInterceptor()
        assertFalse pc.session.voted['acegi']
   }

   void tearDown() {
        pc = null
    }
}

So it all works, at least so far.  Soon I’ll be able to deploy it, but now I’m still fighting with CSS styles.  Whoever thought doing layout with CSS was a good idea has some explaining to do.

Incidentally, anyone who has used WordPress for blogging knows the frustrations of trying to format code in it. I think there are plugins available to make it easier, but I’m not running WordPress myself — I’m letting them host my blog. The bottom line, therefore, is that sometimes it’s really hard to read code that is posted here. I think, when my app is finished, I’ll follow the recent trend and upload it to github. If I do that, I’ll be sure to mention it here.