Archive for October, 2007

I Hate RSS

I am in the midst of writing a newsreader client that must display content from both RSS and Atom feeds. I am using ROME to parse the feeds, which I then display in my GUI. ROME handles a vast majority of parsing nastiness, I just have to interpret and display whatever ROME gives back to me. Rome provides the least-common-denominator of every possible feed, which leaves a lot of room for ambiguity.

Today I discovered that for some RSS feeds, ROME tells me the content type is “text/plain”. When I dutifully attempt rendering as text/plain, I find the feeds in fact contain HTML markup like hyperlinks. When I test these exact same feeds in tools like Google Reader, I see that they treat them as HTML instead of plain text.

Other RSS feeds report their content type (again, via ROME) as text/html.

I do not know a good way to handle this. I guess I’ll just blindly assume that every RSS feed contains HTML, regardless of what the content type says.

This sucks. If you ever have the opportunity to PRODUCE your own feed, PLEASE consider using Atom. And if your feed contains HTML tags, why on earth would your feed tell everyone it is text/plain?

OS X Java Definitive Timeline

Panic! Panic! No, wait. Let’s learn from history. I spent some time this afternoon putting together this timeline comparing Sun’s Java releases with Apple’s Java releases:

Sun Apple Java Timeline

Focus on the right side of the timeline. It is perfectly clear that Apple releases major JDK updates on, or shortly after, major OS updates. I believe we will see Java SE 6 on Leopard within days or weeks.

Apple is not a slave to Sun’s JDK release schedule, nor should they be. Apple’s own operating system is its core business, and it makes perfect sense for them to schedule major JDK releases to coincide with major operating system upgrades.

Apple’s Advantage

This philosophy (keeping JDK and OS releases in sync) gives Apple a huge advantage because they have far fewer backwards compatibility issues to worry about. Each major JDK release can be optimized to take advantage of the very latest OS X features and optimizations. Windows and Linux JDKs do not have this luxury. When Sun releases new JDKs, they must support a wide variety of Windows and Linux OS releases, including 32 and 64 bit versions. The term “least common denominator” comes to mind, and not in a good way.

Striking a balance between backwards compatibility versus moving to new technology is a classic engineering trade-off. Apple chooses to move away from older technologies at a relatively fast pace, while Sun tends to be more conservative in its support of older operating system versions. Each has its pros and cons, but for now, this is what we are given.

Anyone wanting a faster JDK release cycle on OS X will have to look to someone other than Apple to give it to them.

Comic: Apple’s Pathetic Java Support? Oh Really?

Dear Steve,

Writing your own JDK is really hard. Maybe you should follow Microsoft’s lead and let Sun do the dirty work?

Let Sun do the Dirty Work

Swing EDT and UIManager Initialization Question

We all know you are supposed to only interact with Swing GUI components on the event dispatch thread (EDT). Your main method might look like this:

public static void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      createAndShowGui();
    }
  });
}

But what about the first time you call UIManager.setLookAndFeel(...)? Does this one-time action have to go on the EDT?

Sun’s own examples are inconsistent.

First example:

public static void main(String[] args) {
  //Schedule a job for the event dispatch thread:
  //creating and showing this application’s GUI.
  javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      createAndShowGUI();
    }
  });
}

private static void createAndShowGUI() {
  //Set the look and feel.
  initLookAndFeel();
  …
}

private static void initLookAndFeel() {
  ….
  UIManager.setLookAndFeel(lookAndFeel);
  …
}

So you see, in that example, they are careful to set the look and feel on the EDT.

But here is another example from the same web site:

public static void main(String[] args) {
  try {
    UIManager.setLookAndFeel(”javax.swing.plaf.metal.MetalLookAndFeel”);
  } catch (…) {
    …
  }

  //Schedule a job for the event-dispatching thread:
  //creating and showing this application’s GUI.
  javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      createAndShowGUI();
    }
  });
}

I assume the second example is wrong. I believe you might be able to get away with it, maybe even thousands of times, but perhaps once in awhile you might see some weird threading issue or memory visibility problem. ???

What is the correct answer?

Comic: Wide-Stanced Programming

Enjoy!

Wide Stanced Programming Comic

Suggested reading for those who don’t get it…

Atom Valid on WordPress 2.3

I just upgraded to WordPress 2.3, the whole process took a matter of minutes. According to the W3C Feed Validation Service, my Atom 1.0 feed is now valid. Woohoo!

Apostrophes Finally Work

Valid Atom means characters like & and < will render properly in an increasing number of tools. Thanks to clearly defined text constructs, the meaning of such characters is not ambiguous.

WordPress is but one link in the chain of syndication tools. Using Atom helps ensure sites like JavaBlogs, DZone, and others can consume and syndicate content accurately. As I wrote in early September, I explicitly customized my WordPress installation to disable RSS. I simply do not trust RSS because every person writing an RSS tool might interpret entities differently.

Apostrophe Rant

Now that WordPress Atom feeds appear to handle apostrophes a bit better, what can we do about Greengrocers’ apostrophes? It must be embarrassing to work at companies where the official company name makes this stupid mistake. (Answer: the plural of CD is CDs, not CD’s)

Now I fully expect my faithful readers to point out all of the grammatical and spelling errors in this blog. That should teach me to mock apostrophe abuse.

For a Great Time, Try These IDEA Project Tips

Most of these are IDEA specific, but a few concepts in here translate well to other IDEs, I suppose. A basic IntelliJ IDEA project consists of three files:

  • myproj.ipr - this is the project file
  • myproj.iml - a module file, you might have a bunch of these
  • myproj.iws - a workspace file

Here are a handful of tips for managing these files.

New IDEA, New Format

People generally store their IDEA project and module files in the root directory of their project. Take a look at the Guice trunk directory. See the .iml and .ipr files?

As IDEA evolves from release to release, the project file format changes. So if you use the exact same version of IDEA as the Guice authors, you can use their project file. But if you happen to use an older version of IDEA, you probably won’t be able to use their project file. Or, if you open the files with a new (or beta) version of IDEA, the file might get upgraded to the new format.

I always store my project and module files in version-specific directories:

trunk
 |
 +--idea5
 |      .iml, .ipr files for IDEA 5
 +--idea6
 |      .iml, .ipr files for IDEA 6
 +--idea7
        .iml, .ipr files for IDEA 7

Easy, right? This lets different programmers collaborate on the same project without trampling each other’s project and module files.

Relative Paths

IDEA uses relative or absolute paths in both the project file and the module file(s). Modules default to relative paths, the project file defaults to absolute paths.

If you plan to share your project and module files, be sure to set BOTH the project AND module settings to relative paths. This is particularly critical in the directory structure shown above, because all of the paths need to include “../” due to the idea5, idea6, or idea7 directories.

Relative paths are important because different programmers use different directory structures on their computers. Furthermore, if you use Subversion (or other version control tools), your branches will be checked out to different directories. Having all relative paths in your IDEA project and module files means you can do a fresh checkout to any path and get to work right away.

CRLF Woes

I work on a team where some programmers use Linux, others use Windows. We found if a Linux user changes the project or module in any way, IDEA stores using “\n” line endings. If a Windows user modifies the files, IDEA stores the files using “\r\n”. Sigh. I wish IDEA would just store “\n” always.

To avoid this problem, configure your version control tool (CVS, Subversion, whatever) to always store these files using a particular line ending style. In Subversion, you simply set an attribute called

svn:eol-style

on these files. This avoids bogus diffs if your teammates use different operating systems.

Do Not Share *.iws

The .iws file is a workspace file. This contains programmer-specific preferences. Do not share this with other programmers, and DO NOT check this in to a version control repository. If you do, every programmer who opens the file in IDEA will modify it, and you’ll constantly be updating, merging, and resolving conflicts.

If the .iws file is not found, IDEA silently creates a new one for you, so there is no reason to share .iws files.

Avoid Ant Conflicts

I always configure my Ant buildfiles to produce output in a “build” directory. I configure IDEA to put its output in a different directory. It seems to cause problems when two different build systems compete for the same directory.

Ignores

Be sure to tell IDEA to exclude directories that are unrelated to compilation or runtime settings. If your Ant buildfile drops .class files in a directory independent of IDEA’s build directory, be sure to configure your module to exclude the Ant output directory. Otherwise every time you compile in Ant, IDEA will re-scan all of those Ant build artifacts. You should also exclude things like documentation directories, again for performance reasons.

Source Paths

Put your source code in a ’src’ directory of some sort. Configure that as a source path in IDEA. I’ve seen many programmers list OTHER directories as “source” directories as well. I don’t know why so many people do this, but it is not a good idea. For example, we generally have a resources directory that contains images and properties files that should be added to the CLASSPATH at runtime. The resources directory SHOULD be added to the CLASSPATH, but it SHOULD NOT be added as a “source” directory.

Adding non-source code as a source directory slows things down as IDEA scans those files, copies them to cache folders, etc.

I generally like several parallel source paths. I’ll have at least one for application code, and another for unit test sources. I like keeping XML, .properties, and image files in a separate resources folder.

Many people like to put these collateral files right in there with application source code, which I believe is a mistake. They must then add a source directory to the CLASSPATH (which is weird), or they must rely on Maven or Ant to COPY these collateral files to a build directory during the application build. Yuk, yuk, yuk! Having to copy these files around just leads to problems that are completely avoidable.

Be Careful with Plugins

Unfortunately, some plugins store programmer-specific settings in the .ipr file instead of the .iws file. This means if one programmer installs some plugin and commits the project file to the version control repository, other programmers on the team now see what are essentially bogus diffs (and potential conflicts) in the files.

I simply stopped using one plugin because of this behavior. Just something to look out for.

Here is How You Fix Maps

Gregory Kick left a great comment on my recent entry How Do I Submit a Bug Report for Bad Maps?. Sure enough, NAVTEQ Map Reporter lets you submit updates.

This is the root of the bad data for my house:

NAVTEQ

Their system is really cool. You zoom in on the address in question, then you simply double-click to add a new marker at the correct location. You can then provide all sorts of data explaining your update, such as a bad or missing street name, an incorrect location, or various other problems.

I uploaded this picture as “supporting data”:

This is My House

You can also leave your email address to be notified of progress on the update. They claim they provide updated feeds to the various mapping services up to four times per year.

JScrollPane Blunders: Part 3 (of 3, phew!)

This is the final “blunder” of this series. In Part 1, I showed how wrapping the entire screen in one giant scroll pane is usually a bad idea. Part 2 showed how nested scroll panes leads to double scrolling or unusual resize behavior. Now, we see that adding a scroll pane to a BorderLayout’s NORTH, SOUTH, EAST, or WEST region can be troublesome.

As usual, a visual example shows the problem. Here we have a scroll pane surrounding a JTree. This is placed in BorderLayout.WEST, which often causes problems. The problem is, the border layout allocates an initial width to the WEST and EAST regions based on the contained component’s preferred width. For NORTH and SOUTH, it uses the preferred height.

ScrollPane in West

When you first expand a tree node, the BorderLayout does not adjust its width. Thus, you see a horizontal scrollbar as shown in the middle image above.

Even worse, when you resize the window even a tiny bit, the scroll pane instantly skips to a wider size and the scrollbar vanishes.

Some components work reasonably well inside scroll panes in NORTH, SOUTH, EAST, or WEST, but more often than not you will encounter problems. As your layouts become more complex, the results may seem increasingly unpredictable. I recommend you avoid scroll panes in these regions.

Summary

That’s it for the JScrollPane Blunders series of posts. Just like everything else we programmers do, you’ll probably find some rare cases where you can bend or break these rules. Someone asked this in a comment:

Is there no way in Java to get the effect seen in Mac OS X Finder using the View by Column? It is a series of grids, each representing a deeper level in a hierarchy. Each grid is scrollable, and the group is scrollable when the number of grids is too great to fit on screen.

I think the key here is that inner panels have vertical scroll bars, while the outer panel provides the horizontal scroll bar. Thus, you do not simply nest scroll panes inside each other. The inner scroll panes need a vertical only policy, while the outer scroll pane needs horizontal only. Thus you don’t have inner and outer scroll panes competing for scrolling in the same direction.

Something like this:

Finder

That’s about 15 minutes of hacking, and it still has problems. Most notably, the third list (Cities) seems to be truncated by exactly the width of a vertical scrollbar. I’m sure this can be solved; I’ll leave that as an “exercise for the reader”.

And since I do not own a Mac, I don’t really know how the thing is supposed to work anyway. You might want to check out Bug’s work for a more complete and accurate Java implementation.

How Do I Submit a Bug Report for Bad Maps?

I am in awe of the technology behind today’s mapping applications like Google Maps, Google Earth, and Live Search Maps. At the same time, however, these services painfully echo incorrect coordinates and I feel like I have no way to “correct” the problem.

Here is how Live Search Maps shows my address:

Live Search Maps

And here is Google Maps showing the same address:

Google Maps

Both Wrong

The problem is, both are equally wrong. In fact, as long as I have lived at this house, every single mapping service incorrectly shows my house 1 block away from where it actually is.

The data is also stale, at least 3 1/2 years old, if not older. We need drone planes flying 24×7, constantly updating the images. (although I’m not sure who is going to pay for that)

Bad Seed Data

From what I see, some database — somewhere — has incorrect coordinates for my street address. This seed data is then exported, shared, sold, and resold to all of the mapping companies, that dutifully regurgitate the bogus information. (Sounds an awful lot like news/blogs/etc…)

Let Me Fix It!

It would be great if these services had a way for me to send in “bug reports”, or at least offer some kind of community-based updating system where people could submit data fixes.

  • Who is the owner of the flawed “seed” data?
  • Is there a way for me to contact these people and submit a correction?
  • How long will that take to bubble up through the system, so people finally get accurate directions to my house?