The Dojo Bayeux client implements a bunch of different "transports" and tries to pick the right one based on what the browser can support, the cross-domain requirements, and so forth. When we started down this path, most of the reason for doing this was to implement both the forever-frame and long-polling styles of Comet as well as providing a platform to experiment with alternate transport types (e.g., Flash sockets). One of the most promising of these experiments took advantage of the multipart mime support that's been tucked away in the Mozilla codebase for quite a while. What follows is one of those stories that makes people assume that I'm crazy to do what I do for a living. They might be right.
Multipart is attractive because it provides a way of avoiding TCP set-up and tear-down for each and every event across the channel. While it's not significant overhead (comparatively), being able to also reduce the number of HTTP header blocks sent can also help out when it comes to wringing latency out of the system. The code indicates that multipart is supported on Safari and Mozilla, but while events are indeed delivered at the right times on Safari, you can't get at the payload until the connection closes completely. Not useful.
Things were looking better on Firefox and it was the preferred transport type in the Dojo client, but I think that's going to have to change. Sadly, it seems we can't actually tell when a multipart connection has failed. In "normal" XHR requests, the 200 HTTP status code plus a "finished" readystate indicates that the contents of the request can be read and control handed back. In the multipart case, each successful block fires of a load handler and resets the readystate. That means that the combination of readystate and and status can't be used to differentiate between block success and connection success. Making matters worse, server-side connection failure doesn't fire any kind of readystatechange handler, and even if it did, it doesn't appear to be possible to determine if the connection is closed from any of the public properties on the object.
So, OK, what about falling back to a timer that restarts the connection every N seconds for good measure? This might work in cases like failover where a lag of 10 to 30 seconds might be acceptable but not for normal operation. Should events be flow regularly, it might never be necessary to hit this "backstop". Not great, but I gave it a try, only to discover that Firefox won't give you responseText of an XHR request if the connection is marked as multipart but the response isn't a 200 and wrapped in a multipart block. Since we're trying to use HTTP status codes correctly and keep the server internals from needing to fork significantly for each pluggable transport, it's something of a step backward to need this kind of hand-holding.
I'd still like to support the multipart transport type, but until at least one of the implementations becomes rational for use from the XHR object, I think I'm going to just be commenting this transport out in
cometd.js. Like XHR itself, it's one to mark down for resurrection a year or two from now. At least we still have good enough options in the mean time.
This past week I had the good luck to be invited to speak at JavaPolis and while there, even for only 2 days of the weeklong event, amazing stuff seemed to be dropping out of the sky like rain.
My talk was in the first slot of the first day of training (before the official conference start), but despite the hour and the day, folks still came to hear about Dojo. Following me were Jonas Jacobi and John Fallows' talk on JSF+Dojo, but little did I know (until a half hour before they gave the talk) that they'd written a new Comet server from scratch for the talk, and it implements Bayeux! Their demo hooked a Dojo table and chart widget up to a set of Bayeux channels for updating stock prices. It's always fun to see everything on the screen update in unison.
Lastly, there was some spirited debate in the never-ending static vs. dynamic languages debate over dinner. Not sure I swayed anyone at the table, but there was a pretty strong dynamic languages contingent at the conference in general, which I wasn't expecting.
I was happy to hear that the Swing team at Sun is starting to really get that startup time and complexity really are significant limiting factors. To that end I started to throw together a very small
I just fired up Firefox to do a bit of writing over in the project wiki, and as sometimes happens, I was presented with an extension update notification screen. The UI is mostly a farce of user control in that there's not nearly enough information to judge whether or not going to the next version of Me.dium is a good idea or not. I blithely click "OK" to let it do it's installation dance in the hopes that it'll get out of the way. I've got stuff to do. It dutifully proceeds.
A couple of seconds later, it's done, and instead of getting an unobtrusive notification of success while the browser starts to load whatever it is that I actually care about, the update window simply shows a nearly identical UI, but the button that had previously allowed me to proceed with the upgrade now reads "Continue". Do I have a choice at this point? What would closing the browser at this point ever buy me over hitting "Continue"?
Given the massive number of Firefox users and their use of extensions, it boggles the mind to think how much time is wasted by this one button alone. Unless there is an affordance for recoverability (roll back the upgrade) or discoverability (what just happened?), this button needs to die.
AOL has been generously hosting builds of the toolkit in their CDN for some time, but using these builds has always seemed scary. Configuring local and remote copies of the same thing hardly seems like fun. Also, lots of people ask us for a way to "just include one file to get Dojo". It's an obvious thing to do, and it turns out the cross-domain infrastructure that AOL donated is the perfect solution to both problems!
In response to Amit Green's excellent suggestion, I've constructed a couple of very small "wrapper" files that will let you include the "Ajax" build of Dojo from various versions through the cross-domain loader. Including the latest stable Dojo couldn't be simpler:
It's also trivial to test out the latest 0.4.1 Release Candidate:
That's all there is to it!
From here on in, your pages can use the
dojo.require() system to pull in anything that's part of the "stock" distribution, and by following James' detailed documentation and test page, you can also load your own custom packages while still loading the main system from a separate domain.
So for a little while I've been giving this talk on the current state of mobile web app development and why Ajax (as we know it) isn't gonna be the next big thing on phones. Last week, to my tremendous embarrassment, I was asked to give a summarized version of the same talk in front of a lot of folks who actually work on the phone browsers I've been slagging. Of course, me being embarrassed didn't make the state of play on phones any better, but in discussions afterward it became clear that a lot of the people working on these browsers really do get what users want. Not surprisingly, the ones with the best understanding of how to improve the experience were the same people that don't have their bills paid by the OpCos. And then there was J2ME.
Long story short, between XML, XHTML, J2ME, WAP, and BREW it seems the mobile content industry has been so preoccupied trying to stuff useful data into sausages for delivery that they totally forgot why the web won: it lets you be lazy.
The web lets Moore's Law play out to the advantage of people who don't want to understand XML, XHTML, what a "mobile variant" or "compact profile" is, or why they should really think about entering into some sort of totally lame legal agreement with Evil OpCo X. That is to say, HTML and "tag soup" let every Joe and Srinivas put something into the commons for everyone else to see. Even if it's was "broken", you still get best-effort results, and that implies that every successive hardware generation can work harder to do the "right thing". Why is this totally awesome? 'Cause I get to be lazier as a result.
So here's a quick note to the folks who are holding on to the J2ME or XML pipe dreams: you're infrastructure. Cope. Yes, you'll still be "ubiquitous", but you'll never be loved, and don't imagine that you're hard to replace. The really creative stuff isn't going to get done on top of you until you learn to start applying those cycles to letting people be lazy. And I don't mean "here, have a gig of tools that you can use to produce a 'hello world' once you learn this programming language". I mean "so what can I do with Notepad?"
Actually, maybe that's what we should call it: The Law of Notepad: if creative people can't make something awesome using the lamest of production tools, your platform is gonna loose.