Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Patterns + GWT + Ajax = Usability!

Enhance your Web site with Ajax, GWT, and design patterns

Federico Kereki, Systems Engineer, Freelance
Photo of Federico Kereki
Federico Kereki is a Uruguayan systems engineer with more than 20 years of experience developing systems, doing consulting work, and teaching at universities. He is currently working with a good jumble of acronyms: SOA, GWT, Ajax, PHP, and of course FLOSS! You can reach Federico at fkereki@gmail.com.

Summary:  The Google Web Toolkit (GWT) allows for easier development of complex Web sites. When combined with certain design patterns that enhance usability and Asynchronous JavaScript and XML (Ajax), these technologies and techniques provide a smoother look and feel to your application. The result is an application closer to a traditional desktop program than to a typical Web page.

Date:  21 Jul 2009
Level:  Intermediate PDF:  A4 and Letter (301KB | 17 pages)Get Adobe® Reader®
Also available in:   Chinese  Japanese

Activity:  41496 views
Comments:  

Rated by the Jargon, Acronyms, and Buzzwords (JAB) index, the title of this article scores high, but all the terms do come together. This article examines several programming patterns, that together with GWT and Ajax, can produce a better user Web experience with faster response times. And don't worry if you aren't familiar with the JAB index: I just invented it!

Usability

Let's work through the equation in the title from right to left, starting with usability. The usual Web-oriented definitions call for easy-to-use sites that have clear screen layouts and workflow logic, don't require specialized training, and so on. In this case, I focus specifically on response time. Speed alone doesn't provide usability (although under-performing sites aren't very usable), but the tools I consider can make a speed difference without harming other aspects of your site.

Ajax

Ajax allows a client to retrieve data from the server in the background, providing a more streamlined feeling to the user; a well-designed Ajax Web application can look and feel just like a standard (installed) program. Before Ajax, all data requests implied standing by, waiting for the server to answer. With Ajax, users can keep working, and the data will be invisibly fetched. (Actually, Ajax isn't truly required; by using an iframe appropriately, you can manage the same effects, though in a more complicated way.) Being able to free users from (some) delays is an important step toward more usable applications, and that justifies including Ajax in the sum.

The Google Web Toolkit

The GWT is a fully open source Java™ development framework that lets you create Ajax applications working exclusively with the Java language. This bears some attention: Using Java code for the server side is old hat by now (think applets), but here, I mean Java code that gets compiled into JavaScript code, which the user's browser then executes.

GWT applies Ajax transparently. A client application can use server-side servlets almost as if they were client-side servlets, which means that the client and server can (with some limits) share classes and code, allowing for "thicker" clients. Prior to GWT, client-server interactions were more complicated to program, and of course you couldn't use Java code for the client. GWT bridges that gap, making for easier development of highly usable sites.

Patterns

Now, what's a pattern? In software engineering, a pattern represents a general, widely applicable solution for commonly occurring problems. It isn't a direct solution, but rather a "path" that leaves implementation details up to the programmer. A pattern allows developing software more quickly, because it provides a tested, proven scheme.

Patterns originated as an architectural concept, and comparisons with architecture are common. As an oft-cited example, a window is a solution to let the sunshine in, but that doesn't specify the exact shape or style of the window. There need not be a single pattern for a problem (a skylight or an open patio could also solve the lighting problem), and it's up to the designer to decide which pattern to apply. This article introduces several performance problems and provides GWT-appropriate solutions that you can use in your own Web sites.


The test database

Building a large test database

To test server-side servlets and client speed, I needed a large enough database: I used MaxMind's free cities table (see Resources). I added the International Organization for Standardization (ISO) 3166 table of country codes and both the ISO 3166-2 and Federal Information Processing Standards (FIPS) 10-4 tables of region codes, because the U.S. cities data used codes such as AK for Alaska instead of the numeric ISO codes. The needed data was provided as comma-separated values (CSV) files and easily loaded into MySQL tables.

Another possibility would have been using random (or almost random) data, but the cities information was clearer. See Resources for alternatives.

I worked with a simple database (see Listing 1) that included the countries, regions, and cities of the world. I just needed large enough tables, and an open database (see the sidebar, "Building a large test database") provided about three million records, so that suited my needs. To follow the examples below, note that:

  • Countries are identified by a code (such as US for the United States) and have a name.
  • Countries have regions, identified by a (usually numeric) code, unique only within the country, and with a name.
  • Cities are within a region of a country and have a (pure ASCII) name, an accented name (which might include foreign characters), a population (or 0, if unknown), a latitude, and a longitude. The city name is unique only within a region of a country; there are about three dozen cities named Springfield in the United States alone!

Listing 1. Database creation code
	
CREATE DATABASE world
  DEFAULT CHARACTER SET latin1
  COLLATE latin1_general_ci;

USE world;

CREATE TABLE countries (
  countryCode char(2) NOT NULL,
  countryName varchar(50) NOT NULL,
  PRIMARY KEY (countryCode)
  KEY countryName (countryName)
);

CREATE TABLE regions (
  countryCode char(2) NOT NULL,
  regionCode char(2) NOT NULL,
  regionName varchar(50) NOT NULL,
  PRIMARY KEY (countryCode,regionCode),
  KEY regionName (regionName)
);

CREATE TABLE cities (
  countryCode char(2) NOT NULL,
  cityName varchar(50) NOT NULL,
  cityAccentedName varchar(50) NOT NULL,
  regionCode char(2) NOT NULL,
  population bigint(20) NOT NULL,
  latitude float(10,7) NOT NULL,
  longitude float(10,7) NOT NULL,
  KEY `INDEX` (countryCode,regionCode,cityName),
  KEY cityName (cityName),
  KEY cityAccentedName (cityAccentedName)
);
         

I developed a GWT project (see Downloads for complete source listings), including a simple menu (Figure 1) plus two equally simple Web forms: a Cities Creator (for adding new cities to the database—see Figure 2) and a Cities Browser (for paging through the cities in any country region—see Figure 3). I wrote the code in the simplest way I could, with minimal extras, because the idea to show patterns. I worked with GWT version 1.5.3 and MySQL version 5.0; development was done with Eclipse Ganymede running under OpenSUSE version 10.3 Linux®.


Figure 1. The main menu of the sample application, showing both available forms
Screenshot of the main menu of the sample application.  A browser window with the URL http://localhost:8888/com.fkereki.MyApplications/MyApplication.html.  In the content window a title bar with the headings 'Cities Creator' and 'Cities Browser.'

Figure 2. The Cities Creator form allows you to add new cities to the database
The cities creator form shows fields for creating a city: Country, with a dropbox of countries; Region, with a dropbox of regions; City Name, Accented City Name, Population, Lattitude and Longitude, all with text fields.  At the bottom is a button marked 'Add the city.'

Figure 3. If the user enters a duplicate city name, an Ajax background check gives a warning and highlights the field
Screenshot of the the Cities Creator with an error condition.  Country reads 'United States.' Region reads 'New York.'  City Name is 'Albany' in red with a yellow background.  A dialog box is popped up reading 'That city is already in the database' with a button reading 'OK.'

Pattern: prevalidation

An axiom of client-server computing is to check everything server side. (Even if data is validated before calling the server, changes brought by other users might invalidate your previously correct data. An originally available article might have gone just now out of stock.) However, you don't want to make users wait for a client-server round trip before learning about a simple mistake. The solution: Make an Ajax call in the background to a server-side checking routine; if there are errors, warn the user, highlight incorrect fields, and so on.

Study the CitiesCreatorForm class and its addDuplicateCityNameCheck method. Assume that the user should never enter an existing city name. Given the server-side cityExists service that checks for duplicates, add a ChangeListener to the cityName text box; if the user picks a country, region, and city name, call the service and check if it's a duplicate at that time.

The given code has a subtle problem, though. Suppose a nimble-fingered user enters a (duplicate) city name but immediately realizes his mistake and fixes it. Soon, he or she receives an alert stating that the (now correct) field is wrong. A simple fix (see Listing 2) is given in the CitiesCreatorForm2 class: Save the service parameters and, on getting an answer, check whether the form still has the same values as the parameters; if not, don't do anything.


Listing 2. Prevalidation pattern pseudo-code
	
create a new ChangeListener that will:
    get the form field values needed for the check
    if all fields are filled
        save the form field values
        call the server-side service to perform the check
        on callback:
            get the form field values again
            if the current values match the saved values,
                if there was an error,
                    highlight the fields
                    warn the user
                otherwise
                    reset fields to normal

assign the created ChangeListener to all involved form fields
            


Pattern: code sharing

Not all checks need be done on the server, and the more client-side checks, the more spry your application. With classic Web-development tools, that would mean coding all checks twice (once for the server and once for the client), but GWT allows you to use the same Java code on both sides. However, although server-side code may use all Java code, client-side code is compiled to JavaScript code and will share that language's limitations. For example, JavaScript code isn't allowed to use files; thus, you cannot use java.io on the client side.

The code-sharing pattern calls for implementing a client-side version of a class, then extending it for your server, which will be able to use all Java features. Because client-side code is only able to deal with its own, limited objects, two special methods are needed: a constructor that can receive a client-side object and use it to create a server-side object and a method that can produce a client-side object out of a server-side object.

The provided ClientCityData and ServerCityData classes show this pattern. The client-side code needs to implement the IsSerializable interface so objects can be sent back and forth between the client and the server. The ServerCityData class can only be used on the server and includes both special methods described above.


Pattern: caching

So far, GWT has helped me deliver more performance, but there is one area in which it could even make performance worse: caching. Whenever a browser requests a page, it first looks into its own cache. If it finds the needed results there, it won't call the server and simply provides the data. (Of course, many conditions must be fulfilled before something goes into the cache, but that's not relevant now.) The problem is that when GWT calls a servlet, it implements a Remote Procedure Call (RPC) by a non-cacheable Ajax procedure, so even if you repeatedly ask for the same data, the browser won't use its cache, and there will be a delay every time, as shown in Figure 4.


Figure 4. The Cities Browser lets you page through a region's cities
A screen shot of the Cities Browser form showing Country/Region, with a dropbox of countries, and another dropbox which says 'Select a region...'  Below are buttons for 'First 50 cities,' 'Previous 50' and 'Next 50.'  Below the buttons is an empty results section with column headings for City, Population, Lattitude and Longitude.

If your page needs the same (constant) information that it got earlier, you can enhance performance by setting up a local cache, as shown in Listing 3. Before calling the server, check if the needed data is already loaded and if so, skip the call. Of course, don't use a cache for information that changes often. If information can go stale over time, add a time stamp to avoid using old data.


Listing 3. Caching pattern pseudo-code
	
class_with_cache code:
    define class attributes for the cache (a hash map, array, whatever)
    set the cache to empty

    whenever new data are asked for:
        check if the asked data are already in the cache
        if so,
            get the data from the cache
            perform whatever needs be done with it
        otherwise,
            display an appropriate "loading" message
            call a server-side service to get the data
            on callback:
                put the data in the cache
                perform whatever needs be done with it
            

There are three examples of this process in the provided code—all for the CitiesBrowser class. The simplest one has to do with a list box (see the CountryList class) showing all countries. Its basic implementation called the server (to get the countries list) for each object. The modified CountryListWithCache class saves that data in a class variable so that it can be shared by all objects; only the first object creation actually implies a call to the server.

I also needed a regions list box (see the RegionList class) whose contents should vary depending on the current country. There are several thousand regions across the world, and getting all of them isn't practical. To implement a cache (see the RegionListWithCache class) I used a hash map; whenever the country changed (see the changeCountry method), I checked first if I had already gotten that country's regions.

The final example (see CitiesGrid and CitiesGridWithCache) is a bit more complicated. Regions can have too many cities, so information has to be paged. I used a hash map as a class attribute, but had to construct a key that included the country, the region, and the page start, as shown in the LoadCities method.


Pattern: prefetching

Whenever lots of data needs to be sent from the server to the client, some kind of chunking is needed. If you could know in advance which information a user was going to ask for, you could use Ajax mechanisms to "get ahead of the game," asking for the data before it's required. You cannot always guess what a user is going to ask for, so there's the chance that you will be mistaken and bring over some unneeded data; that risk must be balanced with sure delays if you do not prefetch.

But be careful: Don't go overboard and prefetch everything in sight, or you'll make things worse! Since the time of limited-bandwidth dial-up modems, browsers have limited the number of client-server connections. That limitation even made its way into the Hypertext Transfer Protocol (HTTP) version 1.1 standard ("A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy.") If you make several requests to your host, only two of them will go out (in parallel), and the others will be queued for even longer-than-usual delays.

The CitiesBrowserWithCacheAndPreFetching shows the needed changes to implement this. First, change the loadCities method so that it won't always show on screen whatever data it has loaded: When prefetching, you don't display anything. Second, whenever a page is shown (see the showCities method), prefetch the next one (a logical guess) without showing it. And finally, whenever a user picks a country and region, prefetch the first two pages just in case, as shown in Listing 4. Note that if the code asks to prefetch an already-fetched page, the implemented logic avoids making unnecessary, redundant calls to the server.


Listing 4. Prefetching pattern pseudo-code
	
class_with_cache_and_pre-fetching code:
    define class attributes for the cache (a hash map, array, whatever)
    set the cache to empty

    load_data method:
        check if the asked data are already in the cache
        if so,
            get the data from the cache
            perform whatever needs be done with it
        otherwise,
            display an appropriate "loading" message
            call a server-side service to get the data
            on callback:
                put the data in the cache
                if data were needed (as opposed to prefetched),
                    perform whatever needs be done with it

    processing_data method:
        call the load_data method to get that data
        call the load_data method to get extra (prefetched) data
            


Pattern: thread simulation

Suppose a processor-intensive task, like processing large amounts of XML or displaying lots of data. If the process takes too long, users receive a message like Firefox's "A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete." or the similar message in Windows® Internet Explorer®, "Stop running this script? A script on this page is causing Internet Explorer to run slowly. If it continues to run, your computer may become unresponsive." Even worse, if a user pays heed to the warning and stops the script, he or she will actually cancel your client-side program!

This error is typically solved by using threads, but GWT won't allow it, because the JavaScript language provides just a single thread of execution, so the compiled threaded code couldn't work properly. Ajax would provide a way out for server-side processes but is of no use on the client. Fortunately, there are two patterns for this; I apply them to displaying the full page of cities.

A timer-based solution

GWT provides a Timer class with a schedule() method, akin to the JavaScript language's own setTimeout() method. The idea is to do a bit of work and store values so the process can continue later (after a timeout), freeing the processor in the meantime, as shown in Listing 5. Check whether the process needs to go on; the user might have decided to page forward or backward, and it wouldn't do for the former page data to show up.


Listing 5. Thread simulation with timers

	
define a class that extends Timer:
    define attributes so it can save its parameters
    define attributes so it can save local variables from run to run
    define attributes so it can save form field values

    on construction:
        save the received parameters
        initialize local variables for the process
        save the current form field values
        display a "loading" message

    run() method:
        if the current form field values match the saved values:
            execute some process, updating the local variables
            if there's still more work to be done
                schedule another process in a short while

whenever you want to simulate a thread with a timed method:
    create an object of the new class above, with appropriate parameters
    execute its run() method
            

The CitiesGridWithCacheAndPreFetchingAndTimer class shows this pattern. The private TimedCitiesDisplay class extends the Timer class. On construction, it receives a list of cities and initializes an iterator to go through it; it also saves the current country, region, and page to later check whether the process must continue. The run() method goes through a few cities; if there are any more cities left, it schedules a future run, which restarts the work wherever it was stopped, as Figure 5 shows.


Figure 5. The background cities are displayed midway through its work (some cities haven't been loaded yet)
A screen shot of the Cities Browser form showing Country/Region, with a dropbox of countries showing 'Uruguay,' and another dropbox for the region which says 'Colonia.'  Below are buttons for 'First 50 cities,' 'Previous 50' and 'Next 50.'  Below the buttons is a results section with column headings for City, Population, Lattitude and Longitude populated with data from various cities.

For this solution to work smoothly, study the maximum amount of work that can be done at each step and the time interval to allow between steps. A large number of short steps might mean a more responsive machine, but it also means a longer wait until getting all the data. However, long steps can possibly lead to the "busy script" message, and that's also bad. Only experimentation will show the best compromise.

GWT's own deferred commands

Deferred commands are a GWT-specific feature that may provide an even better solution. Deferred commands are queued and executed when the processor is free, as shown in Listing 6. The solution: Parcel the process into short steps, but use a deferred command instead of a Timer. GWT will decide when it can run the next step of the calculation.


Listing 6. Thread simulation with deferred commands
	
define a class that extends IncrementalCommand:
    define attributes so it can save its parameters
    define attributes so it can save local variables from run to run
    define attributes so it can save form field values

    on construction:
        save the received parameters
        initialize local variables for the process
        save the current form field values
        display a "loading" message

    execute() method:
        if the current form field values match the saved values:
            execute some process, updating the local variables
            if there's still more work to be done
                return true, so it will run again shortly afterwards
            otherwise,
                return false (the job is done)
        otherwise,
            return false (situation changed)

whenever you want to simulate a thread with a deferred command:
    create an object of the new class above, with appropriate parameters
    use the addCommand() to add your new object to the processing queue
            

The CitiesGridWithCacheAndPreFetchingAndDeferredCommands class shows this. The main differences with the timer solution are that commands are queued and the execute() method returns True if the process must be sent back to the queue for another round.

This solution is more flexible than the Timer pattern, as it goes full speed if the user doesn't do anything but doesn't keep the machine from being responsive otherwise. Just don't do too much at a stretch.


Conclusion

This article discussed design patterns that provide ways to accelerate your GWT application by leveraging the use of Ajax in the background. It provided some workarounds for common JavaScript limitations (such as the lack of threads) and the usual time delays when requesting data from the server (by prefetching, caching, or prevalidating locally at the client). GWT, Ajax, and a few patterns can help speed up your application and enhance its usability by providing users a much more responsive Web site.



Download

DescriptionNameSizeDownload method
Full source code for this articlefull_source_code.zip24KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

Photo of Federico Kereki

Federico Kereki is a Uruguayan systems engineer with more than 20 years of experience developing systems, doing consulting work, and teaching at universities. He is currently working with a good jumble of acronyms: SOA, GWT, Ajax, PHP, and of course FLOSS! You can reach Federico at fkereki@gmail.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=415027
ArticleTitle=Patterns + GWT + Ajax = Usability!
publish-date=07212009
author1-email=fkereki@gmail.com
author1-email-cc=