Archive for November, 2007

Technology Foothold 101

I do a lot of new technology investigation and I can tell you that first impressions matter.
Far too often, my first few hours with a product consist of:

Rock Climber
  1. Trying to figure out what to download
  2. Searching for simple examples
  3. Fighting CLASSPATH and JAR file hell
  4. Dealing with obscure “Name not found” types of exceptions

If my first day with a new product is miserable, I’ll probably move on to your competition.

Foothold 101

Here are some tips to make your product easier to approach and learn:

  1. Ease the JAR file pain.
    • Reduce the number of JARs, if possible. Apache ActiveMQ lets you choose between a single big JAR or many small JARs. Having that single JAR is a blessing during early development.
    • Clearly list the requirements for each JAR. If your product ships with 30 JARs, provide a documentation page that tells us which ones we need, and why.
  2. Provide 5-minute tutorials with simple example code. Many projects on The Codehaus have these 5-minute tutorials, and they are a fantastic idea. You can always follow up with more in-depth documentation, but the quick-start Hello World is — and always will be — essential.
  3. Beware overly technical documentation. It is highly likely that new users are not experts in arcane P2P networking terminology. The JXTA project documentation is a really good example of what not to do. I struggled with this for an entire day and just gave up in utter frustration and rage, unable to get much of anything to work.
  4. Your web site needs to be clean and easy to navigate. I am generally lost and confused when I try to navigate java.net projects like SwingLabs. Hell, their own search engine just crashed when I tried searching for “swingx”. I found it (and SwingLabs) through Google.
  5. Make sure your damn demos work.
  6. If your project requires me to compile, then let me type a single command to make it happen. I don’t care if it is Maven or Ant, just make it work. I’m here to learn about your API, not to diagnose a sloppy build.
  7. Framework and API developers should spend a huge amount of effort providing useful error messages. There’s nothing worse than firing up a new product and seeing messages like:
    • Logging is not configured. To see output edit some magical XML file.
    • Name not bound. (Uh…where did you look?)
    • Batch update failed. (gee, I don’t suppose you could tell me a table or column name?)
  8. Provide obvious downloads. If a particular release consists of three ZIP file choices, explain what those choices mean. Which do I want, and why? I generally just download all of them, because I’m afraid I’ll miss something. Check out the download counts for Guice. Notice that pretty much everybody who downloads guice-1.0-src.zip also downloads guice-1.0.zip. I’m not alone! Maybe all but the biggest projects should offer a single ZIP to download?
  9. Make sure your ZIP file extracts to a subdirectory. Don’t you hate it when you unzip some new toy, only to find it just dumped everything into the current directory?
  10. Provide an IDE-friendly ZIP or JAR containing all source code. This way I get proper JavaDoc tooltips and can easily navigate to source. Few things are more annoying that projects that ship with 15 separate parallel source trees, requiring me to spend precious time configuring a complex project.
  11. Screencasts are a great way to get people started.
  12. Concise documentation is often better than verbose documentation. Up-to-date documentation is priceless.

Credit

For the record, I stole the term “Foothold” from Mike.

Crash, Boom: Too Many Open Files…

We’ve been plagued by an error similar to this in some long-running server code:

Boom!

Exception in thread “main” java.io.IOException: Cannot run program “…whatever”: error=24, Too many open files

I am pretty sure I tracked down the problem: failure to correctly close Process resources. Consider the case where you create a Process and read data from its InputStream:

(note: this is not a complete example, plus it is wrong!)

// same thing occurs with Runtime.exec(...)
ProcessBuilder pb = new ProcessBuilder(args);
Process proc = pb.start();
InputStream in = proc.getInputStream();
// ...read from the stream in a thread
proc.waitFor();

// ...later, in a finally block, close the InputStream:
in.close();

That’s the general idea. Create a Process, capture output from one or more of the streams, and close the streams when complete.

Unfortunately, this is wrong.

Poor Documentation

The documentation does not really help much. For instance, here is what the comment says for the Process.destroy() method:

Kills the subprocess. The subprocess represented by this Process object is forcibly terminated.

Hmm…that doesn’t really say how the streams are handled. I’ve always assumed if I used one of the streams, I had to close the one I used.

Here are three bug reports asking for documentation clarification:

After studying these reports, I now feel confident that you must first close all three streams, then you must call destroy() in order to fully reclaim resources.

Example Code

Here is a simple example that shows what I’m talking about. Despite the fact that I do not actually use any of the streams, I still need to close them:

public class ProcDemo {
  public static void main(String[] args) throws
        InterruptedException, IOException {
    Process proc = null;
    try {
      ProcessBuilder pb = new ProcessBuilder(args);
      proc = pb.start();
      proc.waitFor();
    } finally {
      if (proc != null) {
        close(proc.getOutputStream());
        close(proc.getInputStream());
        close(proc.getErrorStream());
        proc.destroy();
      }
    }
  }

  private static void close(Closeable c) {
    if (c != null) {
      try {
        c.close();
      } catch (IOException e) {
        // ignored
      }
    }
  }
}

If you study the code for java.lang.ProcessImpl, you’ll see that when you construct the Process object, all three streams are created right away. Thus, regardless of whether you use a stream, you must close all of them.

And even though the Javadoc for destroy() is not all that clear, from reading the bug reports, it is pretty clear you should call it as well.

Problem Solved?

It will probably be several days before I know if this truly solves our problem. While I was able to clean up all of the code I wrote, I don’t have much control over the various libraries we use. Does JGroups always close Process resources correctly? How about Svnkit? We often see these “Too many open files” errors immediately after a large Subversion checkout, so I am somewhat skeptical.

Static HTML Will Do

I just ran across a really good web site consisting of what appears to be nothing more than static HTML, updated about once per month. As far as I can tell, there is nothing interactive about the site, such as the ability to submit comments. On an About page, they list the following technologies:

Less
  • JSP 1.2
  • JSTL 1.0
  • Java Servlets 2.3
  • Struts 1.1
  • JDBC 3.0
  • MySQL 4.0.13
  • Tomcat 5.0
  • Spring 1.2
  • Hibernate 2.1

Holy balls. I wonder how well that holds up to the Slashdot Digg effect compared to a site based on static files?

More

Tech Overkill

My hunch is that this is just someone’s passion and they used these tools because…well…they wanted to. That’s fine for a personal web site — do what makes you happy.

But I wonder how many “real” apps go to such technology extremes when something as simple as static HTML with perhaps some custom publishing scripts are sufficient, if not better?

RSS for Dummies, Safari Style

Check out my blog on Safari: (made possible by browsershots.org, thanks Alex!)

Safari RSS

See the little blue “RSS” icon? That’s fascinating, because my blog does not have RSS.

Why not use the feed icon like everybody else?

Huge Feed Icon

Calling my Atom feed “RSS” is just plain dumb.

Oops: Phone Not Supported

The comments for Oops, browser not supported are a good read. A few quick highlights include:

  • A reference to Yahoo’s graded browser support. This is great stuff, as explained in my fabulous graph below.
  • A link to Reset Reloaded, something I definitely need to do for my own site. I keep running into margin and padding inconsistencies, for instance when embedding certain tags inside of thought bubble comments.

Now for the Graph

This highly technical graph shows why toolkits and libraries like YUI, GWT, Dojo, and others are inevitable:

GWT Can Help

I test my blog on my PC with two browsers: IE 7 and Firefox 2. I simply do not have the resources (time/money/desire/etc) to test on a variety of browsers and operating systems. But I do worry about it…

  • What does my site look like on cell phones and PDAs?
  • Is accessibility even remotely supported?
  • What about Macs? Linux? Old browsers?

The graph shows a vertical dashed line. There comes a point where you have to support so many browser and device combinations that you simply cannot hand code a sophisticated site.

Old Story, New Rules

We’ve dealt with this issue for years and years and years. What makes it any different today than it was a few years ago?

  • Devices, devices, devices – pretty soon an awful lot of people will be browsing your web site with phones, MP3 players, game consoles, and other gadgets. A world with 2 incompatible browsers is childs play compared to today’s reality.
  • User expectations. You can’t just hand-code some XHTML-strict along with compliant CSS and expect great results. People expect AJAX, animations, WYSIWYG, drag-and-drop, mapping, etc. Good luck hand coding all that.

So there you have it. I hope you enjoyed the graph. I wonder how that 453 pixel wide PNG looks on your cell phone?

The Problem with Emma…

Emma is a code coverage tool with great potential. I (sort of) like it and use it (well, until I got sick and tired of seeing huge numbers of “uncovered” sections that were, in fact, IMPOSSIBLE for me to cover). This comment from Tony makes a great point:

One of the ways that 100% code coverage really helps a project is you quickly pick out those classes that are not tested fully. The difference between 87% coverage and 88% coverage doesn’t show up as much of a difference.

But, the difference betweeen 99% and 100% shows up as a huge difference when you use tools like Clover.

This sounds an awful lot like unit testing. When 100% of your tests normally pass, you immediately recognize failures.

If your team habitually tolerates less than 100% test success, you may will fail to recognize new test failures. Test failures are lost in the noise. Over time, developers learn to expect failing tests, ignore the results, and stop running the test suite.

The best way to avoid test rot? Ensure your build FAILS if a unit test fails.

The Problem with Emma

Achieving 100% test success is easy if you start on day 1 and never let failures work their way into the code. Although this sounds similar to code coverage, it is not.

In fast, it is practically impossible to achieve 100% coverage with Emma. Some branches are impossible to reach, such as private constructors. The same is true for the default case in some switch statements, or some of the generated code in enums.

Thus, when you use Emma, you never get a “green bar”. Instead, you constantly have to wade through false “not covered” indicators to determine if you actually forgot to cover something important.

What Can Be Done?

I believe Emma is off to a great start, but it really needs to be smarter about data flow analysis. Private constructors come to mind first: they should not be reported as “uncovered”.

Secondly, I think it would be really nice we had a database of previous runs. It would be great if we could review the coverage report, and mark sections of code as “I know this is not covered, please stop warning me about this.”

If this tool were really smart, it would recognize when the code changes, and clear these markers for those sections.

Static Import Code Completion

As much as I love Java 5 static imports, I’m finding code completion to be more than a little bit frustrating. This is most annoying when I start writing new code with frameworks that make heavy use of static imports, like JUnit 4.4.

The cycle goes something like this:

  1. Create a new source file
  2. Type Assert., then the IDE recognizes I’m missing an import.
  3. Alt-Enter to add the import statement. NOTE: Hopefully I remember to choose org.junit.Assert instead of junit.framework.Assert. Even as I write this, I’m wondering if I just got that backwards? Confusing as hell.
  4. Now I can use code completion (Ctrl-space) to fill in the assertThat(...) method.
  5. Now hit Alt-Enter to add the static import for Assert.assertThat
  6. Now hit YET ANOTHER keystroke to optimize imports, because the old import org.junit.Assert; is no longer used.

Once you go through this “priming the pump” sequence, code completion with static imports works better. But reaching that point makes my hand hurt and is a new awkward wrinkle to Java programming.

Perhaps other IDEs work better than IDEA at static import code completion? (I’d be very surprised, but who knows…)

What do you think? Surely I’m not the only person to stumble on this.

Improved WordPress Titles

Shout out to Carlos Vella for showing how to change the blog title in WordPress. Here is my new code in header.php:

<title><?php if (is_home()) {
  bloginfo('name');
} else {
  wp_title('');
}?></title>

Ahh…that’s one less piece of clutter in my theme.

100 MPG, 100 MPH: I Want One

Check out this prototype “car”:

Carver

You gotta watch the videos.

Woot Monkey Prize Fraud?

I won the Woot Monkey Prize over a month ago and received absolutely nothing. I sent them my mailing address as instructed.

Confused Ape

What’s up with that? Is the monkey prize real?