Monday, July 31, 2006

Peter Norvig's Infrequently Answered Questions

Here's a Java resource I wish I had known about long ago: Peter Norvig's Java IAQ.

UPDATE: Thanks to anonymous for pointing out I mispasted in the link!

Saturday, July 29, 2006

A Java trick with varargs to enforce argument count

Perhaps you've seen this before, but it is new to me:

public void doSomethingAmazing(
        final String firstArgument,
        final String... restOfArguments) {
    // Do something amazing with the arguments
}

What is the point of firstOne and restOfThem (besides looking a little LISPy)?

Fortunately, the coder had this comment for the method: Change from checking at runtime for one or more arguments to syntatically enforcing a mandatory first argument and optional list of remaining arguments. A quick check showed the previous version as:

public void doSomethingAmazing(
        final String... arguments) {
    // Do something amazing with the arguments
}

Aha, how clever! Whereas before the call:

doSomethingAmazing();

compiled but at runtime threw an IllegalArgumentException for empty arguments[], now the same call is a syntax error caught by the compiler. The correct new call is:

doSomethingAmazing("wonderful");

I like it.

UPDATE: Paul Holser points out to me that he uses this trick in the excellent JAggregate. As I reviewed that code within the past several months, I now realize that it is most likely I had already seen this trick there first. Paul is a clever guy, and deserves the credit.

Wednesday, July 19, 2006

The double inheritance pattern in Java

Java is a single inheritance language, yes? Generics adds a new wrinkle to that, however. Consider this problem:

You have a class hierarchy you wish to wrap. For instance, you want wrapped versions of JTextComponent and its subclasses which implement additional functionality or default behaviors. So the first wrapping looks like this:

public class MyTextComponent
        extends JTextComponent {
    // ...
}

The second wrapping looks like this:

public class MyTextField
        extends JTextField or MyTextComponent {
    // ...
}

Oops! What should the second wrapper extend?

Generics provides a neat, if wordy, solution for this problem. Have the wrapper hierarchy extend only within itself, and have generic types extend the wrapped hierarchy. The wrapper hierarchy delegates to the wrapped one. Thus:

public class LabeledTextComponent<F extends JTextComponent>
        extends Box { // Box is just illustrative
    protected final F field;

    private final JLabel label;

    protected LabeledTextComponent(final F field,
            final String labelText) {
        super(BoxLayout.LINE_AXIS);

        this.field = field;
        label = new JLabel(labelText, SwingConstants.TRAILING);

        label.setLabelFor(field);
        
        add(label);
        add(field);
    }

    // ... public constructors

    // delegates via field specific to JTextComponent

    public String getText() {
        return field.getText();
    }

    public void getText(final String text) {
        field.setText(text);
    }

    // ... other delegates

    // methods specific to LabeledTextComponent

    public JLabel getLabel() {
        return label;
    }
}

public class LabeledTextField<F extends JTextField>
        extends LabeledTextComponent<F> {
    protected LabeledTextField(final F field,
            final String labelText) {
        super(field, labelText);
    }

    public LabeledTextField(final String labelText) {
        super(new JTextField(), labelText);
    }

    public LabeledTextField(final int columns,
            final String labelText) {
        super(new JTextField(columns), labelText);
    }

    // ... other public constructors, etc.
}

And a further example:

public class LabeledPasswordField<F extends JPasswordField>
        extends LabeledTextField<F> {
    protected LabeledTextField(final F field,
            final String labelText) {
        super(field, labelText);
    }

    // ... public constructors

    // delegates via field specific to JPasswordField

    public char[] getPassword() {
        return field.getPassword();
    }

    public void getPassword(final char[] password) {
        field.setPassword(password);
    }

    // ... other delegates
}

Generics combined with delegates simulates a kind of multiple inheritance similar to mixins. One can extend the idea one step further:

public interface Required {
    /** Checks if the field requires text to be valid. */
    boolean isRequired();

    /** Toggles that the field requires text to be valid. */
    void setRequired(final boolean required);

    /** Checks if the field is required and if the text is missing. */
    boolean isMissing();
}

public class RequiredTextField extends JTextField
        implements Required {
    private boolean required;

    // Required
    public boolean isRequired() {
        return required;
    }

    public void setRequired(final boolean required) {
        this.required = required;
    }

    public boolean isMissing() {
        return required
                && null != getText();
                && getText().length() > 0;
    }
}

public class RequiredLabeledTextField
        <F extends JTextField & Required>
        extends LabeledTextField<F>
        implements Required {
    protected RequiredLabeledTextField(final F field,
            final String labelText) {
        super(field, labelText);
    }

    // Required
    public boolean isRequired() {
        return field.isRequired();
    }

    public void setRequired(final boolean required) {
        field.setRequired(required);
    }

    public boolean isMissing() {
        return field.isMissing();
    }
}

Now it is simple to glue it all together cleanly, maintaining separation of concerns and working through interfaces based on capabilities rather than concrete classes.

Generics to the rescue!

NB — I relied heavily on my background in C++ templates for conceptualizing this pattern. But I believe it likely I am treading no new ground. If you know an earlier or better reference for this pattern, please drop me a line. I want to give credit to where it is due.

Friday, June 23, 2006

Skipping read-only text components in Swing with TAB

After a superficial web search, I did not turn up a simple way (read cut and paste) to TAB over read-only components while navigating a container in Swing. JComboBox, JTextComponent and JTree all have an isEditable/setEditable(boolean) pair, however it has different meaning for each of them.

The case I am interested in JTextComponent. For text components, uneditable is equivalent to read-only: you can select the text from the component but cannot change it. The alternative is to disable the component, but then the text is not selectable for copying.

So, given a uneditable text component, what happens when I traverse through a form with the TAB key? Unfortunately, the JDK by default will move the focus (the caret) into the read-only text field even though you cannot type anything. Fixing the form to skip over read-only text fields is straight-forward but not directly documented:

public static void skipReadOnlyTextComponents(
        final Container container) {
    // Without this, JDK ignores policy
    container.setFocusCycleRoot(true);
    container.setFocusTraversalPolicy(new MyPolicy());
}

class MyPolicy extends LayoutFocusTraversalPolicy {
    @Override
    protected boolean accept(final Component c) {
        return !isReadOnly(c) && super.accept(c);
    }

    private static boolean isReadOnly(
            final Component c) {
        if (c instanceof JTextComponent)
            return !((JTextComponent) c).isEditable();

        return false;
    }
}

In broader use, it is worthwhile to make an Editable interface for isEditable/setEditable and add that to the instanceof tests in isReadOnly.

Wednesday, June 21, 2006

Answer: Using JFormattedTextField for integers

I wrote earlier about using JFormattedTextField for integers and the difference between using an initial value of Integer (rounds input) v. BigInteger (rejects invalid input). I also wrote that I did not understand why there was a difference.

I now know what happened.

The culprit for handling Integer turns out to be NumberFormat and friends. The rounding behavior is not numerical rounding at all; it is truncating the input text.

The parser for the input stops after finding valid input and returns a parsed value in stringToValue(String):Object. This discards any trailing text, which in the case of parsing an integer is everything from the decimal point forward. The same behavior can be seen with a date parser: Jun 21, 2006xxx parses to Jun 21, 2006 and the xxx is discarded.

The solution to enforce correct input even with trailing garbage is cumbersome: initialize JFormattedTextField with a custom formatter and check that parsed input deparses back cleanly:

new JFormattedTextField(new Integer(0))

becomes:

new JFormattedTextField(new NumberFormatter(
        NumberFormat.getIntegerInstance()) {
    @Override
    public Object stringToValue(final String text)
            throws ParseException {
        // Throws if the input is corrupt from the start
        final Object parsed = super.stringToValue(text);
        final String deparsed = valueToString(parsed);

        // Throws if there is no clean roundtrip,
        // such as trailing garbage characters
        // For date parsing, etc., consider equalsIgnoreCase
        if (!deparsed.equals(text))
            throw new ParseException(text, deparsed.length());

        return parsed;
    }
}) {
    {
        // Initialize to the original starting value
        setValue(new Integer(0));
    }
}

(Yes, the anonymous instance syntax is awkward here.)

That's a lot of work to achieve what seems like a simple goal: actually valid input for a JFormattedTextField.

UPDATE: Given the hoops to jump through for this more "correct" solution, I think I'll stick to new JFormattedTextField(new BigInteger(0)) for now, although that does nothing to help with other input types such as dates.

Tuesday, June 20, 2006

Using JFormattedTextField for integers

I discovered the hard way that:

new JFormattedTextField(new Integer(0))

does not do what I wanted.

What I wanted was to have a text entry field restricted to integers. What I got was a field which rounded off numbers to integers. This was surprising.

After a while of poking at it, I tried using various incarnations of NumberFormat and DecimalFormat in the field constructor with no luck. Perusing the sources was not particularly illuminating either, at least at first.

Finally I noticed that JFormattedTextField.getDefaultFormatterFactory(Object) contained this legerdemain:

if (type instanceof DateFormat) { ... }
if (type instanceof NumberFormat) { ... }
if (type instanceof Format) { ... }
if (type instanceof Date) { ... }
if (type instanceof Number) { /* mucking around with formatter factory */ }

Hmmm. So in a flash of inspiration I tried:

new JFormattedTextField(new BigInteger(0))
and it worked, although I do not entirely understand why. JFormattedTextField maintains separately value, formatter and formatter factory in addition to the document model for text entry and a lot of state options for handling valid and invalid input.

I'm sure its a tour de force for someone at Sun, and most importantly the class works, but quirks like this one are difficult to find and explain.

UPDATE: A colleague of mine asked for more details on this point. To clarify:

Argument Input Behavior
new Integer(0) 3.0 3
3.3 3
new BigInteger(0) 3.0 3
3.3 invalid

So to get non-integral input to be treated as invalid, you must initialize JFormattedTextField with a BigInteger; initializing with an Integer gets a rounding mode instead.

Monday, June 19, 2006

Programmatically show a tool tip in Swing

A better way to do this exists, I am sure, but I failed to find it easily with Google: How to display a tool tip programmatically in Swing:

ToolTipManager.sharedInstance().mouseMoved(
        new MouseEvent(targetComponent, 0, 0, 0,
                0, 0, // X-Y of the mouse for the tool tip
                0, false));

Note the commented line. This is the relative location of the synthetic mouse event to the target component. The (0, 0) example above is as if the user had paused the mouse at the upper-left corner of the component, and the tool tip displays accordingly.

Another choice might be (targetComponent.getWidth(), targetComponent.getHeight()) for the lower-right corner, etc.

I wish Swing had a more straight-forward way of using the tool tip framework programmatically. I would like to be able to reuse tool tips for form validation. But at least this works.

UPDATE: 4 years on and I still get more positive comments on this post than any other. Hopefully the JDK improves in this area.

Monday, June 12, 2006

ViM 7

In another salvo in the endless vi v. Emacs war, the ViM folks released ViM 7.0.

The announcement is about a month old. Why the delay for me mentioning it? Cygwin just updated their 6.4 to 7.0 over the weekend. Too bad the update removed vi from /usr/bin. Oops.

UPDATE: I found one source of my Cygwin trouble. For whatever reason, the ViM 7.0 installation put vim.exe and friends into C:\cygwin\usr\bin instead of /usr/bin. As my default Cygwin installation mounts C:\cygwin\bin as /usr/bin, that means the mount hides the files in the underlying Windows directory:

C:\cygwin\bin -> /usr/bin
C:\cygwin\usr\bin -> hidden underneath

A quick unmount, switch to CMD.EXE, files moved to the right Windows directory, and remount: I can now run vim.

One remaining problem: whither the vi command?

UPDATE: Run the Cygwin installer/updater one more time. There is a patch up for the new ViM 7 package which fixes the missing /usr/bin/vi problem and the overall install issues.

Friday, June 09, 2006

Google Browser Sync

Well, this looks interesting.

Finding a field in Java

A large motivation for me starting this blog was to help me remember useful snippets of code. This is a good example:

Field getField(Class clazz, final String fieldName)
        throws NoSuchFieldException {
    for (; null != clazz; clazz = clazz.getSuperclass()) {
        try {
            final Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (final NoSuchFieldException e) { }
    }

    throw new NoSuchFieldException(fieldName);
}

Very simple code, no? But a fact I seem to sometime forget is that inherited fields do not show up in reflection; one must reflect down into the appropriate superclass where the field was declared. The simple method handles the details easily enough.

Thursday, June 08, 2006

Against agilism

As much as I am a fan of agile development methodologies, I must admit that Cedric Beust has some good points against agile.

I need more time to think his post through. It is meaty, lengthy and well-written. It is also a bit abrasive, but I enjoy that style.

Wednesday, June 07, 2006

IntelliJ IDEA build 5321

After several builds that gave me a lot of trouble, IntelliJ IDEA build 5321 seems to hit the spot.

With several of the previous EAP builds the IDE leaked memory fairly badly and I often hit mysterious lock ups for minutes at a time. The only solution was restarting. Worse was that many times the dialog to mail exception reports to JetBrains itself would fail.

Build 5321 does not seem to have these flaws, happily, and seems robust enough for daily use.

Monday, May 22, 2006

Learning more about web continuations

Web continuations fascinate me, but alas I have no current project in which to work on them. So I try to keep up in my reading instead.

I ran across this lengthy post on the "abandoned session" problem by Blushish Coder, one of my favorite code bloggers. Meanwhile, I bide my time looking for the right project for proposing continuations.

Friday, May 19, 2006

Leo Simons on unit tests for complex software

Leo Simons has a useful post on how to organize unit tests for complex software. Included is a nifty chart which explains his post well. I feel chart envy setting in.

Tuesday, May 02, 2006

A debugging glass pane

I've started on a largish Java project (4000+ classes) with a complex Swing UI front-end and have had difficulty working out just which class is in play for a given visual component.

Glass pane to the rescue.

To help me out, I've written a small debugging glass pane based on a universal right-click handler found on Google similar to the example provided in the Swing documentation.

Use is simple:

JFrame frame = ...;
DebugGlassPane.setDebugGlassPaneOn(frame);

Now when you hover the mouse over a component in the content pane, up pops a tooltip identifying the class and instance name. If you want to change the displayed information, edit createTipText(Component).

The complete class:

public class DebugGlassPane
        extends JComponent
        implements MouseListener, MouseMotionListener {
    private final JLayeredPane layered;

    public static void setDebugGlassPaneOn(final JFrame frame) {
        final Component glass = new DebugGlassPane(frame);
        // Must be in this order
        frame.setGlassPane(glass);
        glass.setVisible(true);
    }

    public DebugGlassPane(final JFrame frame) {
        layered = frame.getLayeredPane();

        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void mouseMoved(final MouseEvent e) {
        setToolTipText(createTipText(getChildUnderMouse(e)));

        redispatchMouseEvent(e);
    }

    public void mouseDragged(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    public void mouseClicked(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    public void mouseEntered(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    public void mouseExited(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    public void mousePressed(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    public void mouseReleased(final MouseEvent e) {
        redispatchMouseEvent(e);
    }

    private String createTipText(final Component c) {
        return "<html>Class: <b>" + c.getClass().getName()
                + "</b><br>Name: <i>" + c.getName();
    }

    private void redispatchMouseEvent(final MouseEvent e) {
        final Component component = getChildUnderMouse(e);

        // E.g., popup menus
        if (component == null) return;

        // redispatch the event
        component.dispatchEvent(
                SwingUtilities.convertMouseEvent(this, e, component));
    }

    private Component getChildUnderMouse(final MouseEvent e) {
        // get the mouse click point relative to the content pane
        final Point containerPoint = SwingUtilities.convertPoint(this,
                e.getPoint(), layered);

        return SwingUtilities.getDeepestComponentAt(layered,
                containerPoint.x, containerPoint.y);
    }
}

Surprisingly, I had a difficult time finding such a class already coded up somewhere. It is quite handy for exploring the UI.

UPDATE: An important fix (already incorporated in the code, above). Say you have a menu bar. The current code throws a NullPointerException. The problem is that all the work is relative to the content pane, but a JFrame can have visual space which recieves mouse events but is not part of the content.

The fix is simple: change getChildUnderMouse(MouseEvent) to work with the component from frame.getLayeredPane() instead of frame.getContentPane(). Sun has a good explanatory diagram and description making this point clear.

Sunday, April 23, 2006

Nifty JDBC 4.0

Today I've been playing with some of the new JDBC 4.0 features in the latest JDK6 beta. In particular, I've been scouting around for a lighter-weight alternative to Hibernate when working with small-sized projects, and one that uses annotations rather than XML.

A few weeks ago I tried out Ammentos, and although in the right direction it did not quite handle everything I threw at it. JDBC 4.0, however, seems just the thing with a little extra effort.

First some setup. After grabbing the latest JDK6 build I needed a database with a JDBC 4.0 driver. Some googling revealed that the also nifty Apache Derby database project is such a database, however only special daily builds have support turned on. Fair enough, it was only a download away and JDK6 is still in beta.

Finally, time for some code (ignoring imports, error handling and such):

public static void main(final String[] args)
        throws ClassNotFoundException, SQLException {
    Class.forName(EmbeddedDriver.class.getName());

    final Connection connection = DriverManager.getConnection(
        "jdbc:derby:test-database;create=true");

    final Statement statement = connection.createStatement();
    statement.execute("CREATE TABLE BOB"
            + "(ID INT NOT NULL GENERATED ALWAYS AS IDENTITY,"
            + " NAME VARCHAR(32))");

    connection.setAutoCommit(false);
    connection.setTransactionIsolation(TRANSACTION_SERIALIZABLE);

    final BobQuery query = connection.createQueryObject(BobQuery.class);

    final String name = "the Builder";
        
    final BobKeys key = query.addBob(name).get(0);
    final Bob bob = query.findBobByName(name).get(0);

    System.out.println("inserted = selected? " + key.id.equals(bob.id));

    query.close();
    statement.execute("DROP TABLE BOB");
    connection.commit();
    statement.close();
    connection.close();
}

public class Bob {
    public BigDecimal id;
    public String name;
}

@AutoGeneratedKeys
public class BobKeys {
    public BigDecimal id;
}

public interface BobQuery
        extends BaseQuery {
    @Update(sql = "INSERT INTO BOB(name) VALUES(?1)",
            keys = RETURNED_KEYS_DRIVER_DEFINED)
    DataSet addBob(final String name);

    @Select("SELECT * FROM BOB WHERE name = ?1")
    DataSet findBobByName(final String name);

    @Select("SELECT * FROM BOB")
    DataSet findAllBobs();

    @Update("DELETE FROM BOB")
    int removeAllBobs();
}

Everything worked!

(And Derby helpfully creates a scratch database in-place given the proper JDBC URL.)

There were some gotchas:

  • The Derby driver did not seem to use the new service feature at least for the embedded case shown here.
  • The type for primary key identifiers is BigDecimal, not Long as I guessed at. Improved javadocs would help here.
  • I had little luck with the {fieldName} syntax shown in the @Update annotation javadocs for auto-generated keys. I am unsure if the driver, the JDK, the javadocs or the coder is at fault.

JDBC 4.0 is particularly well thought-out for custom persistence layers. I suspect much was borrowed conceptually from Hibernate's excellent work. To use the common DAO pattern as an example, just consider insertion:

public int addBob(final Bob bob) {
    final DataSet keys = addBob(bob.getName());

    if (keys.isEmpty()) return 0;

    bob.id = keys.get(0).id;

    return keys.size();
}

So much boilerplate code saved, a real boon to the coder in the trenches; the code is very readable; no SQLException peppering the entire DAO layer. (Of course my curiosity rises: what does happen when the database cannot insert? — I need to read more on getSQLWarnings().)

JDBC 4.0 is nifty indeed.

UPDATE: As noted in one of the trackbacks, the Derby JDBC 4.0 driver now supports the service discovery mechanism. No more need to call Class.forName. Excellent.

Sunday, March 05, 2006

Using JNLP for a J2EE application client

In Moving the view away from the controller I talk about general ideas for separating the typical cohosting of a J2EE application (the service layer and below) from the view (JSPs, etc.).

Sun's own way of handling this is to make the client intimately familiar with the application beans. But this is the opposite of the direction I want to go in. Instead, I want to have the controller reside at the server, and the veiw in the client without any knowlege of beans and such.

Of course, this is the same as having any of a REST, SOAP, RPC or similar architectures, or all of them.

Presently, I am evaluating JBoss serialization v. REST-RPC to see how they compare for performance, reasonableness and ease of development, but am open to other suggestions.

My goal is to construct a demo client and server application with JNLP Swing at one end and standard J2EE servlets at the other. Fortunately for me, Sun gets me started and there are good examples by others.

Friday, March 03, 2006

IntelliJ IDEA 5175

Yah! Finally, an EAP build of what will become IntelliJ IDEA 6.0 that is usable for me. The previous EAP build (5162) had two problems for me:

  1. It threw exceptions a lot.
  2. Fatally, 5162 corrupted project settings files.

But the new 5175 build works great.

I like the newer way of handling views borrowed from Eclipse (I presume) but without the klunkiness feel of Eclipse perspectives (although the J2EE portion has some kinds to iron out: I get the J2EE view twice in the drop list).

I also see lib/emma.jar and lib/emma-agent.jar new with 5175 (perhaps also with 5162, but not in 5131). I have not found any UI yet for unit test code coverage, but it looks like IDEA is heading that direction.

Lastly, I also noticed lib/rt/org.eclipse.jdt.core.jar which is not in 5.1. I wonder what JetBrains is up to?

JUnit testing for exceptions

A JUnit pattern I find myself using very frequently is testing constructor and method inputs. Usually the first testcase I have for a new class is to test what happens in the constructor with null inputs. I believe in fail-fast coding principals and expect calls to quit as soon as they know there is no point in continuing. This helps me find bugs and other problems quickly during development rather than slowly during deployment.

So my typical test looks like this. For some class Foo whose constructor takes a single non-null parameter, bar, and which throws an IllegalArgumentException otherwise, I check for the name of the missing parameter in the exception message (as a convention):

 1 /**
 2  * Test {@link Foo#Foo(String)} for {@code null} <var>bar</var>.
 3  *
 4  * @throws Exception if unexpected
 5  */
 6 public void testFooForNullBar()
 7         throws Exception {
 8     try {
 9         new Foo(null);
10         fail("Did not throw");
11 
12     } catch (final IllegalArgumentException e) {
13         assertExceptionMessageContains(e, "bar");
14     }
15 }

But what about assertExceptionMessageContains? It is very simple:

 1 /**
 2  * Assert that the given exception, <var>e</var>, constains the given
 3  * string, <var>s</var>, in its message failing with <var>message</var>
 4  * otherwise.
 5  *
 6  * @param message the failure message
 7  * @param e the exception
 8  * @param s the string in the message
 9  */
10 protected static void assertExceptionMessageContains(final String message,
11         final Exception e, final String s) {
12     assertTrue(message, e.getMessage().contains(s));
13 }
14 
15 /**
16  * Assert that the given exception, <var>e</var>, constains the given
17  * string, <var>s</var>, in its message.
18  *
19  * @param e the exception
20  * @param s the string in the message
21  */
22 protected static void assertExceptionMessageContains(final Exception e,
23         final String s) {
24     assertExceptionMessageContains(
25             "Exception missing message: " + s + ": " + e, e, s);
26 }

Originally I threw NullPointerException from my constructors when encountering missing parameters, but over time I changed to IllegalArgumentException as more descriptive, and also so that any NullPointerException would always indicate something unexpected from the JVM.

Tuesday, February 28, 2006

Using Java 5 enums for the Command Pattern

Perhaps posted about elsewhere (my Google search did not turn up what I was looking for), one of the best uses for Java 5 enums is to implement the well-known Command Pattern.

Just one simple example with two commands, START and FINISH, and a simple execution parameter, sessionId:

/**
 * Demonstrates using JDK5 {@code enum}s for the Command Pattern.
 * 
 * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
 */
public enum CommandEnum {
    /**
     * The {@code START} command.
     */
    START() {
        @Override
        public void execute(final SessionId sessionId) {
            System.out.println("Start: " + sessionId);
        }
    },
    /**
     * The {@code FINISH} command.
     */
    FINISH() {
        @Override
        public void execute(final SessionId sessionId) {
            System.out.println("Finish: " + sessionId);
        }
    };
    
    /**
     * Executes the command.
     */
    public abstract void execute(final SessionId sessionId);
    
    public static void main(final String[] args) {
        final SessionId mySessionId = new SessionId(13);
        
        for(final CommandEnum command : CommandEnum.values())
            command.execute(mySessionId);
        
        final SessionId yourSessionId = new SessionId(31);
        
        CommandEnum.valueOf("START").execute(yourSessionId);
        CommandEnum.valueOf("FINISH").execute(yourSessionId);
    }
    
    private static final class SessionId {
        private final int id;
        
        SessionId(final int id) {
            this.id = id;
        }
        
        @Override
        public String toString() {
            return Integer.toString(id);
        }
    }
}

A nice benefit of this use of enum is that one need not refactor existing code to take advantage. Use the enums with the Adapter or Facade Patterns and replace the bodies of execute() with forwarding calls to the original code implementations. Then new code can use the Command Pattern while existing code can continue to use the (possibly @Deprecated) original calls.

Monday, February 20, 2006

Bootstrapping Maven dependencies into Ant

One thing about builds I detest: packing the universe into the source tree. Maven and Ivy are two good solutions for this problem, keeping your external dependencies out of your source control system. And they both work with Ant.

But how to get the ball rolling?

Helpfully, Ant has the get task for fetching files from the Internet. Thus I can fetch Ivy or the Maven-Ant bindings, plug them into build.xml, and pull down my other dependencies all without checking in anything outside of my project.

Here's how:

  1     <property name="target.dir" location="target"/>
  2     <property name="maven-artifact-ant.bootstrap.jar"
  3               location="${target.dir}/maven.artifact-ant-2.0.2-dep.jar"/>
  4 
  5     <target name="-check-get-maven-artifact-ant">
  6         <available property="-get-maven-artifact-ant-done"
  7                    file="${maven-artifact-ant.bootstrap.jar}"/>
  8     </target>
  9 
 10     <target name="-get-maven-artifact-ant"
 11             depends="-check-get-maven-artifact-ant"
 12             unless="-get-maven-artifact-ant-done">
 13         <mkdir dir="${target.dir}"/>
 14         <get src="http://www.apache.org/dist/maven/binaries/maven-artifact-ant-2.0.2-dep.jar"
 15              dest="${maven-artifact-ant.bootstrap.jar}"/>
 16     </target>
 17 
 18     <target name="-maven-artifact-ant" depends="-get-maven-artifact-ant">
 19         <typedef resource="org/apache/maven/artifact/ant/antlib.xml"
 20                  uri="urn:maven-artifact-ant">
 21             <classpath>
 22                 <pathelement location="${maven-artifact-ant.bootstrap.jar}"/>
 23             </classpath>
 24         </typedef>
 25     </target>
 26 
 27     <target name="init" depends="-maven-artifact-ant">
 28         <tstamp/>
 29         <!-- All the other init tasks: buildnumber, mkdir, et al -->
 30     </target>

In essence the steps are:

  1. Check if there is already a downloaded jar (-check-get-maven-artifact-ant).
  2. If not, fetch one from a well-known location (-get-maven-artifact-ant).
  3. Load the bindings from the jar into Ant (-maven-artifact-ant).

Now build.xml is ready to proceed with Maven (or Ivy) for fetching dependencies and deploying them.

A tricky ant trick

It took me some time to get this exactly right (if such a thing can be said): How to get ant to copy over a set of files when one is out of date, but do nothing otherwise. Pretty simple, I know, but still I discovered several gotchas. Here is what I wound up with:

(Yes, this does not resemble a production ant script. The real task was signing jars for JNLP deployment from a CVS repository into a staging directory if they were not already there.)

<project default="boom">
    <property name="bob" location="bob"/>
    <property name="nancy" location="nancy"/>

    <fileset id="bobs" dir="${bob}"/>

    <target name="check-up">
        <uptodate property="dental">
            <srcfiles refid="bobs"/>
            <mapper type="glob" from="*" to="${nancy}/*"/>
        </uptodate>
    </target>

    <target name="boom" depends="check-up" unless="dental">
       <echo message="Ka-BOOM!"/>
       <copy todir="${nancy}">
           <fileset refid="bobs"/>
       </copy>
    </target>
</project>

Some of the mistakes I made along the way:

  • The unless attribute of target is just a plain token; do not try to surround it with dollar-curly braces>.
  • If you do not give srcfiles an includes or refid attribute, it silently does nothing rather than complaining.
  • The from attribute to mapper takes a plain asterisk and is relative to the srcfiles: it was easy to get this wrong in several ways and only experimentation saved me.

In short this is a nice setup to avoid extra build work, but it is somewhat fragile and Ant needs more documentation and examples in this area.

Thursday, February 16, 2006

Moving the view away from the controller

One of the most widely used embodiments of MVC architecture is the web application. Finding its most widespread origin in the desktop application framework, modern enterprise MVC applications live and breathe the Internet and the browser.

One result, however, is that the model, controller and viewer are usually colocated: the browser may display the web pages and let the user send input back, but it is in the server pages that the real code for the viewer runs. This is changing, perhaps.

New AJAX technologies are pushing some of the work of the viewer into the browser. One result is that whereas with Web 1.0 the viewer and controller run in situ on the server and developers must take care not to mix them, with Web 2.0 the joys of RPC appear and AJAX writers should bunch up requests for good performance. (Although seeing the responsiveness of Google's AJAX application, I wonder how much larger, faster bandwidth alleviates this problem.)

What I would like to try is this: in addition to enrichening the browser with AJAX, I would like to explore using Java WebStart for full-blown desktop applications while keeping the model and all or a portion of the controller back on the server.

Perhaps with SOAP, or simple XML-RPC, or even with extensions of HTTP (the path followed by WebDAV) the desktop application can call back to the server for work in the domain, model and persistence layers, while keeping a rich presentation layer local.

Thinking more about this, I can see the split between viewer and controller shifting under this circumstance. Say one had a tabbed application interface. Changing tabs with a Web 1.0 application involves trips to the controller to redirect the view. But changing tabs with a desktop application require no such direction. The initial view of the tab, though, would need the model on the server.

By no longer colocating all the MVC pieces, the relation or balance of power among them changes in, I believe, new and interesting ways. It is another option in the new Web 2.0.