You Call That An Application?
So, I've done the nice Java thing and deployed my applications as executable jars, with properly formatted manifests, and, um...
well, I'm feeling a little underwhelmed.
Let's face it, those don't look like applications. Nothing about them stands out in a folder and says hey, double-click me!
Oh sure, I could use an application to create an "installer" for my application. That would wrap my jar with an
.exe on Windows, put it in a
.app bundle for Mac OS X, etc. But I'm not entirely comfortable with reducing "write once, run anywhere" to "write once, run wherever the installer bothers to support".
Is a Java application just a class with a
static void main (String)? I think that fails to capture many of the behaviors we typically expect from desktop applications, such as:
- A custom icon.
- Document association (the ability to launch and open docs when they are double-clicked, based on metadata about the file like its filename extension, Mac
TYPE/CREA, BeOS MIME type, etc.)
- The ability to ask for the user's attention while in the background (flashing the button on Windows task bar, bouncing the Mac OS X icon, etc.)
- Provide a real name to the rest of the OS (ever run five java apps on Windows, noticed one has hung, then gone to the Task Manager and had to guess which of the five "Java"s needed to be killed?)
While I'm at it, I'm going to be greedy. After all, I played with Project Builder on Mac OS X to bundle up a java app in a Mac wrapper recently, and I'm jealous of some of the things that developers over there can take for granted in native applications, including:
- A standard for placing localization files. Sure, we have ResourceBundles in java, and a scheme for locating them based on the current Locale, but where do they go? Do you have one per class, one per package, or one per application?
- Same thing for artwork. Yeah, both L10N files and artwork can go in the jar file and be found along the classpath with a ResourceLoader, but if that's such a great idea, why don't we standardize on some paths in the jar, instead of making new developers repeatedly re-invent the wheel? This would be great for tools too.
- Java command-line args. Ever tried to set something like the max stack size (the old -mx command-line arg for "java") with a double-clickable jar file? Last time I checked, no amount of Manifest voodoo could do this. But Project Builder will do it for pure-java bundles on OS X.
To top it all off, I don't want to get any of this by going outside of standard Java... maybe I could get some of my application behavior with a mixture of a platform-specific installer and some JNI code to get outside the Java "box", but then I'm radically limiting the number of platforms, present and future, that my app can run on.
Obviously, this is a big wish-list. And I don't have all the answers. But I think I see where part of the problem is.
I've been openly envying Mac OS X application development above, so let's look at the layers involved with a Cocoa app:
- Language - in which we write the behavior specific to our application - Objective-C (or, if you're gutsy, Java)
- API's - which provide common functionality to applications - CoreFoundation, Quartz, QuickTime, etc.
- OS - which executes the code and provides the display, sound, networking, I/O, etc - Mac OS X
Now compare that with how a Java application's layers:
- Language - Java
- API's - Java core libraries
- OS - Java Virtual Machine
From what I can see, we have a very nice language, a vast set of API's, and a runtime environment that's not holding up its end of the deal. When people complain to me about the inability of Swing to deliver professional applications, I tell them that I don't think that it's Swing that's lacking. Surely anyone developing AWT or SWT applications has the same problems developing apps that act like real apps.
What do I want from the JVM? I think two things need to happen:
- There needs to be an Application class or interface that gives us some kind of abstraction of behaviors like requestUserAttention() to bounce an icon or flash the task bar. The JVM then provides a platform-appropriate implementation, if any.
- There needs to be a standard for where we put localization files, artwork, etc. inside the jar. Maybe also files defining file-associations by filename extensions, MIME types, or other predictable and somewhat standard systems. And a file for java runtime arguments.
But now here's the kicker - when the JVM sees it's running a jar whose main class is such an Application, it does a one-time-only repackaging of the jar, with the user's permission, into something that makes sense on that platform. On Windows, it creates a folder with needed files in the right places and an .exe to invoke java, dinging the registry to set up file associations. On Mac OS X, it creates a .app bundle. If the platform isn't supported in this manner, then running from the jar still works; you can still pick up the localization files and artwork from the classpath, and any Application calls like requestUserAttention() just harmlessly no-op. That way, nothing breaks, but current and future operating systems get java applications that behave more like native applications.
I know, this is probably idle dreaming. But something along these lines would make it easier for developers to make "first-class" applications in Java.