The Source for Java Technology Collaboration
User: Password:



Tim Boudreau's Blog

Community: JavaDesktop Archives


The Capability Pattern - Future-Proof Your APIs

Posted by timboudreau on August 11, 2008 at 01:00 AM | Permalink | Comments (19)

Here is a simple pattern which you can use to make your APIs extensible, even by third parties, without sacrificing your ability to keep backward compatibility.

It is very frequent to create a library which has two “sides” — an API side and an SPI side. The API is what applications call to use the library. The SPI (Service Provider Interface) is how functionality — for example, access to different kinds of resources, is provided.

One example of this is JavaMail: To read/write email messages, you call JavaMail's API. Under the hood, when you ask for a mail store for, say, an IMAP mail server, the JavaMail library looks up all the providers registered (injected) on the classpath, and tries to find one that supports that protocol. The protocol handler is written to JavaMail's SPI. If it finds one, then you can fetch messages from IMAP servers using it. But your client code only ever calls the JavaMail API - it doesn't need to know anything about the IMAP service provider under the hood.

apispi.png

There is one very big problem with the way this is usually done: API classes really ought to be final in almost all cases. SPI classes ought to be abstract classes unless the problem domain is extremely well-defined, in which case interfaces make sense (you can use either, but in a not-well-defined problem domain you may end up, over time, creating things with awful names like LayoutManager2).

I won't go into great detail about why this is true here (my friend Jarda does in his new book and we discuss it somewhat in our book Rich Client Programming). In abbreviated form, the reasons are:

  1. You can provably backward compatibly add methods to a final class. And if the class is final, that fact has communication-value — it communicates to the user of that class that it's not something they might need to implement, where an interface would be more confusing.
  2. You can backward compatibly remove methods from an SPI interface or abstract class, if your library is the only thing that will ever call the SPI directly is your library. Older implementations will still have the method, it just will never be called (in a modular environment such as the NetBeans module system, OSGi or presumably JSR-277, you would enforce this by putting the API and SPI in separate JAR files, so a client can't even see the SPI classes).
A minor benefit of using abstract classes is that you can semi-compatibly add non-abstract methods to an abstract class later. But do remember that you run the risk that someone will have a subclass with the same method name and arguments and an incompatible return-type (the JDK actually did this to us once in NetBeans, by adding Exception.getCause() in JDK 1.3). So adding methods to a public, non-final class in an API is a backward-incompatible change.

Given those constraints, what happens if you mix API and SPI in the same class (which is what JavaMail and most Java standards do)? Well, you can't add methods compatibly because that could break subclasses. And you can't remove them compatibly, because clients could be calling them. You're stuck. You can't compatibly add or remove anything from the existing classes.

As I've written elsewhere, it is the height of insanity that an application server vendor is supposed to implement interfaces and classes that its clients directly call — for exactly this reason. It would be much cleaner, and allow Java APIs to evolve much faster, if API and SPI were completely separated.

But part of the appeal to vendors, for better or worse, to implement these specifications, is that they can extend them in custom ways that will tie developers who use those extensions to their particular implementation. This behavior not entirely about being evil and locking people in. There is a genuine case for innovation on top of a standard - that's how standards evolve, and some people will need functionality that the standard doesn't yet support.

Enter the capability pattern. The capability pattern is very, very simple. It looks like this:

public <T> getCapability (Class<T> type);
      
That's it! It's incredibly simple! It has one caveat: Any call to getCapability() must be followed by a null-check. But this is much cleaner than either catching UnsupportedOperationExceptions, or if (foo.isAbleToDoX()) foo.doX() or if (foo instanceof DoerOfX) ((DoerOfX) foo).doX(). A null-check is nice and simple and clean by comparison. It's letting the Java type system work for you instead of getting into a wrestling match with it.

Now, what can you do with it? Here's an example. In my previous blog I introduced an alternative design for how you could do something like SwingWorker. It contains a class called TaskStatus, which abstracts the task status data from the task-performing object itself. It is a simple interface with setters that allow a background thread to inform another object (presumably a UI) about the progress of a task.

In light of what we just discussed, TaskStatus really ought to be a final class. So let's rewrite it a little, to look like this. We will use a mirror-class for the SPI.

public final class TaskStatus {
    private final StatusImpl impl;
    TaskStatus (StatusImpl impl) {
        this.impl = impl;
    }

    public void setTitle (String title) {
        impl.setTitle (title);
    }

    public void setProgress (String msg, long progress, long min, long max) {
        //We could do argument sanity checks here and make life
        //simpler for anyone implementing StatusImpl
        impl.setProgress (msg, progress, min, max);
    }

    public void setProgress (String msg) {
        //...you get the idea
        //...
}

public abstract class StatusImpl {
    public abstract void setTitle (String title);
    public abstract void setProgress (String msg, long progress, long min, long max);
    public abstract void setProgress (String msg); //indeterminate mode
    public abstract void done();
    public abstract void failed (Exception e);
}
      

So we have an API that handles basic status display. But people are going to invent new aspects to status display. We can't save the world and solve everybody's task-status problems before they even think of them - and we shouldn't try. We don't want to set things up so that it's up to us to implement everything the world will ever want. Luckily, it doesn't have to be that way.

Since we've designed our API so that it can be compatibly added to, we let the rest of the world come up with things they need for displaying task status, and the ones that a lot of people need can be added to our API in the future. The capability pattern lets us do that. We add two methods to our API and SPI classes:

public abstract class StatusImpl {
    //...
    public <T> T getCapability (Class<T> type);
}
public final class TaskStatus {
    //...
    public <T> T getCapability (Class<T> type) {
        return impl.getCapability (type);
    }
}
    

Let's put that to practical use. Someone might want to display how much time remains before the task is done. Our API doesn't handle that. Through the capability pattern, we can add that. We (or anyone implementing StatusImpl) can create the following interface:

public interface StatusTime {
    public void setTimeRemaining (long milliseconds);
}
      
A task that wants to provide this information to the UI, if the UI supports it, simply does this:
public T runInBackground (TaskStatus status) {
   StatusTime time = status.getCapability (StatusTime.class);
   for (...) {
      //do some slow work...
      if (time != null) {
          long remaining = //estimate the time remaining
          time.setTimeRemaining (remaining);
      }
   }
}
      

Even better, our Task API is, right now, not tied specifically to Swing or AWT - it could be used for anything that needs to follow the pattern of computing something on a background thread and then doing work on another one. Why not keep it un-tied to UI toolkits? All we have to do is make the code that actually handles the threading pluggable (I'll talk about how you do this simply using the Java classpath for dependency injection in my next blog). Then the result could be used with SWT or Thinlet as well, or even in a server-side application. Instead of a SwingWorker, we have an AnythingWorker!

But we know we need a UI - and we know we are targetting Swing right now. How can we really keep this code completely un-tied from UI code and still have it be useful?

The capability pattern comes to our rescue again - very very simply. An actual application using this UI simply fetches the default factory for StatusImpls (you need such a thing if you want to run multiple simultaneous background tasks and show status for each — my next blog will explain how this can be injected just by putting a JAR on the classpath) and does something like:

Component statusUi = theFactory.getCapability (Component.class);
if (statusUi != null) {
    statusBar.add (statusUi);
}
      
(or if we want to allow only one background task at a time, we can forget the factory and put the Component fetching code directly in our implementation of StatusImpl).

If you are familiar with NetBeans Lookup API, the capability pattern is really a simplification of that (minus collection-based results and listening for changes).

The point here is that the capability pattern lets you have an API that is composed completely of nice, future-proofed, evolvable, final classes, but the API is extensible even though it is final. The result is that the API can evolve faster, with fewer worries about breaking anybody's existing code. Which reduces the cycle time to improve existing libraries, and all our software evolves and improves faster, which is good for everyone.

It also helps one to avoid trying to “save the world” — by allowing for extensibility, it is possible to create an API that is useful without needing to handle every possible thing anyone might ever want to do in that problem domain. Trying to save the world is what leads to scope-creep and never-finished projects. In this tutorial I discuss the don't try to save the world principle in a practical example.

Does the mirror-class design seem a bit masochistic? I think it does point up a weakness in the scoping rules of the Java language. It would definitely be nicer to be able to, on the method level, make some methods visible to some kinds of clients, and other methods visible to other kinds of clients. But regardless of this, it's even more masochistic to end up “painted into a corner,”[1] and unable to fix bugs or add features without potentially breaking somebody's code. That's how you end up with ten-year-old unfixed bugs.

[1]painted into a corner &mdash An English idiom meaning to leave yourself with no options — you were painting the floor of a room in a pattern such that you end up standing in an unpainted corner of the room, and you can't leave the corner until the paint dries.



Where's the state?

Posted by timboudreau on August 07, 2008 at 01:04 PM | Permalink | Comments (14)

Where's the state? This is a small but useful question when deciding how a problem domain gets carved up into objects: What things have state? What things have values that can change? When and how can they change? Can the changes be observed? Who needs to observe changes in state?

These questions make a good start for figuring out how to carve up a problem domain into objects, if you observe the principle keep all related state in one place. I would go so far as to say that the majority of the appeal of Model-View-Controller (MVC) architecture is that it encourages you to keep state in one place.

One big reason why statefulness matters is threading. In practice, it is common to see designs where threading was an afterthought. This is to be expected. Concurrency is a not natural way for human beings to think. So commonly a library is designed with no thought about threading; then a problem shows up which multi-threading can solve. Threading ends up being introduced into a codebase that was never designed for it. Retrofitting a threading model on something designed without one is very painful and sometimes impossible.

Some threading models can be simple. For example, any time you are writing a Swing application, and you have a method that can do long running I/O, the first line of that method should be

assert !EventQueue.isDispatchThread();
under all circumstances.

But keeping I/O off the event thread is the trivial case. Managing mutations to a model inside an application is a more complicated, less obvious problem.

IMG_2949.png

Any time you find yourself writing a setter (or more generally, mutator) method, it is worth asking yourself Who does this piece of state really belong to? Am I putting state in the right place? Blindly following the beans pattern (add a getter/setter to whatever type you happen to be editing) can result in state being distributed all over objects in an application. The result will be harder to maintain, and if it has any lifespan, less and less maintainable over time. Like entropy, or the no broken windows theory, the more state is distributed all over the place, the more that will masquerade as design and make it okay for a programmer to further diffuse state throughout objects in the application. Human beings can only hold so many things in their minds at a time. The more state is diffused, the more things someone must pay attention to simultaneously to solve a problem in that code.

Another question above was Who needs to observe changes in state? There are some corollaries: Where should those changes be published? and Does the thing observing the change need a reference to the thing that changed?

Let's return to the concept of having a model for a minute. A model gets all related state in one place quite well. It does nothing for threading issues — these still have to be handled somehow within the model, or appropriate use of the model in a multi-threaded environment must be documented. There is a thing you can do at this juncture that can make life much easier — and it is all about how the code that uses the model is designed. If you're creating an API, there is probably more to it than just a data model. There is also how the model is accessed.

Essentially what you can do is this: If you design the rest of your API so that the only way to get a reference to the model is to be passed one (i.e. “don't call us, we'll call you”), then you know the context (particularly, on what thread, while holding which locks) in which your code is going to be called.

I'll pick a class at random as a case in point: SwingWorker. While useful, it does represent poor design in a couple of ways:

  • It mixes the concerns of task state (progress, title) and performing a task and the outcome of that task in a single class.
  • It uses the beans pattern in something that is obviously not a JavaBean.

saltlake.png

I mentioned mixing concerns: Avoiding mixing concerns is not just an academic issue of idealized architectural purity. APIs are things human beings use. If you avoid mixing concerns in a public class, you can name things more clearly, and the result will be easier to understand and need less documentation (which most people won't read unless they have to anyway).

In a perfect world, a thing representing a task should probably be stateless (subclasses can have state if that makes sense for them - but no setters or getters or mutable state in the interface/superclass). If the code that does the work is passed a reference to a model object it can set task state on, that untangles the task-state concern from it.

It also removes a bit of psychological weirdness: Someone who is writing a SwingWorker subclass being is required to think to themselves “Now I have to tell myself what my state is.” I suspect many developers anthropomorphize classes they are writing — they think of the class they are editing, or the program counter, in the first person, as I, myself. I don't have empirical evidence for this, but I know I do it, and I have heard many other developers who were discussing code do it - if there's someone out there who emphatically does not do anything of this sort, I'd be interested to know about your thinking style when coding - please speak up.

Detangling the other concern is as simple as returning a java.util.concurrent.Future from the method that enqueues a task. The result would look something like this:

public interface Task<T> {
    public T runInBackground (TaskStatus status);
    public void runInForeground (TaskStatus status, T backgroundResult);
}

public interface TaskStatus {
    public void setTitle (String title);
    public void setProgress (String msg, long progress, long min, long max);
    public void setProgress (String msg); //indeterminate mode
    public void done();
    public void failed (Exception e);
}
        

and then perhaps you would have a concrete TaskRunner class that runs tasks

public final class TaskRunner {
    public <T> java.util.concurrent.Future<T> launch (Task<T> task, TaskStatus statusUI) { ... }
}
        

or, perhaps preferably, Task is an abstract class with a static launch(Task) method (or instance method - this is a matter of taste) and the TaskRunner class is an implementation detail. (Further refinements would be to look up an injected implementation of TaskRunner, and/or a factory for TaskStatuses on the classpath, etc., not to mention making TaskStatus a final class that delegates, but that's getting out of scope...)

What's the difference between this and SwingWorker? First, we've detangled all of the concerns and made them explicit. While sometimes wadding up a bunch of related concerns may seem like it's doing someone a favor, consider that you really need to read the documentation to figure out what a SwingWorker does. While the above design is simpler, you could probably figure out how to use the above API without reading a line of documentation and get it right.

More importantly, by passing in a TaskStatus instance, we've encouraged healthy client code — no code can get a reference to the passed TaskStatus until the Task is actually being run, and no code can get a reference to the passed TaskStatus unless the client actually wants it to. Contrast this with SwingWorker, which (!!!) allows foreign code to call firePropertyChange() and which can set its status to "done" or "started" inside its constructor! We haven't guaranteed correct behavior (a client could pass a reference to a TaskStatus to some object that will try to do something evil with it on another thread, although implementations could defend against this). But we have strongly encouraged proper usage by designing in such a way that the TaskStatus is only made available within the scope where it is actually used. In addition, since we're the one passing in the reference to the TaskStatus instance, we can much more safely assume what thread will call the TaskStatus instance, and what locks are held when it does. While deadlocks will surely still be possible, we're doing as much as possible to discourage them on our side.

One of our questions above was Does the thing observing the change need a reference to the thing that changed? In this case, absolutely not. In fact, to make the Task object available could only do harm. There is no reason for Task's run*() methods to be exposed to code that are interested in the status of a Task, not the Task itself. It causes harm not only because status-reporting code could potentially invoke run*() methods, but because, to the programmer who is interested in the status of a Task, the run* methods are simply noise. Most developers learn APIs through code-completion in their IDE; mixing concerns just makes it harder to figure out what is and is not relevant.

You'll notice that we've completely removed use of the listener pattern here. The listener pattern is seriously overrated, but is often used by default because developers have seen it in the Java core libraries — we use what we know. The listener pattern has a number of problems. If you've ever had to debug a Swing application where you have a severe bug that only occurs after you switch Windows from Classic to XP appearance or vice versa, then you know this pain — I know I do. What is happening is:

  • Before the look and feel change, the look and feel's listeners on components get called before the application's listeners
  • After the change they get called after the application's listeners
Some code is unknowingly depending on a side effect of the look and feel's reaction to a change — in particular, it is depending on that side effect to happen before the application's listener is called, and exceptions get thrown. While rare, the listener pattern is prone to ordering bugs which are quite painful to reproduce and fix. Additionally, in my experience, listeners are the most potent source of memory leaks in Swing applications. So it is a pattern to avoid unless you know you really need it.

Especially when you have a situation where it is very unlikely ever to have more than one listener, the listener pattern is probably not a good choice. Listeners monitor changes in state. It is not good design to assume that multiple things will want to monitor the status of a Task without any evidence to back up that assumption If needed, it is easy enough to provide a ProxyTaskStatus (and note here the "listeners" are provided as a constructor argument - any ordering issues are those of the caller)

public final class ProxyTaskStatus {
    private final TaskStatus[] statii;
    ProxyTaskStatus (TaskStatus... statii) {
        this.statii = statii;
    }
    public void setTitle (String title) {
        for (TaskStatus status : statii) { 
            status.setTitle (title); 
        }
    }
    //...
}
        

if that's really a need; or leave that up to someone implementing TaskStatus (it can always be added to the API later if there are sufficient use-cases).

What we have, instead of the listener pattern, is a situation where we're passing in the model object (in this case, the thing that holds state about status), as opposed to having the state belong to the task itself and having other code listen for changes in the state. Most likely that model object writes directly to a UI showing task progress. I believe I've read of this pattern being called don't call us, we'll call you somewhere (if anyone can point me to where I ran across that usage, let me know so I can give credit where it's due).

To get back to threading for a minute: There are three ways I typically see threading + statefulness dealt with in code:

  • Close your eyes and pray — i.e. do nothing with regards to threading and hope there is never a problem (or better, document that the code is intended to be single-threaded and the caller needs to enforce correct threading behavior because you don't)
  • Synchronize everything — make deadlocks (you hope) somebody else's problem — you pay a price with synchronization — even if not so much with performance, with maintainability
  • Enforce an actual threading model

This last item brings me to my main point here: The combination of keep all related state in one place plus don't call us, we'll call you creates the possibility of encouraging and even actually enforcing a threading model over a complex data model, without (generally) having to document lots of rules about threading and pray that people obey them. A weakly enforced example of this from the JDK is Document.render(), where you pass a Runnable that is guaranteed to block any other threads writes until the Runnable has exited (it is weakly enforced because you can read the document's content outside of this method — and there is much code out there that does so).

snail.png

Lastly, for anybody about to scream that I have misrepresented SwingWorker here (it has lots of complexity about batching up interim results and so forth, and the above is a simplification), I'll mention that

  1. I don't mean to ding the authors of it - they were being consistent with the library they were working in. Nonetheless, one could do all of those things with the above general design, and have a much simpler, easier-to-use result.
  2. I could have chosen many APIs to pick on here. I work for Sun. It seems more polite to call your own baby ugly than call someone else's baby ugly :-)
  3. Patterns are easier to abstract than anti-patterns. Anti-patterns tend only to become really visible after code containing them has been in production for a while. There's lots of things we know now about what not to do that simply weren't known a decade ago.



API Blogs

Posted by timboudreau on August 05, 2008 at 11:38 AM | Permalink | Comments (13)

One thing which I think about often is the design of code, software libraries and APIs. I've been working on deriving some principles from the things I do intuitively based on experience. Whether those are useful to anyone else is an open question. Peer review is the best tool for figuring out if these really make sense or not, so I'd appreciate feedback on my next few blogs - hopefully one day they can make up some articles or a book or similar.

Whether the results are of value is not for me to judge. If, at worst, what comes out of this is a healthy debate and identifying some things that are not good ideas, that has value too.

Why is a subject like API-usability interesting? Well, the history of software is a history of libraries. Libraries have APIs. An operating system is a set of libraries. The Apache web server is a set of libraries. The Java platform is a set of libraries. The set of things people simply take for granted when they write code are things provided by libraries. If you're writing code, you're usually creating an API whether you know it or not. Better API design skills on average means more software that people can use and rely on faster.

There are plenty of prescriptive books on coding - Effective Java is one of the best, and I recently reread it. I do hope some prescriptions can come out of this writing; what I miss in prescriptive books is the sort of “Here's how to think about such and such a problem in order to arrive at a good solution” advice that helps one to know when one has encountered the illness the prescription cures.

A good little computer scientist is very tempted to avoid anything that isn't more-or-less mathematically provable, or at least demonstrable from statistical evidence.

But objects are a convenience for human beings! There is a psychology of how you carve a problem up into objects, how you name things, and so forth. Some ways will be easier to use for the majority of people than others. Yet, at the same time, design is a matter of balancing sometimes fuzzy principles of code ease-of-use with the requirement that the result ask only a sane amount of work from the computer, and sometimes you still have to let the computer win.

Take, for example, the argument against mixing concerns in a single class. There are excellent arguments from the perspective of architectural purism, and from the perspective of code reuse, for why mixing concerns is a bad idea. What I seldom see articulated is the simple notion that if you mix concerns, people will have a harder time understanding how to use what you create. You can't write a proof for that - and there will be cases where mixing concerns actually is the optimal solution. Those are the dark waters I would like to venture into.

 

There is much fascinating research to be done in the area of api-usability. To be done properly, that should involve not only programmers and usability experts, but cognitive psychologists. It would be wonderful to have such research, and would also take years to do, and I suspect cognitive psychologists have their hands full with problems more interesting to them than how to design an API.

In the absence of such research, perhaps some thoughts from one humble programmer will stir up some wisdom.

 

The problem with writing this sort of thing is that often you cannot write about single patterns or principles in isolation - the point is how a number of patterns interact. This inevitably makes the subject complex. For example, this first of these, which I will post shortly, touches on

  • Statefulness and Model Driven Architecture
  • The Don't Call Us, We'll Call You principle
  • The listener pattern being more harmful than good, and
  • Threading models.
Discussing each of these in isolation might be interesting, but it wouldn't provide the “here's a useful way to think about this class of problems” aspect — and that's the thing I really feel is missing from most design prescriptions - prescriptions are the “what”. The “when”, “how” and “why” are at least as interesting as the prescription itself.

Hopefully your feedback, flames and/or howls of protest will help sort the relevant from the irrelevant. Don't be sparing - if I don't post at least one thing that is approaches dead-wrong, I'm not thinking hard enough.

library1.png
Stern warning in the University of the Philippines Computer Science Building


Egads! An actual Swing Tree-Table!

Posted by timboudreau on June 03, 2008 at 03:36 AM | Permalink | Comments (22)

Four years ago, I went on a hunt for best practices for doing tree table components in Swing. We had a tree-table component in NetBeans, whose maintenance was my never-ending nightmare and the biggest source of bugs on my bug list. It had been written, with the best of intentions, based on Scott Violet's Swing Connection article about how to quickly hack up a tree-table component in Swing (Scott's article was also written with the best of intentions, and I have no intention to ding him here - what he wrote does work for simple use-cases - a debugger is not a simple use-case).

When I canvassed folks who had done Swing tree-tables on our mailing lists, most of them were based on that article, as ours was. What I heard back varied between groans of pain and mad rabid howls of pain. There are a few things in that original tree table design that just don't work - not reliably, anyway. Sending events to an offscreen component as if it were on-screen and expecting it to behave sanely is just a really bad idea that happens to work if the look and feel is a subclass of BasicLookAndFeel, and other look and feel implementations have been tormented into supporting this abuse by all the evil Tree-Table implementations in the wild. But the bottom line is, a look-and-feel author would have to be slightly insane to code their TreeUI to behave as if it were a live component when it has no parent and obviously is not one. In other words, the fact that the JTree-as-cell-renderer design works at all is just an accident of how BasicLookAndFeel's TreeUI implementation was designed, which other look and feels inherited. Never mind trying to use said JTree as a cell renderer in a table (I once made a 400% performance improvement in our tired, tortured, hacked-up TreeTable just by having it translate the graphics context instead of repositioning - and thus causing a re-layout) is seriously abusing the component. Now try convincing said offscreen JTree that it has keyboard focus in order to get it to paint appropriately in its role as a cell renderer for another component. On all look and feels. On all platforms. Everywhere.

You see what I mean.

After doing that canvassing back in '04, it was obvious that Swing needed a real tree-table component. So I started to write one (and the layout cache classes JTree uses were very, very helpful - thanks, Scott!).

I started on it, got the basics working, and then moved back to the U.S., changed jobs and ended up travelling the world full-time teaching other people to write NetBeans modules - but it didn't leave time to finish up the Tree Table work. Thankfully, my former office-mate, David Strupl, picked up where I left off when he left Sun to work on Nokia's NetBeans RCP app for managing cellular telephone networks.

The really, really great news is: This week, Standa Aubrecht - who took over a bunch of the stuff when I left full-time development of NetBeans in '04 and amazed me with how quickly he was able to get going in a complex codebase - committed it into the main line of NetBeans sources yesterday. So anybody who gets a dev build of NetBeans as of today has a perfectly working Swing Tree Table component they can use (the class name is Outline - I borrowed the name from Apple's Cocoa library - it's a little less clunky than "tree table" but gets the point across). The JAR file is org.netbeans.swing.outline.jar. Usage is incredibly easy - you just provide a standard Swing TreeModel of whatever sort you like, and an additional RowModel that can be queried for the other columns contents, editability and so forth. And you never have to worry about cells painted half one color and half another because the tree-cell part got repainted after focus went to a popup menu. It actually works!

The real credit here goes to David and Standa for getting this thing production-worthy - I just was pissed-off enough at having a gargantuan list of unfixable bugs (well, fix it on one platform, break it on another, or leave it unfixed everywhere, or semi-fixed some places - pure evil if you hold the illusion that what we do is computer science) four years ago to get the ball rolling. They're the guys who delivered it.

I'm incredibly happy to see this finally be real and available not just to people writing NetBeans modules, but anybody doing GUI apps in Java. There has been a need for a real, reliable tree table component for Swing programmers for a long, long, long time. All hail David and Standa!

What if we built Java code with...Java?

Posted by timboudreau on January 30, 2008 at 01:36 PM | Permalink | Comments (23)

My friend Jon had an interesting insight: Both Ant and Maven rely on lots of XML. XML is good for describing data and terrible for describing behavior. A build is mostly behavior. What if, instead of tormenting Ant into iterating on a bunch of subprojects of subprojects, if we just used an actual programming language to write build scripts. Like, oh, say...Java, for instance?

So he created the Gosling project. It's pretty embryonic - and I think some of the file and resource classes could be replaced by straight usage of things like javax.tools.FileObject, but it has a nice simplicity. Here's the constructor for Gosling's own build to build itself. It has a similar feel to what Jon did in designing Wicket's APIs:

    public GoslingProject() {
        final Folder root = new Folder("/Projects/gosling/workspace/gosling");
        final Folder source = root.folder("src");
        final Folder lib = root.folder("lib");
        final Folder target = root.folder("target");
        add(new JavaApplicationBuilder() {
            @Override
            protected Set getDependencies() {
                final ResourceDescriptorSet dependencies = new ResourceDescriptorSet();
                dependencies.add(Apache.apache.wicket.core.development.resources());
                dependencies.add(Apache.apache.wicket.extensions.development.resources());
                return dependencies;
            }

            @Override
            protected Set getJars() {
                return lib.nestedJars();
            }

            @Override
            protected Folder getSourceFolder() {
                return source;
            }

            @Override
            protected Folder getTargetFolder() {
                return target;
            }
        });
}
Brazilian Salt Shakers I spent last night wrestling with writing an Ant script to build, test and build Javadoc for an ad-hoc collection of projects, where a bunch of custom information needs to be gathered from the projects and embedded elsewhere, and I just found myself thinking this is so not the way to build software!.

I mean, the appeal of things like Ant is that many things are built in a pretty similar way; Maven is even more "my way or the highway" in that regard. I use (and sometimes like) both of them. And in theory an Ant XML script (xml script - now there's an oxymoron) is human readable - although I challenge anyone to make heads or tails of this in ten minutes. It certainly beats Make and tab vs. space madness. There's an argument that it's toolable - that a tool can analyze an Ant script. This seems to me to be a red-herring if you do a design like Wicket or Gosling use - where you know that the entire state you need to analyze is going to be set up in the constructor of a known class of a known type. The Javac Tree API may not be for the faint of heart, but analyzing the closure of a constructor is perfectly doable.

My point is that Ant doesn't really deliver the clarity it promised except in the most trivial of cases. You could have at least as much clarity with plain-old Java code - you just need to start from a good design so the code can speak for itself. And a design where all targets will be added to the build in the constructor is pretty darned clear. Isn't one of the things the agile crowd talks about a lot letting code speak for itself?

Not to mention that running javac in-process ought to be blazingly fast. And that such a project could import and call existing Ant tasks to do things with a thin adapter layer - so anybody's custom tasks or missing functionality could be handled leveraging stuff that's already out there.

It seems like a pretty nice idea to me.

Wizard project updates

Posted by timboudreau on September 24, 2006 at 08:33 PM | Permalink | Comments (21)

I spent part of the weekend adding some needed features to the Wizard library on java.net. If you need to do wizard-style UIs in Swing, this library makes it pretty easy to do something slick.

The Wizard library now supports JLF-spec summary panels - so you can easily display a final page which lists what the wizard has done. I also added background completion support with a progress bar and proper threading handling - so if what the wizard will create is slow, you can show progress while it is going.

Something I added some time ago that is fairly useful for speeding up the Wizard creation process is a class called WizardPage - you simply add components to this panel, and set the name of each component; the framework will automatically listen for changes and put whatever the user inputs into the settings map. If you want validation, that is easy to implement as well.

There's also a new Quick Start Guide and a WebStart™ demo (BeanNetter)

sky-panorama-2-smaller.png
Sunrise over Denver airport
(yes it's a real photo - it was quite a sunrise)


A Single-Mouse-Gesture Color Chooser for Swing

Posted by timboudreau on June 05, 2006 at 05:56 PM | Permalink | Comments (1)

Ever needed a faster, slicker way to let your users select a color in Swing? I just set up a new java.net project, which produces just such a widget. Press the mouse and a palette pops up; drag over the palette and release when the color is right; use combinations of ctrl/alt/shift to switch palettes (palettes are pluggable if you want to write your own).

The widget is the Quick Color Chooser - net.dev.java.colorchooser.ColorChooser. It's a simple Swing widget with one property of interest - color - that is incredibly easy to use.

It's actually been sitting around in contrib/ on netbeans.org for a couple of years, and the palette code dates back to 2000 - it's a port of a Delphi component I wrote in the mid nineties. .

So the code is fairly mature and solid - I just split it out into having a separate UI delegate so it's more Swing-like and the painting behavior is overridable, but it's the same logic as before. Feedback appreciated.

If you want to try it using Matisse in NetBeans, there's a NetBeans module that installs the component in the component palette for immediate drag-and-drop use (created using BeanNetter). The module includes the javadoc.

Got JavaBeans? Here's a way to distribute them...

Posted by timboudreau on April 03, 2006 at 11:53 AM | Permalink | Comments (10)

BeanNetter - the NetBeans Module Generator

So NetBeans has this cool component palette from which you can drag and drop components onto Swing componentPalette.png

forms. But where are all the cool components? NetBeans just shows the default JDK Swing components - but there are lots of components out there. Wouldn't it be nicer if you could make them just appear in your IDE? And there are sites such as nbextras.org with NetBeans plug-ins, and there is an update facility built into NetBeans - so why shouldn't you be able to download JavaBeans straight into the IDE from them? Well, first, it needs to be easy to create a NetBeans module that embeds JavaBeans and puts them on the Component Palette.

So I wrote a small tool that generates a NetBeans plugin. It's a wizard, and you point it at a JAR file with some Swing components in it. It finds all the declared JavaBeans that are there, and lets you choose to add or remove other classes. Then it asks for some info like the name of the library - this will be your Beans' category on the Component Palette.

When you complete it, it generates a complete, redistributable NetBeans Module (.nbm file - the distribution format for plug-ins - a glorified zip file), and all of the components you selected will show up on the Component Palette in their own category as soon as you install it in the IDE. Now...how to distribute these glorious plugins?

What to do with the results

Now you've got a module, but the point is to get that module to other people. How to do that? Well, first, if the components are open source, I bet the folks at nbextras.org would happily host them, and that site's been getting a lot of attention lately. If they're commercial, there is the Third Party update center that every release copy of NetBeans checks for plug-ins, and that could be a good place - the partner page would be a good place to start.

Sources and Screen Shots

Sources are in contrib/Beans2nbm/beans2nbm in CVS on NetBeans.org. The tool also happens to showcase one of my (far too many) weekend projects, the Wizard project.

wizardPanel2.png
BeanNetter - the NetBeans Module Generator

wizardLicense.png
Choosing a License - Extra points if you can identify the text above




Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds