Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Deploying a new version of a GWT app

For the record, I’ve never even been offered a Microsoft MVP. How’s THAT for street cred! That said, if the MVP lead in my area is reading: even though I don’t speak at user groups these days and hardly blog (and even then, rarely about Microsoft products anymore), I still feel my lack of contribution to OSS projects should count for something…

Now back to our regularly scheduled hoe down.

One of the issues with GWT apps that’s only really discussed in hushed whispers in the back alleys of Google Groups is how to handle new versions. The nature of pure JavaScript applications is a bit of a hindrance in this case.

When converting a Java application to the necessary Javascript, GWT generates (depending on your set up):

  • a .nocache.js file
  • several .cache.js and .cache.html files
  • several .gwt.rpc files

The .nocache.js file has the same name every time you compile. But if you’ve changed any code, the cache files and rpc files will not. Here’s what my folder looks like today for BookedIN:

FolderStructure

 

The next time I GWT-compile (provided I’ve changed some code), the folders and files in red will be deleted and replaced with new ones with different names. Among other things, the scheduler.nocache.js file is used to locate these files on demand while the app is running.

We use the Google Plugin for Eclipse to deploy our application to AppEngine. We almost always deploy to a new version in AppEngine as well so that we can play around with it ourselves before unleashing it on an unsuspecting public. The upshot of this process is that the new version will have new .cache and .gwt.rpc files but not the old ones.

So let’s run through a potential scenario:

  • Our faithful user logs into BookedIN and uses the default version, which I will call “Dandelion”.
  • We deploy a new version, called “Thistle” and make it the new default version
  • The user makes a request for a page that is, say, behind a code-split. One of GWT’s nice optimization features that lets you split JavaScript among several files and loads them dynamically as needed.

At this point, the user has the main page and the .nocache.js file loaded in memory. When it tries to satisfy the request, it will look for a .cache.js file from version “Dandelion”. Only by refreshing the entire browser page will it then load the new .nocache.js file, which knows about version “Thistle”. But this being a GWT-type, AJAX-ified application, there is rarely much call for them to refresh the entire page.

Predictably, we get a 404 error:

404

This leads to some pretty nifty dancing when it comes to deployment time. For example, how do you take down the application for maintenance cleanly? If the user has the page loaded in memory and is just making AJAX calls, you can’t just throw up an appoffline.htm file and redirect all your traffic to it (says the guy who thought differently a few short months ago).

Even if you can take the app down for maintenance, I don’t want to. We’re trying to shorten our deployment cycles which doesn’t lend itself to a page that says “hey, paying user, we’re adding some cool new features so pardon us interrupting you using the old ones” every week even if it just shows for a few minutes. In short, what I’d really like is a hot deployment.

Based on my research and questions, this isn’t 100% possible but we can get close. As was suggested in the previous link, we can trap the appropriate exception in RPC calls and display a message to the user asking them to refresh their browser. Similarly, for code-split .cache.js files, we can trap the 404 error in the onFailure of the RunAsyncCallback (or better yet, use GWTP and have some main presenter implement AsyncCallFailHandler to make this easier) and do the same thing: notify the user that the page needs to be refreshed.

Initially, this kind of left a bad taste in my mouth. But from a marketing perspective, it’s not bad. We have a little popup that we display to users when we’ve implemented something new so this is a nice way to ensure they see it.

Another suggestion that was made (by one of the creators of GWTP, no less) was to use the Channel API to detect when a new version has been released. This has an advantage in that you don’t need to wait until the user does something before informing him of the change.

So far, much of this is theoretical for us because it was easier to write about it than to actually implement it. In any case, few people seem to be discussing it. Besides which, I had to write *something* after that little Microsoft MVP commentary.

Kyle the Filler

This entry was posted in BookedIN, Google App Engine, GWT. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://kyle.baley.org Kyle Baley

    We use a slight variation of the first method where we show an alert when we detect a 404 in the RPC or the callback exception. Except we don’t ask the user to refresh, we tell them that we’re about to do a hard refresh and then we do it when they click OK. So far, we haven’t had any complaints (which doesn’t mean there haven’t been any). We also do our deployments late Sunday evening which likely helps.

    The channel method is one we want to move to because it addresses one concern with our method: we’re interrupting them when they’re trying to do something.

  • Doug Stoddart

    Hi there, I just stumbled across this as I also have a web-app hosted on GAE/J using GWT. http://www.bikeshopmanager.com bookedIN looks nice, good work.
    I’m curious to how you now manage your updates? For about 7 months now I have been using a solution based around the Channel API to essentially send a ‘refresh’ message to my apps automatically – works well.

  • http://kyle.baley.org Kyle Baley

    Javier, if that works as well as I think it will, I shall bestow upon you the legendary title of “Honorary Hillbilly” for a FULL MONTH!

  • Javier Vargas
  • http://kyle.baley.org Kyle Baley

    Joel,

    I’m all about the distraction.

  • http://HuddledMasses.org Joel “Jaykul” Bennett

    So, if the two comments from people who actually appreciated your humor don’t clue you in … the snarky comments about the MVP program probably don’t belong at the top of an actual article. Just saying. I don’t even know what you’re reacting to, but it’s purely a distraction.

  • Battaile

    “, I still feel my lack of contribution to OSS projects should count for something…”
    Haha, well played sir.

  • Brendan Tompkins

    I was thinking someone needs to do a “How to react to MVP controversy” flowchart.  You’re the guy to do it IMO, being the most serious guy in .net.