RSS feed
<< September 2007 | Home | November 2007 >>

The extra dot in dot-com

Sun no longer claims they "put the dot in dot-com", but did you know there's actually more than one dot in dot-com?

According to RFC1034 "www.example.com" is a relative domain name. The complete domain name (also called absolute) is "www.example.com." (Notice the trailing ".")

Reading this RFC one should think that adding a trailing dot to a domain name should have no effect. All you're doing is to be explicit by using the absolute representation of the domain right?

Not quite so. It doesn't seem like web server vendors and administrators have read this RFC and neither have web browser vendors. This becomes a problem if you're using name based virtual hosting on your web server. When the server gets a request for "www.example.com." it won't have a clue that the user is actually looking for the content at "www.example.com".

So I did a little survey on the web servers I use. The Apache HTTP Server handles the trailing dot perfectly. Tomcat doesn't understand it and serves content from the default host instead. You can mediate this by always adding an alias with the trailing dot, but that's a hack and it's something the server should handle by itself.

I was a little disappointed to find that Jetty (my favorite web server) failed the trailing dot test. But then I remembered how nice the Jetty developers are so a couple of weeks ago I decided to fix the problem and  submit a patch for it. Today Greg applied it. From the next release onwards, Jetty will normalize host names before comparing them. Try reporting something like that to IBM or BEA and you'll find out why Jetty rocks!

Now, just for the fun of it, let's take a look at how some big sites handle requests with trailing dots:

Microsoft: Bad request

Microsoft solves the problem the easy way. Just blame it on the user:



MSN: Page not found

MSN is a little more polite, they even say they're sorry:



Myspace: Redirect to google

I knew Myspace and Google made an advertising deal, but this is just weird:



Facebook: Redirect to www.facebook.facebook.com

Facebook is getting so big they seem to have started a facebook inside the facebook, but there's no response there:

 

NSA: Trust no one, say nothing

One can say a lot about the NSA, but don't give them a trailing dot because they will refuse to talk to you. Period.



Sun: Page not found

Sun may once have "put the dot in dot-com", but that's no longer the case. They're more sorry than MSN though. Sorry with an exclamation point. And what makes them think I own documents at sun.com?

Making your Java app shine on OS X

Making your Java application look and feel like a native OS X application has until recently been one of those things that is hard to get right. There are various solutions floating around, but they tend to force you to build and package the application on a Mac and they often involve some manual steps.

Last week I released the OS X Application Bundle Maven plugin. This plugin solves the packaging part of creating Java applications for OS X. But packaging is just one piece of the Java-on-a-Mac puzzle. You also need to integrate properly with the application menu and with the dock.

As an example, I've created a demo application called TinyNotepad. By default it looks like this on OS X:


There are a few issues with this example that makes it stand out as a non-native application. First, the name of the application is "org.simplericity.macify.Example" which happens to be the name of the main class. Second, Mac OS X has a global menu bar, so we need to move the menu from the window frame to the top of the screen. We can solve both of these issues by using the mentioned Maven plugin:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>osxappbundle-maven-plugin</artifactId>
<version>1.0-alpha-2-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
<configuration>
<mainClass>org.simplericity.macify.Example</mainClass>
<bundleName>tinyNotepad</bundleName>
<vmOptions>-Dcom.apple.macos.useScreenMenuBar=true</vmOptions>
 </configuration>
</execution>
</executions>
</plugin>

Now the name on the application menu is the much nicer "tinyNotepad" and the menu bar has moved to the top of the screen:

Let's take a look inside the menus. The file menu has the normal new, open,  save and exit items.


Additionally, I've added a Preferences item that lets the user configure tinyNotepad:

The "Help" menu only contains the "About" item:

By clicking on the "About" item we get this  dialog:


The application menu is OS X specific. Apple's design guidelines mandates that this menu contains an  "About application". Additionally it may contain a menu item for editing preferences. It always contains the "Quit application" item. Selecing "Quit application" (or using the Command-Q shortcut) will kill our application immediately without asking the user for verification. The application menu of tinyNotepad looks like this:

This about menu item isn't hooked up to our about dialog. Clicking on it gives us this generic dialog:



As you can see, the integration with the application menu isn't quite as good as it should be. So to clean up things we need to:

  • Attach the about menu item to our own about dialog
  • Add a preferences menu item and attach it to our preferences dialog
  • Hook into the "Quit application" menu item and allow our users to verfy that they really want to quit
  • Hide the "about" and "preferences" and "exit" menu items if running on OS X so they don't appear two places.

Apple offers the Apple Java Extensions API that lets us do just this type of integration with the application menu. However, adding that as a compile dependency to our application makes it impossible to build on other platforms without redistributing the Apple API.

That's why I created the Macify Library. This library basically provides the same features as Apple's, it automatically detects if it's running on a Mac and it integrates with the Apple API entirely through reflection.

This means you can  develop and distribute your application without redistributing Apple's API and you don't need to worry about any licensing issues. If your app runs on Windows, it will work fine. If you run it on a Mac it will run just as fine, and as a bonus it will be integrate properly.

So let's do some coding and use the Macify Library to make tinyNotePad shine on OS X. All our integration will be done through the Application interface. There is a default implementation of this called DefaultApplication:

Application application = new DefaultApplication();
MacifyExample example = new MacifyExample();
example.setApplication(application);

In the MacifyExample class we can now use the Application instance to register an ApplicationListener and add the preferences menu item:

application.addApplicationListener(this);
application.addPreferencesMenuItem();
application.setEnabledPreferencesMenu(true);

Then we make MacifyExample implement the ApplicationListener interface and it's methods:

    public void handleAbout(ApplicationEvent event) {
aboutAction.actionPerformed(null);
event.setHandled(true);
}

public void handleOpenApplication(ApplicationEvent event) {
// Ok, we know our application started
// Not much to do about that..
}

public void handleOpenFile(ApplicationEvent event) {
openFileInEditor(new File(event.getFilename()));
}

public void handlePreferences(ApplicationEvent event) {
preferencesAction.actionPerformed(null);
}

public void handlePrintFile(ApplicationEvent event) {
JOptionPane.showMessageDialog(this, "Sorry, printing not implemented");
}

public void handleQuit(ApplicationEvent event) {
exitAction.actionPerformed(null);
}

public void handleReopenApplication(ApplicationEvent event) {
setVisible(true);
}

The final thing to do is to not add the About and Preferences menu items if we're running on OS X since they are already in place in the application menu.

if( !application.isMac()) {
file.add(preferencesAction);
file.add(exitAction);
help.add(aboutAction);
}

That's all there is to it. We have now made tinyNotepad really shine on the Mac OS X platform.

A bonus feature..

If you're an Apple Mail user, you've probably noticed how the Mail icon updates in the dock and the appcation switcher when you have new, unread mail, like this:


This feature is fully supported in the Macify library. The setApplicationIconImage method updates the dock icon while getApplicationIconImage returns the current icon.

Let's add a method to our example that updates the icon with a red circle containing the number of files that have been opened. The method looks like this:

private void incrementIcon(int num) {
BufferedImage newIcon = new BufferedImage(originalIcon.getWidth(), originalIcon.getHeight(), BufferedImage.TYPE_INT_ARGB);

Graphics2D graphics = (Graphics2D) newIcon.getGraphics();

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.decode("#E40000"));

graphics.drawImage(originalIcon, 0, 0, null);

graphics.fillOval(originalIcon.getWidth()-40, 0, 35, 35);

graphics.setColor(Color.WHITE);
graphics.setFont(new Font("Helvetica", Font.BOLD, 23));
graphics.drawString(Integer.toString(num), originalIcon.getWidth()-28, 25);

graphics.dispose();

application.setApplicationIconImage(newIcon);
}

originalIcon is a BufferedImage we fetched by calling getApplicationIconImage on startup. The result looks like this:

You'll find the full example in Subversion here:

http://simplericity.org/svn/simplericity/trunk/macify-example

The source code of Macify Library itself is located here:

http://simplericity.org/svn/simplericity/trunk/macify

You'll find version 1.0 of the Macify Library  in the Simplericity Maven repository:

http://simplericity.org/repository/





Tags :