Sunday, February 27, 2005

How Eclipse outshines IntelliJ IDEA

I enjoy IntelliJ IDEA. It is a better Java editor than Eclipse. I find Eclipse clunky, slow and ugly. But I expect Eclipse to dominate the Java editor marketplace and plug-ins such as Jupiter are the reason why. Ilmyggo points out Jupiter in his post, Two excellent Eclipse plug-ins and notes:

The Jupiter code review plug-in tool integrates with Eclipse in order to carry out code reviews. Reviewing code is a tedious job. Previously I've been writing comments on paper copies, using @todo-tags and other custom JavaDoc tags. No more! With Jupiter you just move the cursor to the place in the code where you see an issue and enter a new Jupiter issue in the review editor. The issues are listed in a separate review table, and are also displayed as purple marker fields in the source code editor. Nice!

'Nice' indeed. Because of Eclipse's development model and corresponding mindshare, outstanding academic projects like Jupiter gravitate to it rather than to IDEA, the better product.

But IDEA will stay better for only so long. If you imagine the improvement of Eclipse and IDEA (and JBuilder, et al) as lines on a graph of quality to time, IDEA intercepts the y-axis at a higher point than IDEA and remains higher at the present moment, but Eclipse has a greater slope because of the larger contributing mindshare. It is a matter of time before Eclipse will pass IDEA, and not long afterwards IDEA will stagnate as its advantages no longer raise it above the free alternative.

The marketplace is very efficient.

Friday, February 25, 2005

Testing output streams in Java

Here's a handy little helper test class for unit testing output streams in Java:

public class AssertOutputStream extends ByteArrayOutputStream {
    private final byte[] expected;

    public AssertOutputStream(final byte[] expected) {
        if (null == expected) throw new NullPointerException();

        this.expected = expected;
    }

    @Override
    public void close()
            throws IOException {
        super.close();

        Assert.assertTrue(Arrays.equals(expected, toByteArray()));
    }
}

Just drop it into a unit test as the destination output stream along with an expected byte array to test that the expected bytes were written out. If you prefer a failure message, it is easy enough to add a member String to hold one for the call to Assert.assertTrue.

UPDATE: Following the suggestion of ThoughtWorker Paul Holser, here is an inproved version:

public class AssertOutputStream extends ByteArrayOutputStream {
    private final String message;
    private final byte[] expected;

    public AssertOutputStream(final byte[] expected) {
        this(null, expected);
    }

    public AssertOutputStream(final String message,
            final byte[] expected) {
        super(expected.length);

        this.message = message;
        this.expected = expected;
    }

    @Override
    public void close()
            throws IOException {
        super.close();

        Assert.assertTrue(message,
                Arrays.equals(expected, toByteArray()));
    }
}

Thursday, February 24, 2005

The STL in Java

One of the most pleasurable parts of C++ is the STL. Some benighted souls have created Java equivalents in the JGA project now that JDK 5 has generics. If this excites you, read what you can do with iterators and functors. It is not as elegant as C++, but the idioms are much more functional than most Java coders are used to. Until Java has closures, it will do.

UPDATE: I do not want to give the wrong impression. JGA is quite nice for what it is trying to do. The inelegancies that crop up are due to Java, not JGA. It is the same old story: trying to use anonymous classes for closures, lack of mixins, et al. If you want a more elegant version of Java, try Scala or Nice. But do try JGA for your Java projects.

A bozo moment

In my previous post I made a big to do about needing an extra class for pulling together all the generics. My example called it LocalDirectoryType. Guess what? I don't need it.

public class LocalDirectory extends LocalEntity<LocalDirectory>
        implements Directory<LocalDirectory> {
    // Constructors, and unimplemented directory-specific methods
}

That's it. Strike the section named The final problem: it was a solution in search of a problem.

Wednesday, February 23, 2005

Coplien for Java

The justly famed Curiously Recurring Template Pattern (CRTP) is one of the cooler consequences of the design of templates in C++. But Java generics supports the same idiom:

public interface Bob<T extends Bob<T>> {
    T doWop(T t);
}

public class Fred implements Bob<Fred> {
    public Fred doWop(final Fred f);
}

Which is particularly nice if you are writing base classes.

Good for something

However, what about a case like this — lets try to rationalize my favorite pariah class, java.io.File. For starters, files and directories should be different types extending a common superclass. It makes no sense to list children on a file, nor to open an input stream on a directory. Starting simply:

public interface Entity<T extends Entity<T>> {
    void create() throws IOException;
    void delete() throws IOException;
    void renameTo(final T newLocation) throws IOException;
}

renameTo is the first interesting method. I do not want renaming files to directories and vice versa to even compile if possible, so I require the arguments to be of the same type.

Problem the first

Now a file:

public interface File<T extends Entity<T>> {
    InputStream getInputStream() throws IOException;
    OutputStream getOutputStream() throws IOException;
}

In the generic specification, why not T extends File<T>? Ah, my first chance to get bit by generics. You see, when I tried that the first time, I could then no longer implement Entity and File separately with FileImpl extending EntityImpl. Why not? Then there are two distinct superclasses, Entity<EntityImpl> and Entity<FileImpl> for my eventual concrete class tying it all together, and the compile does not like that.

(This is a great spot to point out that languages with multiple inheritance or mixins such as C++ and Scala do no suffer this limitation. It is a direct fallout of single inheritance with generics. You should try it yourself a few times to convince yourself; it took me a while to accept the problem at face value.)

And a directory:

public interface Directory<T extends Entity<T>> {
    boolean isRoot() throws IOException;
}

(By now you are probably wondering about throwing IOException from everywhere. My practical use for reimplementing java.io.File includes networked files so I must accept that all operations potentially fail. Throwing is so much better than the broken example of java.io.File, some methods returning false on failure. And just look at the horror that is createNewFile(), both throwing IOException and returning false depending on the exact failure.)

Problem the second

What about some implementations?

public abstract class LocalEntity <T extends LocalEntity<T>>
        implements Entity<T>, Comparable<LocalEntity<T>> {
    protected final File backing;

    // Constructor, implementations
}

And yet another gotcha! See that backing is marked protected? This is not of necessity because I access backing from classes which extend LocalEntity. It is required because I access backing from within LocalEntity. Here:

public void delete()
        throws IOException {
    if (!backing.delete())
        throw new IOException();
}

public void renameTo(final T newLocation)
        throws IOException {
    if (!backing.rename(newLocation.backing))
        throw new IOException();
}

The delete() method compiles fine if I change backing from protected to private. The renameTo(T) method, however, does not: specifically, newLocation.backing is no longer accessible. That is because T is not the same type as myself; the generic declaration declares that it is some type which extends myself. Hence, I need protected access. That one took a while for me to grok as well.

The final problem

One last final trick. What about the final concrete classes? I want to be able to write Directory dir = new LocalDirectory("/home/binkley") and not worry about generics. There takes quite a bit more magic for that to happen. Watch:

public abstract class LocalDirectoryType <T extends LocalDirectoryType<T>>
        extends LocalEntity<T> implements Directory<T> {
    // Constructors forwarding to super; no methods or members
}

public class LocalDirectory
        extends LocalDirectoryType<LocalDirectory> {
    // Constructors, and unimplemented directory-specific methods
}

Wow! The chicanery is necessary so that the end product, LocalDirectory has no generics. The implementor should do all the work, not the user. I make one last use of CRTP, extend an implementation superclass and add on the Directory interface.

Conclusion

That is a lot of typing. I hope it is all worth it. In C++-land this sort of thing is considered high sport, but most Java folks I know get a sour expression at the sight of generics. Suum cuique pulchrum est.

If you would like to see a fuller example, please drop me a line.

UPDATE: I add an important correction in the following post.

Tuesday, February 22, 2005

Interesting Java design ideas

Thanks to Stephen Colebourne's post on Joda, I took a look at Joda Time - Java date and time API (refreshingly, Joda is not an acronym). Goodness knows the JDK needs help with dates, time and calendars. Joda has several interesting Java design ideas worth consideration for other projects. Among them:

User-oriented
By user, I mean a developer using the library. Many Java libraries seem ambiguous in their orientation: they have many internal bits highly-visible to a user which are really only of interest to library developers. To quote the user guide (really more of an introduction, but written well):
Joda Time is like an iceberg, 9/10ths of it is invisible to user-code. Many, perhaps most, applications will never need to see what's below the surface. This document provides an introduction to the Joda-Time API for the average user, not for the would-be API developer.
Heavy use of interfaces and immutables
The JDK is particularly guilty in underusing interfaces and immutables (e.g., java.io.File). Both interfaces and immutables make for easier to develop, easier to maintain and easier to understand code.
Interesting package structure
In support of being more user-oriented, Joda separates the public bits from the implementation bits with an uncommon package structure. Public bits are where you would expect, underneath org.joda.time. Private bits are in implementation-specific packages, base, chrono, tz, et al. Although unusual, this is very logical.
Wide use of concrete classes
Although designed around interfaces, Joda encourages the use of concrete public implementations reserving the interfaces for common operations between classes and providing for easy means to convert from one to the other. Witness:
public void process(ReadableInstant instant) {
    DateTime dt = instant.toDateTime();
}
Again, in the words of the user guide:
An important point to mention here is that the Joda interfaces are used differently than, for instance, the JDK Collections Framework interfaces. When working with a Collections interface, such as List or Map you will normally hold your variable as a type of List or Map, only referencing the concrete class when you create the object.
List list = new ArrayList();
Map map = new HashMap();
In Joda-Time, the interfaces exist to allow interoperation between similar date implementations, such as a mutable and immutable version of a class. As such, they only offer a subset of the methods of the concrete class. For most work, you will reference the concrete class, not the interface. This gives access to the full power of the library.
DateTime dt = new DateTime();
This seems easy to understand in practise, and I am eager to see how it feels under the fingers as I work with Joda.
Separation of fields and properties
Joda provides traditional getters (e.g., int iDoW = dt.getDayOfWeek();) but also has properties which are richer object versions of simple fields:
DateTime.Property pDoW = dt.dayOfWeek();
String strST = pDoW.getAsShortText(); // returns "Mon", "Tue", etc.
String strT = pDoW.getAsText(); // returns "Monday", "Tuesday", etc.
String strTF = pDoW.getAsText(Locale.FRENCH); // returns "Lundi", etc.
This is a clever innovation of traditional getters/setters and I expect to see more libraries follow Joda in this. The only odd point is that all the property methods return the same type, DateTime.Property. This seems reasonable for DateTime, but does not work for the general case in other libraries.
Overall, Joda is superbly thought out and well-integrated into the JDK (just look at the JDK-Joda converters and the use of the JDK security framework for time changes). More library designers and implementers should study Joda for good patterns to follow.

Monday, February 21, 2005

Using varargs for path names

A handy pair of utility methods:

public static <T> String join(final T separator,
        final T first, final T... rest) {
    final StringBuffer buf = new StringBuffer();

    buf.append(first);

    for (int i = 0; i < rest.length; ++i)
        buf.append(separator).append(rest[i]);

    return buf.toString();
}

And:

public static String makePath(final String root, final String... children) {
    return join(File.separator, root, children);
}

No more junk like node + File.separator + subNode + File.separator + fileName when I can call makePath(node, subNode, fileName).

UPDATE: See the Jakarta Commons Lang version of join(Object[], String) and friends. Unfortunately it predates JDK 5 and varargs by enough that the designer didn't place the separator argument first in the list instead of last.

An old XML friend

A coworker of mine noted that we had this bug: our system would turn filenames with multiple embedded spaces in them into a single space. The culprit? XML. We pass the filenames to a backend server via XML, and XML is not space-preserving for ordinary parsed character data (PCDATA) inside of elements (between start and end tags). There are three solutions:

  1. Escape the spaces
  2. Use CDATA
  3. Write a space-preserving DTD

Of these, I prefer the second, using CDATA. It is the simplest to implement and makes the most readable XML as one does not need to mentally translate the escaped characters. However, it does require that the receiving XML parser understand more than just tags and attributes (and some hand-writter parsers do not, in fact, do any more than just this). The first, escaping the spaces, is probably the most portable but requires work in properly escaping anything in the data that might cause trouble.

The thrid, writing a space-preserving DTD, is the most intersting. In fact, it is probably the most correct solution of all from the perspective of elegance and clarity, but requires the most support from the receiving end. Caveat emptor.

Saturday, February 12, 2005

A more useful way to write JAR files

The Java java.util.jar package has an ancient pedigree. Unfortunately, it shows that the early Java engineers did not all understand object-oriented design. Consider writing a file into a JAR:

// Write foo.jar!bar/qux.txt
JarOutputStream jos
        = new JarOutputStream(new File("foo.jar"));
jos.putNextEntry(new JarEntry("bar/qux.txt"));
writeContentsToOutputStream(jos);
jos.closeEntry();
jos.close();

Contrast with a more modern design:

NewerJarOutputStream newerJos
        = new NewerJarOutputStream(jarFile);
JarEntryOutputStream entryJos= newerJos.openEntry("bar/qux.txt");
writeContentsToOutputStream(entryJos);
entryJos.close();
newerJos.close();

The whole business with putNextEntry/closeEntry is lame, and managing a separate JarEntry object is annoying. What would NewerJarOutputStream and JarEntryOutputStream look like?

class NewerJarOutputStream extends JarOutputStream {
    public JarEntryOutputStream openEntry(final String name) {
        return new JarEntryOutputStream(this, name);
    }
}

class JarEntryOutputStream extends OutputStream {
    private final NewerJarOutputStream jos;

    public JarEntryOutputStream(final NewerJarOutputStream jos,
            final String name) {
        this.jos = jos;

        jos.putNextEntry(new JarEntry(name));
    }

    public void write(final int b) {
        jos.write(b);
    }

    @Override
    public void close() {
        jos.closeEntry();
    }
}

What I have actually written is a SignedJarOutputStream to provide programmatic JAR signing and the attendent classes such as SignedJarFile, et al. Unfortunately, the literature is a bit dowdy, and Sun provides very little help. But the task was interesting, and the JAR signing specification is elegant and well-considered even if over-sparse. Factum est.

Another way to write code in the annotation processor

As noted, it is hard to write annotation processors in part because there's no easy way to read in the source Java code, nor write out new code. The first problem still requires some kind of Java parser to generate an AST, but CodeMonkey looks like an interesting tool for the second problem.

Wednesday, February 09, 2005

The one-line urge

Sometimes the one-line urge gets the best of me:

someMethodCall(new ArrayList<String>(2) {
    {
        add("foo");
        add("bar");
    }
});

Yes! It is the infamous anonymous instance initializer block. I suppose it would not have killed me to type instead:

final List<String> listy = new ArrayList<String>(2);
listy.add("foo");
listy.add("bar");
someMethodCall(listy);

But the one-liner was so much more fun to format with my editor. This is what pair programming is good for, to stop non-sense like that. When you have a peer watching you type, you are too embarrassed to commit unmaintainable code into the codebase.

UPDATE: Looking of the documentation for java.util.Arrays.asList(T... a) made me realize an even easier way to get the one-liner, and a maintainble one at that:

someMethodCall(Arrays.asList("foo", "bar"));

How slick!

Re: Creating an array from a generic Java collection

I'm reading Paul's post on arrays and generics and although I don't have an answer to his interesting question, I did find this trick today for narrowing a Java array as a one liner using a List as an intermediate. The trick depends on List using generics:

I have an Certificate[] array for a private key from a key store. I happen to know that all of the array elements are actually X509Certificate and I'm calling into an undocumented API in the JDK which requires an array of such a critter. What's the easiest thing to do?

public static X509Certificate[] narrowToX509(final Certificate[] certificates) {
    return Arrays.asList(certificates).toArray(
            new X509Certificate[certificates.length]);
}

As I explained to a coworker, Java arrays are not related to the object types they hold: just because SubFoo extends Foo does not mean SubFoo[] extends Foo[]. But all arrays do extend java.lang.Object.

UPDATE: Although my trick is still just as useful, my comment about it depending on generics is completely crocked. It is true that asList is generified, but that does not make the trick work.

Tuesday, February 08, 2005

Another way to look up the location of a class file

I wrote in looking up the location of a class file with this suggestion:

new File(clazz.getProtectionDomain().getCodeSource()
        .getLocation().toURI().normalize())

But this failed for me while looking up SignatureFile: the protection domain for this class turned up with no associated code source. I'm not sure if it is related, but the class appears in rt.jar and tools.jar and as a package-scope inner class in JarSigner.

In particular, I'm unable to compile the constructor call, new SignatureFile(Manifest, String) (I'm rolling my own programmatic jar signer).

As is often the case, it turns out there's another way:

new File(clazz.getResource(
        "/" + clazz.getName().replace(".", "/") + ".class").toURI());

With interesting results:

jar:file:/C:/jdk1.5.0_01/jre/lib/rt.jar!/sun/tools/jar/SignatureFile.class

Now I can see which class definition is pulled in. On to figure out why my constructor call does not compile.

UPDATE: Talk about bit in the ass. Here is the full signature with packages for the constructor I am interested in according to SignatureFile.class.getDeclaredConstructors():

public sun.tools.jar.SignatureFile(sun.tools.jar.Manifest,
        java.lang.String) throws sun.tools.jar.JarException

Am I using sun.tools.jar.Manifest? No! I am using the more sane java.util.jar.Manifest class. Oops. And they are not replaceable for each other. Time to rethink.

Monday, February 07, 2005

Taking another tack

I'm a big fan of XP, the programming methodology. But I sometimes have difficulty spreading my enthusiasm at work. XP can be offputting to the uninitiated, and its advocates are at times boat-rockers. So I'm looking at other ways to spread agile methodologies than just XP.

Looking over my shelf I spy Applying UML and Patterns by Craig Larman, something I picked up while at ThoughtWorks, but never got very far into (too many good books to read!). Larman introduces the Unified Process or just UP. At first I was wary, but as I've been reading his book I see how much XP and UP have in common. More to my problem, UP looks like it would appeal well to process-oriented but open-minded businessmen.

Perhaps, then, I should consider changing tack, and point out UP resources to my coworkers. Taking up UP might be a fine way to promote agile programming, and the UML review[*] in Larman is a big help.

[*] The agile modeling link also has an excellent case study on introducing agile programming into a non-agile environment.

Saturday, February 05, 2005

More fun with enum

The Enum<E extends Enum<E>> class is very special: only the compiler is able to create instances of classes which extends Enum. This prevents the creation of dynamic enumerations. But there is hope:

final MockControl control = MockClassControl.createControl(
        Enum.class,
        new Class[]{String.class, int.class},
        new Object{"Foo", 1});
final Enum mock = (Enum) control.getMock();

System.out.println("mock.name() = " + mock.name());
System.out.println("mock.ordinal() = " + mock.ordinal());

The magic of EasyMock and its class extension (using cglib under the hood) creates a Java proxy for Enum. Bytecode engineering to the rescue!

But do note that some methods associated with enumerations (such as values()) do not exist in the base class, Enum. They are synthesized by the compiler specific to each enumeration class.

Friday, February 04, 2005

Unusual use for enum

In JDK 5, enum isn't just a collection of static instances, it is also conceptually a list and a map (although it does not implement these interfaces). To wit:

enum Hierarchy {
    ACCOUNT(Preferences.userNodeForPackage(Account.class)),
    LOCAL(Preferences.userNodeForPackage(Local.class)),
    SYSTEM(Preferences.systemNodeForPackage(System.class)),
    GLOBAL(Preferences.systemNodeForPackage(Global.class));

    private final Preferences preferences;

    Hierarchy(final Preferences preferences) {
        this.preferences = preferences;
    }

    public Preferences getPreferences() {
        return preferences;
    }

    private static final class Account { }
    private static final class Local { }
    private static final class System { }
    private static final class Global { }
}

This creates a hierachy of preferences. Finding a match is simple:

public String get(String key, String def) {
    for (final Hierarchy hierarchy : Hierarchy.values()) {
        final String preference = hierarchy.getPreferences().get(key,
                null);

        if (null != preference) return preference;
    }

    return def;
}

As the for loop iterates over the values of the enumeration in order of declaration, this ensures they individual preferences are searched in order. In effect, they are overlaid. And the encapsulation is particularly elegant.

An immediate design decisions lays ahead: Should methods such as get(String, String) and its ilk be static members of the enumeration, or should the enumeration be a private class inside a utility class which has the various get/put pairs?

UPDATE: In the original posting, I mistakenly assigned system nodes for ACCOUNT and LOCAL instead of user nodes. Fixed.

UPDATE: Oops! Preferences are stored per-package, not per-class. My clever trick still works, provided I make packages out of the categories rather than inner classes. I lose the encapsulation, but keep the technique. Unless I can create packages on the fly at run-time.

Reflection humor

Here is a funny bit of Java code:

private static class Root {
    protected Root(final String intFieldName) {
        try {
            final Field i = getClass().getDeclaredField(intFieldName);
            i.setAccessible(true);
            i.set(this, 4);

        } catch (final NoSuchFieldException e) {
            throw new IllegalArgumentException(intFieldName);

        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException(intFieldName);
        }
    }
}

private static class Branch extends Root {
    private int i = 3;

    public Branch() {
        super("i");

        System.out.println("i = " + i);
    }
}

What does new Branch() print? A better question, why?

UPDATE: A great answer to my question.

Localized exception messages

Some programs I work on use getMessage() from an exception for display to end-users when problems crop up. Other programs use the message as a key into a message bundle. The question is, how do I localize the text of getMessage()?

The authors of java.lang.Throwable planned for this and provided getLocalizedMessage() which is not overridden in java.lang.Exception. However, the implementation is:

public String getLocalizedMessage() {
    return getMessage();
}

To make this useful I write a new abstract class, LocalizedException, with two overriden methods and a new abstract method:

/**
 * {@inheritDoc}
 * <p/>
 * This implementation throws {@code UnsupportedOperationException}.  Use
 * {@link #getLocalizedMessage()} instead.
 *
 * @return this implementation never returns
 *
 * @throws UnsupportedOperationException
 * @see #getLocalizedMessage()
 */
public String getMessage() {
    throw new UnsupportedOperationException(
            "CODING ERROR: call getLocalizedMessage() instead");
}

/**
 * {@inheritDoc}
 * <p/>
 * This implementation delegates to {@link #translateMessage(String)}
 * with the original exception message text.
 *
 * @return {@inheritDoc}
 *
 * @see #translateMessage(String)
 */
public String getLocalizedMessage() {
    return translateMessage(super.getMessage());
}

/**
 * Translates exception <var>message</var> text.
 * Implementations depend on the nature of the text.  For example,
 * one implementation might require the text to be keys into a
 * message bundle.  Another might require the text to be the message
 * text in the default locale.
 *
 * @return the translated exception message text
 */
protected abstract String translateMessage(final String message);

Using this class, write concrete implementations of translateMessage that can figure out how to internationalize the message strings particular to your program.

Thursday, February 03, 2005

More on using apt

The ServerSide has a news article on a new JSR from Sun for addressing shortcomings in writing annotation processors. This is a topic which interests me, and it is clear that annotation processors as they exist right now are ungainly beasts. I look forward to Sun and the JSR process fixing this.

At a minimum, I'd like to know from within an annotation processor just what are the boundaries of a method. Right now the processor knows the textual start of a method in the source file, but that is it. Best would be an AST for the method, permitting me to rewrite the method and emit that from the processor. I can dream.

Wednesday, February 02, 2005

Methods I cannot do without

In almost any project I work on I wind up writing certain methods over and over again. High among them are:

public static void copyAndClose(final InputStream in, final OutputStream out)
        throws IOException {
    try {
        // CopyUtils is from Jakarta IO
        CopyUtils.copy(in, out);
        out.flush();

    } finally {
        try {
            out.close();

        } finally {
            in.close();
        }
    }
}

public static File createTemporary(final String prefix) {
    final File tmp = File.createTempFile(prefix, null);

    tmp.deleteOnExit();

    return tmp;
}

Perhaps I can persuade Jakarta IO to take on copyAndClose, but there seems low odds of the JDK including createTemporary.