Thursday, January 18, 2007

Controlling a blocking queue in Java

Recently I needed a blocking queue in Java in which I could pause the reader side. Normal behavior is for queue.take() to block so that a reader only runs when there are elements in the queue to process. What I wanted was for there to also be a throttle, so I could pause reading even when there were elements to process. It is not difficult, in fact, to make such a queue in which either end might be paused or stopped, and resumed or restarted:

public class LinkedControllableBlockingQueue<E>
        extends LinkedBlockingQueue<E>
        implements ControllableBlockingQueue<E> {
    // Read side
    private final Lock readLock = new ReentrantLock();
    private final Condition resumed = readLock.newCondition();
    private final AtomicReference<Thread> pausingThread
            = new AtomicReference<Thread>();

    // Write side
    private final Lock writeLock = new ReentrantLock();
    private final Condition restarted = writeLock.newCondition();
    // Begin started
    private final AtomicReference<Thread> startingThread
            = new AtomicReference<Thread>(currentThread());

    // Controllable

    public boolean isStarted() {
        return null != startingThread.get();
    }

    public boolean isPaused() {
        return null != pausingThread.get();
    }

    public void start() {
        if (!startingThread.compareAndSet(null, currentThread()))
            throw new IllegalStateException("Already started");

        writeLock.lock();
        try {
            restarted.signalAll();
        } finally {
            writeLock.unlock();
        }
    }

    public void pause() {
        if (!pausingThread.compareAndSet(null, currentThread()))
            throw new IllegalStateException("Already paused");
    }

    public void resume() {
        if (!pausingThread.compareAndSet(currentThread(), null))
            throw new IllegalStateException("Not paused by current thread");

        readLock.lock();
        try {
            resumed.signalAll();
        } finally {
            readLock.unlock();
        }
    }

    public void stop() {
        if (!startingThread.compareAndSet(currentThread(), null))
            throw new IllegalStateException("Not started by current thread");
    }

    // LinkedBlockingQueue

    // Read side

    @Override
    public E take()
            throws InterruptedException {
        readLock.lock();
        try {
            while (isPaused())
                resumed.await();
        } finally {
            readLock.unlock();
        }

        return super.take();
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Time spent <em>paused</em> is subtracted from <var>timeout</var>.  That
     * is, the total time spent in {@code poll} is the same for the pausing and
     * non-pausing versions of {@code LinkedBlockingQueue} for a given
     * <var>timeout</var> and <var>unit</var>.
     */
    @Override
    public E poll(final long timeout, final TimeUnit unit)
            throws InterruptedException {
        long nanos = unit.toNanos(timeout);

        readLock.lock();
        try {
            while (isPaused())
                if (0 >= (nanos = resumed.awaitNanos(nanos)))
                    return null;
        } finally {
            readLock.unlock();
        }

        return super.poll(nanos, NANOSECONDS);
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Returns {@code null} if paused.
     */
    @Override
    public E poll() {
        readLock.lock();
        try {
            if (isPaused())
                return null;
        } finally {
            readLock.unlock();
        }

        return super.poll();
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Returns {@code null} if interrupted while paused.
     */
    @Override
    public E peek() {
        readLock.lock();
        try {
            while (isPaused())
                resumed.await();
        } catch (final InterruptedException e) {
            return null;
        } finally {
            readLock.unlock();
        }

        return super.peek();
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Returns {@code false} if interrupted while paused.
     */
    @Override
    public boolean remove(final Object o) {
        readLock.lock();
        try {
            while (isPaused())
                resumed.await();
        } catch (final InterruptedException e) {
            return false;
        } finally {
            readLock.unlock();
        }

        return super.remove(o);
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Also throws {@code NoSuchElementException} if interrupted while paused.
     */
    @Override
    public E remove() {
        readLock.lock();
        try {
            while (isPaused())
                resumed.await();
        } catch (final InterruptedException e) {
            throw new NoSuchElementException(e.getMessage());
        } finally {
            readLock.unlock();
        }

        return super.remove();
    }

    // Write side

    @Override
    public void put(final E o)
            throws InterruptedException {
        writeLock.lock();
        try {
            while (!isStarted())
                restarted.await();
        } finally {
            writeLock.unlock();
        }

        super.put(o);
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Time spent <em>stopped</em> is subtracted from <var>timeout</var>.  That
     * is, the total time spent in {@code offer} is the same for the stopping
     * and non-stopping versions of {@code LinkedBlockingQueue} for a given
     * <var>timeout</var> and <var>unit</var>.
     */
    @Override
    public boolean offer(final E o, final long timeout, final TimeUnit unit)
            throws InterruptedException {
        long nanos = unit.toNanos(timeout);

        writeLock.lock();
        try {
            while (!isStarted())
                if (0 >= (nanos = restarted.awaitNanos(nanos)))
                    return false;
        } finally {
            writeLock.unlock();
        }

        return super.offer(o, nanos, NANOSECONDS);
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Also returns {@code false} if interrupted while stopped.
     */
    @Override
    public boolean offer(final E o) {
        writeLock.lock();
        try {
            while (!isStarted())
                restarted.await();
        } catch (final InterruptedException e) {
            return false;
        } finally {
            writeLock.unlock();
        }

        return super.offer(o);
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Also returns {@code false} if stopped.
     */
    @Override
    public boolean add(final E o) {
        return isStarted() && super.add(o);
    }
}

Wednesday, December 27, 2006

Making a one-jar with Maven

(This is a lengthier post than usual. You can skip forward to the finished example, if you like.)

UPDATE:The One-JAR author comments:

Nice article, thanks for using (and persisting with) One-JAR. I just released a new version (0.97), checkout http://one-jar.sourceforge.net/

The one-jar-maven plugin has been updated with this new release, and there is also a new project in the CVS repository showing how to use maven2 to build (http://one-jar.cvs.sourceforge.net/viewvc/one-jar/one-jar-maven/)

A major part of this release was making it easier to set up One-JAR projects, to which end there is an application generator (one-jar-appgen) which will create a basic One-JAR directory tree, with support for building under Eclipse/Ant, and which contains a JUnit test harness. I’d be interested in hearing your thoughts on this if you’re still working with the product.

One-JAR

I recently came across Simon Tuffs' One-JAR Java project. It uses a custom "boot" classloader to place whole JARs within JARs and fix up the classpath accordingly.

The standard classloader will not do this and requires that supporting JARs be external to each other. So if I have Main.jar with dependency log4j.jar where Main.jar holds the main entry point—hm.binkley.Main, say—I cannot bundle log4j.jar into Main.jar but must distribute it alongside separately.

This has no effect on running Java, but changes distribution as I can no longer provide a single file (Main.jar in this example) for others to run.

Contrast these two ZIP files:

  • Foo-1.0-with-one-jar.zip:
    • foo-1.0/Main.jar
    • foo-1.0/README
  • Foo-1.0-without-one-jar.zip:
    • foo-1.0/Main.jar
    • foo-1.0/log4j.jar
    • foo-1.0/README

In this example, it does not seem to make a lot of difference; but when a project pulls in several Jakarta Commons JARs, several other open-source JARs, and several in-house, proprietary JARs, it becomes very obvious that distribution is an issue. One project I work on has a java command line between 5000 and 6000 characters long because of external jar dependencies in the classpath.

A traditional solution is to repack all the classes, internal and external, in to a single über-JAR, losing the independent qualities of each JAR including interesting MANIFEST.MF entries.

One-JAR solves this elegantly by packing everything into one JAR without unpacking the dependencies. My command line becomes just:

$ java [-options] -jar Main.jar

Ant

An Ant script for One-JAR is simple. One-JAR requires that you pack your original Main.jar into the final, single JAR along with dependencies:

  • main/Main.jar
  • lib/log4j.jar

They pack in with the One-JAR classes.

One-JAR then provides a custom classloader and alternative main entry point to glue it all together and a custom URL for classloading, onejar:.

As One-JAR provides you with a prototype outer JAR, all you need do is update the prototype, adding in main/Main.jar and lib/log4j.jar with Main.jar!main/Main.jar!META-INF/MANIFEST.MF unchanged:.

Manifest-Version: 1.0
Main-Class: hm.binkley.Main
Class-Path: log4j.jar

Leave unchanged the Main.jar!META-INF/MANIFEST.MF provided in the prototype:

Manifest-Version: 1.0
Main-Class: com.simontuffs.onejar.Boot

(Note that the first Main.jar is the prototype copied from one-jar-boot-0.95.jar, provided with the One-JAR download, and the second Main.jar is your original executable JAR.)

One-JAR follows the convention that your "real" JAR is in main/ and all dependency JARs are elsewhere within your single, distributable JAR. Nothing is unpacked.

The jar task handles this ably:

<target name="one-jar" depends="jar" description="Build one ONE-JAR">
    <property name="onejardir" location="${pom.build.directory}/one-jar"/>
    <mkdir dir="${onejardir}/main"/>
    <mkdir dir="${onejardir}/lib"/>

    <copy tofile="${onejardir}/${jarfile}"
            file="lib/one-jar-boot-0.95.jar"/>
    <copy todir="${onejardir}/main"
            file="${pom.build.directory}/${jarfile}"/>
    <copy todir="${onejardir}/lib" flatten="true">
        <fileset dir="lib" includes="*.jar"
                excludes="one-jar-boot-0.95.jar"/>
        <fileset refid="runtime.dependency.fileset"/>
    </copy>

    <jar jarfile="${onejardir}/${jarfile}" update="true"
            basedir="${onejardir}" excludes="${jarfile}"/>
</target>

But what of Maven?

Maven

Where Ant asks, How do I make this cake? - Maven asks Where can I find cake ingredients? But Maven does provide a mechanism for adding new recipes, the assembly plugin.

An assembly is a description of packaging for Maven, and is usually hooked into the package phase in your build lifecycle. (The assembly plugin is much simpler than adding new packaging with Plexus, the method described in the link.)

To build a One-JAR with Maven and the assembly plugin, add a new assembly descriptor which follows the outline of building with Ant, taking care to unpack the One-JAR prototype JAR and add to it Main.jar and its dependencies.

This is better explained by example.

Example

The sources

Unfortunately, One-JAR is not in the Maven central repository, so it is included here as part of the project. That is the reason for the added repository in the POM and the lib/ files. Ignoring directories:

  • lib/com/simontuffs/one-jar/0.95/one-jar-0.95.jar
  • lib/com/simontuffs/one-jar/0.95/one-jar-0.95.pom
  • pom.xml
  • src/assembly/one-jar.xml
  • src/main/java/hm/binkley/Main.java
  • src/main/resources/log4j.properties

The POM

<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>hm.binkley</groupId>
    <artifactId>Main</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>
    <name>One-JAR Example</name>
    <url>http://binkley.blogspot.com/</url>

    <repositories>
        <repository>
            <id>project</id>
            <name>Project Repository</name>
            <url>file:///${basedir}/lib</url>
            <layout>default</layout>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>hm.binkley.Main</mainClass>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.simontuffs.onejar.Boot</mainClass>
                        </manifest>
                    </archive>
                    <descriptors>
                        <descriptor>src/assembly/one-jar.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>attached</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>com.simontuffs</groupId>
            <artifactId>one-jar</artifactId>
            <version>0.95</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
    </dependencies>
</project>

The assembly

In src/main/assembly/one-jar.xml:

<assembly>
    <id>one-jar</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory/>
            <unpack>true</unpack>
            <includes>
                <include>com.simontuffs:one-jar</include>
            </includes>
        </dependencySet>
        <dependencySet>
            <outputDirectory>main</outputDirectory>
            <includes>
                <include>${groupId}:${artifactId}</include>
            </includes>
        </dependencySet>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
            <excludes>
                <exclude>com.simontuffs:one-jar</exclude>
                <exclude>${groupId}:${artifactId}</exclude>
            </excludes>
        </dependencySet>
    </dependencySets>
</assembly>

The finished One-JAR

  • META-INF/MANIFEST.MF
  • com/simontuffs/onejar/Boot.class
  • com/simontuffs/onejar/Boot.java
  • com/simontuffs/onejar/Handler$1.class
  • com/simontuffs/onejar/Handler.class
  • com/simontuffs/onejar/Handler.java
  • com/simontuffs/onejar/JarClassLoader$ByteCode.class
  • com/simontuffs/onejar/JarClassLoader.class
  • com/simontuffs/onejar/JarClassLoader.java
  • doc/one-jar-license.txt
  • main/Main-1.0.jar
  • lib/log4j-1.2.14.jar

Thursday, December 14, 2006

Brilliant: C to MIPS to Java bytecode

NestedVM is one of the cleverest solutions to the problem of legacy C and C++ code I have ever seen: use GCC to compile to MIPS machine instructions, then translate those directly into Java bytecode.

There is also a good slideshow.

A straight-forward example is a pure-Java translation of the SQLite JDBC driver.

Wednesday, November 22, 2006

What is the type of this in Java?

I was late to read: Peter Ahé has a wonderful post on the type of this.

Among the gems:

  • Design issues with generics
  • A lengthy, well-developed example
  • Laird Nelson is a great name

Thursday, November 02, 2006

Java enum misuse

The Java enum is a nice feature, but like anything it is open to abuse. Witness:

enum OverTheTop {
    A, B;

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(final String value) {
        this.value = value;
    }
}

Even though the instances of OverTheTop are fixed and immutable, enums are after all simply class instances and can be use anyway a class can be used. This is the same problem with unmodifiable collections having modifiable members.

You could view enums as a generalization of singletons, having a fixed number of members not limited to just one. (Class loading is thread safe — does this mean one can use a single-member enum to implement a thread-safe singleton?)

As abusive as enums with setters seems, worse still remains:

enum TrulyUnpredictable {
    A, B;

    private Runnable runnable;

    public void setRunnable(final Runnable runnable) {
        this.runnable = runnable;
    }

    public void run() {
        new Thread(runnable).start();
    }
}

As unmaintainable as this seems (what does TrulyUnpredictable.A.run() do?), there are legitimate uses for complex enums.

Say you have a limited set of algorithm implementations and would like to switch on them:

enum Algorithm {
    FAST(ImplementationFactory.getInstance("FAST")),
    ACCURATE(ImplementationFactory.getInstance("ACCURATE")),
    EFFICIENT(ImplementationFactory.getInstance("EFFICIENT"));

    private final Implementation implementation;

    Algorithm(final Implementation implementation) {
        this.implementation = implementation;
    }

    public double calculate() {
        return implementation.calculate();
    }
}

And for the fan of difficult syntax:

enum Algorithm {
    FAST() {
        public double calculate() {
            new FastImplementation().calculate();
        }
    },
    ACCURATE() {
        public double calculate() {
            new AccurateImplementation().calculate();
        }
    },
    EFFICIENT() {
        public double calculate() {
            new EfficientImplementation().calculate();
        }
    };

    public abstract double calculate();
}

There are very many variations on these themes, but it is not too difficult to reach the point where no one can read your code except you.

Monday, October 30, 2006

The null collection anti-pattern

NEVER do this:

public Collection<T> doTheMacarena() {
    if (isPresidentialElection())
        return null;

    return visitSouthAmerica();
}

ALWAYS throw exceptions or return empty collections; never use null as a kind of "soft exception". Either:

if (isPresidentialElection())
    throw new UnwiseCampaignTacticException();

Or:

if (isPresidentialElection())
    return Collections.emptySet();

Are preferable, depending on whether the return-condition is fast-failure or the "no data" sort.

How would you like to spend your day debugging:

for (final Dancer dander : doTheMacarena())
    dancer.dazzleWithSmoothMoves();

From inside miles of nested code across several transaction and remote boundaries?

UPDATE: A nice post from Nishanth Shastry on the for-each loop. Look at item #6, Return zero length arrays or empty lists rather than nulls.

Monday, October 16, 2006

Live or Memorex?

The Daily WTF has run a series of posts on Virtudyne, a $200 million spectacular failure of a software company.

Many commenters have suggested that the anonymized company referred to throughout is my former employer, SimDesk.

I signed a document upon leaving SimDesk which prevents me from expressing my opinion about such things, but I hope you might enjoy reading the articles nonetheless. And please sweep for bugs, just to be sure.

Sunday, October 01, 2006

Correction for read-only Java objects

The problem

In my own code I sometimes bypass a getter for a final field in favor of direct field access for struct-like classes:

public class BigFoot {
    public final int shoeSize;

    public BigFoot(final int shoeSize) {
        this.shoeSize = shoeSize;
    }
}

I figure: why not? As the field is final there is no need for modifying behavior in a getter method. This seems ideal for data transfer objects (DTOs).

However Miles Barr points out the big flaw with this idea. It is subtle and has to with how the Java compiler deals with direct field access. Miles explains the problem as well as anyone and has a clear example. Fundamentally, you lose polymorphism for shadowed variables and bad things result.

The solution

The mistake for my DTO was not carrying the notion of simple struct-ness to its full conclusion. How much sense does it make to extend DTOs?

public final class BigFoot {
    public final int shoeSize;

    public BigFoot(final int shoeSize) {
        this.shoeSize = shoeSize;
    }
}

If the class is marked final then there will never be a problem with shadowing fields in subclasses.

A caveat

Sometimes I want to extend my DTOs when I have a set of similar data to represent and extract out the common fields in to a base class.

But this is an implementation detail. Logically there is no class relationship among the DTOs and the problem with shadowed fields is one which exposes an implementation detail to the user.

So don't do that.

Wednesday, September 20, 2006

Tom Ball's Hacking javac

Tom Ball posts a chok-full-of-nuts run through of the nifty javac happenings comming out of JDK6, leading to things like Sorcerer.

Normally I avoid posts which simply link to someone else (I rely on Erik's Linkblog for that beneficial service, but he's on vacation right now), but Ball is really on the ball with this one. I can't wait to try these out in a real project.

Wednesday, September 13, 2006

JPMorgan Investment Bank

I've been hired on this week to a permanent position with JPMorgan Investment Bank—no more contracting for me.

It's a double pleasure: I've been picked by a team with former ThoughtWorkers, an all-agile team. After getting some preliminaries out of the way, today I'll dial in for my first daily standup in several years.

I was just reading Tim Ottinger in More Work? discuss some of the benefits of agile development. It's great to see a smart place like JPMorgan with agile teams and a management that believes in its staff.

Wednesday, September 06, 2006

The continuing influence of Smalltalk

My friend Paul Holser likes to point out to me how great Smalltalk is. Just this past weekend he and I were chatting about it at the Rice's opening game (we beat the spread).

Lo and behold, why the lucky stiff mentions on 06 Sep 2006 at 13:17 (emphasis mine):

So, Matz cites four reasons for this decision:

  1. The spread of ActiveSupport has increased the need for strings and symbols to be united as hash keys.
  2. To address RCR 342 , which would allow sorting of symbols. (Try: Symbol.all_symbols.sort.)
  3. Smalltalk’s symbols are a subclass of string. (He adds that this is his most motivating reason to do it.)
  4. Using symbols as immediate values can cause them to venture into pointer territory, particularly on OSX .

Smalltalk never dies, it just slowly gets absorbed by languages with good taste.

Tuesday, September 05, 2006

Java applications, messaging and exceptions

On and off I have looked at messaging for Java applications as an alternative, more loosely coupled design pattern. Particularly for smaller applications messaging has some interesting solutions in lieu of other approaches.

Take the event listener model for AWT/Swing. Each component is responsible for maintaining its own listener event list, and each listener is responsible for finding the component it wants to get events from. This is, of course, the Observer pattern.

I want more decoupling. Message busses decouple this pattern by managing listeners and delivering events—I grew up calling this publish/subscribe—mixing in the Mediator pattern models the bus.

Channels and Subscribers

I'm going to call the bus a channel. There are many common vocabulary choices for the kind of simple message bus I have in mind, and channel is the one I used most with Gregory Hohpe who introduced me to this design. Start with the channel interface:

public interface Channel {
    void subscribe(Object subscriber);
    void unsubscribe(Object subscriber);
    void publish(Object message) throws Exception;
}

Choices, choices. Most messaging interfaces I see use a topic text to distinguish messages when publishing. But like the AWT/Swing event system, I prefer objects so that I may use inheritance to narrow or widen the scope of events I receive. Subscribers receive any intersection or union of message types they want using simple method overloading. For example:

interface BobTheBuilder {
    void onMessage(CanHeFixItRequest message);
    void onMessage(YesHeCanDispute message);
}

class MessageLogger {
    public void onMessage(Object message) {
        SomeLogger.logMessage(message);
    }
}

MessageLogger subscribes to all possible message types planning to ambitiously log everything. BobTheBuilder is only interested in requests to fix something or in criticisms of his abilities.

Supporting the union of disjoint message types explains why subscribe(Object):void and unsubscribe(Object):void take object arguments rather than using a Subscriber interface. Sketch out what Subscriber might look like with typed messages:

interface Subscriber<T> {
    void onMessage(T message);
}

This works great is a subscriber wants a single type of message, but Java does not support classes implementing the same interface multiple times—generics does not produce different interfaces:

interface IllegalJavaSubscriber {
        implements Subscriber<String>, Subscriber<Integer> {
    // Will not compile.
}

And the lack of typed interfaces for subscribers implies that the signature for onMessage(Object):void cannot narrow either. What to do? The only option is reflection. So I reflect for "onMessage" methods with the correct signature and handle overriding and overloading in the bus.

All in all I get a lot of flexibility for very little work by subscribers using the bus.

Exceptions

But what of exceptions? I realized, given the inheritance of message types, that I could simply publish exceptions as messages, same as any other type. Exception handlers simply subscribe to messages:

class ExceptionLogger {
    public void onMessage(final Exception e) {
        SomeLogger.logException(e);
    }
}

This is akin to how AOP works but without the extra syntax or new language to learn. The try/catch normally in each subscriber for logging exceptions is gathered together into the message bus with pseudo-code akin to:

for (final Subscriber subscriber
        : getSubscribersForMessage(message))
    try {
        invokeOnMessage(subscriber, message);
    } catch (final Exception e) {
        this.publish(e); // I am a channel
    }

This simplicity is very appealing, but it leaves out an interesting possibility: that subscribers could try redeliving a message to just the failed cases. Adding one more reflected method adds this option:

class SystemMonitor {
    public void onMessageException(Exception e,
        Object subscriber, Object message) {
        fixSystem(); // magic
        retryMessage(subscriber, message); // more magic
    }
}

In principal a subscriber could republish using the signature after fixing some broken part of the system. It would also make logging more informative.

Active Messages

Using pure reflection opens up another design choice, active messages. Simply having messages themselves provide an onMessage method and subscribe to the channel. Messages can publish themselves. As clever as this seems, it does leave me in fear of maintaining someone else's system years hence in which the entire thing is a ball of spaghetti with messages and subscribers calling hither, thither and yon.

Debugging is a problem with systems like this. YMMV.

Code

Some simple code illustrating this post.

Tuesday, August 29, 2006

Filling in the Java closure gap

The interesting FuntionalJ library fills in a gap with reflective function objects while waiting for JDK7 closures. With flavors of C++ functors and Python zip and tuples, FuntionalJ is a gem.

Tuesday, August 22, 2006

Two new toys to try out

Today I'm looking at two new web toys:

Getting started on JRuby, a great post

Ola Bini has a great post on getting started with JRuby on Windows, The JRuby Tutorial #1: Getting started, followed up with more excellent posts in the JRuby tutorial series.

Monday, August 21, 2006

Mapping a Java bean

This is a straight-forward code post.

public class BeanMap<T>
        extends AbstractMap<String, Object> {
    private final T bean;
    private final Set<PropertyDescriptor> descriptors;

    public BeanMap(final T bean)
            throws IntrospectionException {
        this.bean = asNotNull(bean, "Missing bean");

        final Set<PropertyDescriptor> descriptors
                = new HashSet<PropertyDescriptor>();

        for (final PropertyDescriptor descriptor
                : getBeanInfo(bean.getClass()).getPropertyDescriptors())
            // Only support simple setter/getters.
            if (!(descriptor instanceof IndexedPropertyDescriptor))
                descriptors.add(descriptor);

        this.descriptors = unmodifiableSet(descriptors);
    }

    public Set<Entry<String, Object>> entrySet() {
        return new BeanSet();
    }

    @Override
    public Object get(final Object key) {
        return super.get(checkKey(key));
    }

    @Override
    public Object put(final String key, final Object value) {
        checkKey(key);

        for (final Entry<String, Object> entry : entrySet())
            if (entry.getKey().equals(key))
                return entry.setValue(value);

        return null;
    }

    @Override
    public Object remove(final Object key) {
        return super.remove(checkKey(key));
    }

    private String checkKey(final Object key) {
        // NB - the cast forces CCE if key is the wrong type.
        final String name = (String) key;

        if (!containsKey(asNotNull(name, "Missing key")))
            throw new IllegalArgumentException("Bad key: " + key);

        return name;
    }

    private class BeanSet
            extends AbstractSet<Entry<String, Object>> {
        public Iterator<Entry<String, Object>> iterator() {
            return new BeanIterator(descriptors.iterator());
        }

        public int size() {
            return descriptors.size();
        }
    }

    private class BeanIterator
            implements Iterator<Entry<String, Object>> {
        private final Iterator<PropertyDescriptor> it;

        public BeanIterator(final Iterator<PropertyDescriptor> it) {
            this.it = it;
        }

        public boolean hasNext() {
            return it.hasNext();
        }

        public Entry<String, Object> next() {
            return new BeanEntry(it.next());
        }

        public void remove() {
            it.remove();
        }
    }

    private class BeanEntry
            implements Entry<String, Object> {
        private final PropertyDescriptor descriptor;

        public BeanEntry(final PropertyDescriptor descriptor) {
            this.descriptor = descriptor;
        }

        public String getKey() {
            return descriptor.getName();
        }

        public Object getValue() {
            return unwrap(new Wrapped() {
                public Object run()
                        throws IllegalAccessException,
                        InvocationTargetException {
                    final Method method = descriptor.getReadMethod();
                    // A write-only bean.
                    if (null == method)
                        throw new UnsupportedOperationException(
                                "No getter: " + descriptor.getName());

                    return method.invoke(bean);
                }
            });
        }

        public Object setValue(final Object value) {
            return unwrap(new Wrapped() {
                public Object run()
                        throws IllegalAccessException,
                        InvocationTargetException {
                    final Method method = descriptor.getWriteMethod();
                    // A read-only bean.
                    if (null == method)
                        throw new UnsupportedOperationException(
                                "No setter: " + descriptor.getName());

                    final Object old = getValue();
                    method.invoke(bean, value);
                    return old;
                }
            });
        }
    }

    private static interface Wrapped {
        Object run()
                throws IllegalAccessException,
                InvocationTargetException;
    }

    private static Object unwrap(final Wrapped wrapped) {
        try {
            return wrapped.run();

        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);

        } catch (final InvocationTargetException e) {
            // Javadocs for setValue indicate cast is ok.
            throw(RuntimeException) e.getCause();
        }
    }
}

The idea is simple: give the Java getter/setter idiom a Map interface. Commons Beanutils already does this but with a significant difference.

My example class is very brittle. It doesn't like null, wrong classes or missing keys. And in a brittle language like Java, this is a good thing. This kind of brittleness finds bugs quickly following the venerable fail-fast principle.

Avoid code which returns null or silently converts wrong-class arguments. You pay now in return for a clear conscience in the long term. I have better things to do with my time than debug NullPointerExceptions.

Thursday, August 17, 2006

Class literal woes

In Bitten by the class literal change in Tiger Michael Nascimento writes about the surprising impact of JDK5 changing the rules for Foo.class. As simple as that.

Amazing how such a small change can have ramifications. This is food for thought when making a "small change" as I often do while cleaning old code: How can it make a difference? should be asked as a real question, not as gesture to shrug off the nay-sayers.

May I follow my own advice!

Tuesday, August 15, 2006

Strange mini anti-pattern

It's strange seeing this:

List copy = (List) ((ArrayList) original).clone();

When this will do:

List copy = new ArrayList(original);

And as a bonus original need not be an ArrayList.

Saturday, August 12, 2006

Ask, and ye shall receive

No sooner had I posted a Java enhanced for loop wish than a commenter pointed out the JGA and jga & the java 1.5 forloop. Shades of my beloved STL!

The JGA would be another excellent addition to the JDK and an encouragement to a well-proven style of programming common in many programming languages.

Friday, August 11, 2006

Read-only enhanced for loops in Java

I was just commenting on Paul Holser's blog about this small idiom using the Java enhanced for loop:

for (final T t : unmodifiable(collection)) {
    doSomethingWith(t);
}

The plumbing is simple:

public static <T> Iterable<T> unmodifiable(
        final Collection<T> c) {
    return new Iterable<T>() {
        public Iterator<T> iterator() {
            // Presuming a static decorator method
            // akin to Collections.unmodifiableCollection()
            return unmodifiableIterator(c.iterator());
        }
    };
}

Naturally, I wish Sun would add something like this to java.util.Collections, but I am sure they get many, many requests for JDK additions. Adding in a cleaned up Jakarta Collections library would help.

Another example of this sort of thing is a filterable iterator:

for (final T t : filter(collection, filter) {
    // Only works on collection elements
    // accepted by the filter.
    doSomethingWith(t);
}

Anyway, Paul has a lot of interesting ideas in store for Jaggregate 3.0.

UPDATE: An anonymous commenter made the observation that an immutable Iterable is useless in an enhanced for loop. D'oh! I should not have overlooked that point when I used the enhanced for loop in my examples. However, the read-only property is still useful when you call iterator().

Thursday, August 10, 2006

Replace simulated Java lists with Iterable

While cleaning old Java code I ran across this pre-Tiger pattern several times:

class Thingies {
    private final List things = new ArrayList();

    // Other useful fields

    public List getThings() {
        return Collections.unmodifiableList(things);
    }

    public void addThing(final Thing thing) {
        things.add(thing);
    }

    // Other useful methods
}

Essentially the author intended to simulate a sort of List decorated with other, useful information for a business object. Hiding the list internally is a Good Thing and helps abstraction. Using unmodifiableList is great.

But with Tiger and generics, I can do better:

class Thingies implements Iterable<Thing> {
    private final List things = new ArrayList();

    // Other useful fields

    public Iterator<Thing> iterator() {
        return things.iterator();
    }

    public void addThing(final Thing thing) {
        things.add(thing);
    }

    // Other useful methods
}

Now I can use the class with Tiger foreach syntax:

for (final Thing thing : instanceOfThingies) {
    // Do something with thing.
}

This advice is available in many places on the Internet, and is good advice. But did you notice something wrong with the example? What happens with thingies.iterator().remove()? I introduced an abstraction leak.

Let's fix the leak:

public Iterable<Thing> iterator() {
    return new Iterator<Thing>() {
        final Iterator<Thing> it = things.iterator();

        public boolean hasNext() {
            return it.hasNext();
        }

        public Thing next() {
            return it.next();
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    };
}

Now if the caller decides to use thingies.iterator() directly, they still cannot modify the underlying list.

A neat trick

Continuing this theme, I also ran across a neat trick. The old code has a small class hierarchy which the simulated list managed. Typical usage:

class FourWheeler {
}

class Sedan extends FourWheeler {
}

class Pickup extends FourWheeler {
}

// In another class far, far away:
final Iterator sedans = fourWheelers.getList().iterator();
while (sedans.hasNext()) {
    final Sedan sedan = (Sedan) it.next();
}

// In yet another class even more far, far away:
final Iterator pickups = fourWheelers.getList().iterator();
while (pickups.hasNext()) {
    final Pickups pickup = (Pickup) it.next();
}

The thing is, the four wheelers list manager only held one type of four wheeler at a time so the caller was safe in casting as long as they were careful in updating the list. But this is very wordy. One approach is to generify the list manager:

class FourWheelers<T extends FourWheeler> {
    private final List<T> list = new ArrayList<T>();

    // Rest of class uses T instead of FourWheeler.
}

This is a great approach to the problem for new code. But there is a smaller change one can make to the class that also works. Add a new method:

public Iterable<Sedan> sedans() {
    return new Iterable<Sedan>() {
        public Iterator<Sedan> iterator() {
            final Iterator it = list.iterator();

            public boolean hasNext() {
                return it.hasNext();
            }

            @SuppressWarnings({"unchecked"})
            public Sedan next() {
                return (Sedan) it.next();
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    };
}

And likewise for Pickup. You can abstract this common pattern to a base class and simplify the methods further:

public Iterable<Sedan> sedans() {
    return new FourWheelerIterable<Sedan>(list.iterator());
}

Usage is now like this with all the nasty casting hidden away:

// Back in a far, far away class.
for (final Sedan sedan : fourWheelers.sedans()) {
    // Do something with sedan.
}

UPDATE: Jörg has a great observation in the comments: you may need more than one kind of generic Iterable<T> for a complex class.

Wednesday, August 09, 2006

Crossing generics and covariant returns

Quick: why doesn't this compile?

fred.setFoo(new Foo());

Ok, some context:

class Bob<Foo extends Foo> {
    private Foo foo;

    public void setFoo(final Foo foo) {
        this.foo = foo;
    }
}

class Fred extends Bob<Bar> {
}

See it now? How about now:

class Foo {
}

class Bar extends Foo {
}

class Bob<NOTFOO extends Foo> {
    private NOTFOO foo;

    public void setFoo(final NOTFOO foo) {
        this.foo = foo;
    }
}

class Fred extends Bob<Bar> {
}

Yes, it was a mean trick to name a generic parameter the same as the class it extends. Sensibly, SUN's javac complains "illegal forward reference". I had to reread several times the code this example came from before it finally clicked what had happened.

But enough; on to the meat of the post.

I was cleaning some code and noticed this mini-anti-pattern in many places:

class Bob {
    private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(final Foo foo) {
        this.foo = foo;
    }
}

class Fred extends Bob {
}

class SomewhereElse {
    public void doWork(final Fred fred) {
        final Bar bar = (Bar) fred.getFoo();
    }
}

This style is quite commmon in pre-generics Java where there are parallel inheritance hierarchies: Foo goes with Bob, Bar goes with Fred, et al, and all the common code is pushed down into the lowest base class. All that casting makes my eyes sore.

But using generics, I get the advantages of covariant returns without needing any extra coding:

class Bob<F extends Foo> {
    private F foo;

    public F getFoo() {
        return foo;
    }

    public void setFoo(final F foo) {
        this.foo = foo;
    }
}

class Fred extends Bob<Bar> {
}

Now the syntax error I first posed is a real time-saver: instead of getting a ClassCastException at runtime, I get a compile error when trying:

fred.setFoo(new Foo());

The correct call is now:

fred.setFoo(new Bar());

What are covariant returns? To get generic code like this to work right, Java picked up covariant returns for free:

class abstract NumberPicker {
    public abstract Number pickANumber();
}

class IntegerPicker extends Base {
    public Integer pickANumber() {
        return 42;
    }
}

Because an Integer is a Number, Java recognizes that declaring IntegerPicker to return an Integer for pickANumber() satisfies the contract for NumberPicker: covariant returns. Generics uses the same trick in the compile when narrowing the return type for getFoo() in the first examples, or something near enough.

You can read more on this and other goodies in Angelika Langer's Java Generics FAQs.

Tuesday, August 08, 2006

SQL and XML and JDBC4 and you

I missed it when he first posted: Lance Anderson (lead for JDBC4) has an excellent post with short recipes on using XML and SQL with JDBC4, JDBC 4.0 SQLXML Interface. Just the sort of thing when one is poking around for an easy way to use the new XML features of JDBC4.

Friday, August 04, 2006

A refinement on constructor tidiness

Last year I wrote a post about using generics to improve constructor argument checking, Let generics make your Java constructor cleaner. Since then I have refined the example method, asNotNull.

The original:

public static <T> T asNotNull(final T input) {
    if (input == null)
        throw new NullPointerException();

    return parameter;
}

And updated:

public static <T> T asNotNull(
        final T input, final String message) {
    if (null == input)
        throw new IllegalArgumentException(message);

    return input;
}

There are two differences:

  1. I throw IllegalArgumentException instead of NullPointerException. In addition to this being arguably more correct for the semantics of those two exceptions, it is also more useful as I will know that any NullPointerException is because of a call on a null object.
  2. I use a message for the thrown exception—usually of the form "Missing variableName"—to aid in fixing the problem from the stack trace output.

Another reason for the changes are consistency. I make use of other "contract"-based methods such as asNotEmpty, etc., who all throw IllegalArgumentException with an explanatory message. The consistency makes it easier for other programmers to take up the methods into their own code.