Item 51: Consider rich-client UI technologies



Item 51: Consider rich-client UI technologies

No, this tip doesn't refer to the wealthy customer who wants changes made to the application. Instead, it refers to that form of presentation that offers a richer, more powerful user interface, in contrast to the thin (HTML-browser-based) client.

The HTML-browser-based thin-client application offers a significant advantage over traditional two-tier, fat-client, client/server applications: low to no deployment costs. Because the HTML resides on the server, deploying a new version of the application requires zero client-side installation. As long as the client has a Web browser, he or she is ready to use the system. Since literally every operating system on the planet offers a browser as part of the base installation, clients can start using the application as soon as the upload to the server is complete. Even more importantly, updates to the application can happen as often as necessary because nothing needs updating on the client machine. This Zero Deployment scenario is powerful, particularly for enterprise applications because they have a tendency to evolve more quickly than shrink-wrap software. Users don't even need to know when a new version rolls out—they're always downloading what's on the server anyway.

However, HTML also carries with it a number of disadvantages.

  • Portability: HTML was designed from its inception to be a cross-platform technology, and as a result, it suffers somewhat from that portability. Form controls are rendered entirely as the host (the browser) wishes, so HTML forms behave differently from platform to platform. This can make designing easy-to-use forms difficult, if not impossible, particularly if the forms are complex.

  • State management: Because the Web browser can't hold client-side state (aside from cookies, which are extremely limited in scope), an HTML-based thin-client application needs to hold all user state on the server, identified by an opaque token usually stored in a cookie or as part of subsequent requests (also known as URL rewriting). Unfortunately, this also increases the load on the server and reduces the server's scalability. An alternative is to make the application entirely stateless and pass all data required between the browser and the server, usually encoded in hidden form fields or embedded inside request URLs. Unfortunately, this isn't a perfect solution either, since now additional bandwidth is consumed to transfer all that state back and forth on every request. There's also a security concern. A well-known (perhaps apocryphal) story tells of a creative consumer who noticed that the price of the computer system he was about to purchase online was stored in a hidden field on the form. He created a local HTML page to mimic the online purchase order form but coded the hidden price field to contain a value of $1. He submitted it, and it was accepted—in essence, he purchased a $5,000 system for exactly $1. (The story goes on to say that the computer manufacturer tried to sue him but the suit was denied because the system behaved precisely as it should. That online system no longer encodes price in hidden form fields.)

  • Control: HTML offers little in the way of control over how elements are rendered; in fact, HTML's original approach was to be as high-level as possible, deferring to the host browser on how to render elements of the HTML page so that it would be as close to the norm for that platform as possible. Over time, however, HTML page designers have sought more control over how the presentation elements are rendered in the browser (as all good UI designers do). Cascading Style Sheets (CSS) offers some of that ability, but even so, not all browsers support CSS fully, nor does CSS provide complete control over all presentation elements—for example, page designers must provide a set of fonts to use for a given presentation element, in case the font desired isn't available on that platform.

  • Cross-platform differences: Despite the best efforts of the World Wide Web Consortium, HTML is one of the least-obeyed standards on the Internet. Both major browsers—Microsoft Internet Explorer and Netscape Navigator (Mozilla)—offer significant extensions, and while both claim to comply entirely with HTML 4.01, each seems to have problems rendering certain facets of legitimate HTML 4.01 markup. The story gets even worse when considering client-side scripting languages: Internet Explorer supports both VBScript and JScript, whereas Navigator uses JavaScript. Each provides its own object model for working with items on the page. And each makes enhancements and adds features to new versions of the browser, meaning that a site must consider not only the browser type but the advertised version of that browser as well. As a result, frequently sites just choose a particular vendor and version number to support ("Best viewed with Internet Explorer 5.5") and code to that browser alone, leaving users outside of that range more or less out of luck.

  • Bandwidth: HTML is a presentation language, designed for providing hints and commands to the host browser on how to render a user interface. On every action by the user that requires a new interface, the entire interface must be sent to the browser, including both data and presentation elements. This means that additional bandwidth is consumed on each request, increasing load on the network (and the server). Some sites try to reduce this by shipping data back to the browser and using an XSL Transformation in the browser to marry the data to the user interface, but this is supported only in Internet Explorer (and only in very recent versions at that). Even then, the browser must obtain the XSL script via another HTTP request.

  • Lack of presentation elements: The HTML form is extremely simplistic, offering about a half-dozen controls for use: push buttons, radio buttons, check boxes, edit controls (single-line, multiline, and password), and drop-down lists. While you could argue that this "core set" of controls is all any application really needs and that HTML's ability to use clickable images can provide additional behavior, the fact remains that in comparison to the UI elements of the operating system underneath the browser, HTML forms are severely constrained. Menu bars and tool bars can be approximated with Dynamic HTML (DHTML) and/or client-side script programming, but now we're back to the realm of cross-platform support.

It's a testament to the benefits of Zero Deployment that so many application developers are willing to develop workarounds to all these problems. In fact, many applications just assume only HTML 4.0 and as a result produce applications whose user interfaces appear to have stepped directly out of the early 1980s.

The problem here is that developers have forgotten why they adopted the HTML-based interface to begin with—trivial, if not zero-cost, deployment of new versions of the code. While HTML certainly is enough for some applications, it pays to take a look around at other UI approaches to see if some of these problems can be solved while still maintaining the benefits of Zero Deployment. As it turns out, several rich-client technologies offer Zero Deployment and the benefits of a richer client-side footprint.

One principal advantage to a rich client is that of state management: not only can the rich client hold state information locally until it needs to be sent to the server for processing (such as when the user finally clicks the OK or Apply buttons), but the lifetime of the rich client also mirrors that of the user's session. When the user exits the rich client, it can perform the necessary cleanup to release the resources for that given user. Because all state is held on the client, load is removed from the server. Thus we avoid all issues of cookies, server-side session state (which in turn leads to more scalable server-side footprints), session timeouts, and so on. That in itself is usually enough to convince the servlet developers of the world to consider another approach than just HTML.

The following subsections briefly discuss several of the available rich-client technologies.

Dynamic HTML

If we view client-side presentation technologies as a continuum with traditional fat clients to the far right and pure HTML 4.0 (or its successor, XHTML 1.0) at the far left of the picture, DHTML is just a half-step to the right of HTML 4.0. In essence, this is your classic JavaScript/JScript/VBScript code downloaded as part of the HTML from the server and executed as part of the client's browsing experience. Both of the major browsers have extensive DHTML support, and as a result some very interesting effects can be accomplished that plain-vanilla HTML can't do, like mouse flyover effects and such.

The problem with DHTML, unfortunately, is its complete lack of standardization. Despite numerous attempts to do so, each of the browser vendors has introduced specific features into its products as value-added benefits, and as a result it's not uncommon to see little graphic images in the corner of an application's entry page reading, "Best viewed with Internet Explorer" or similar text. In addition, as if that weren't enough, trying to degrade gracefully to an older version of the browser can be a difficult task.

Certainly, lots of server-side support has emerged over the years to make working with DHTML easier. JSP tag libraries are just one of several solutions to make this easier, for example. The real problem is that many users don't like client-side scripting for one reason or another (some organizations really dislike it, fearing security holes), and as a result, many browsers in the World Wide Web have client-side scripting turned off—which essentially shuts down your beautifully crafted DHTML user interface. Oops.

Macromedia Flash

Flash is probably the most popular rich-client technology in use today. Although typically used for passive, animation-based multimedia clips, Flash is capable of issuing HTTP requests and parsing the responses, meaning that a Flash-based client, using HTTP to communicate back to the server (typically to a java file upload servlet), is not only feasible but also practical. A Flash-based approach does suffer from the drawback that the Flash player browser plug-in must be installed on the user's desktop in order to function, but by this point in its lifecycle Flash is well enough established that we can safely assume this for a large number of users. For those users who don't have the Flash player installed, the Flash site has a self-installing download that requires only a single click to install.

Despite all this goodness, Flash is rumored to be notoriously difficult to program against, and many organizations have reservations about hiring Flash developers on the grounds that because that skill tends to run more in the area of graphic designers than hard-core J2EE programmers, it means forking the team across two languages. Macromedia has been working on Flash to extend it into the enterprise area, by putting better XML support into the environment, and as a result some of the first Flash-to-Web-Service back-end applications have started to appear. In addition, Macromedia is pushing Flex, a more developer-oriented way to build Flash applications; whether it will succeed long-term remains to be seen.

The difficulty of programming Flash is a solvable problem; unfortunately, another problem arises, in the same category as the DHTML problem. Because Flash doesn't come installed in the Web browser out of the box, users have to install the Flash plug-in the first time they navigate to your site (assuming they haven't installed it already), and for some users (think of your grandparents, for example) this is a nontrivial process—and, once again, many large organizations are turning off any installed plug-ins in user browsers due to security concerns. While it's certainly more common to see Flash installed than not, it's still a concern if your goal is to reach as many users across the Internet as possible. In addition, you need to keep a careful eye on the minimum browser requirements for the Flash plug-in itself, to make sure that it stretches back far enough for your particular user base.

Applets

Java applets offer solutions to some of the problems mentioned earlier, but they introduce problems of their own. For starters, applets rely on the JVM in the browser, and neither Microsoft's nor Netscape's record is very good here—neither browser supports beyond JDK 1.1 out of the box, and Java's AWT UI library is too significantly constrained in functionality to seriously consider it for an industrial-strength enterprise application. Sun developed the Java Plug-In as a workaround for both browsers, but in addition to the fact that the Plug-In has a nasty reputation among those projects that relied on it, it leaves other browsers still unsupported. In addition, the applet security model is extremely restrictive, requiring digital signatures in order to do even the simplest thing, such as write to the local filesystem. Even worse, the applet must be downloaded each time the user browses to the page, meaning large UI applications face significant download hits.

Quite possibly the largest problem with applets, however, is that if all the browser has installed is the 1.1 JDK, there is no Swing support, and developing a user interface against AWT 1.1 is truly an exercise for the incredibly sick and twisted. Theoretically, you could extract the Swing classes from rt.jar and put them into your applet's .jar file, but you're looking at several megabytes worth of compiled code, and again, that's going to be downloaded on every visit to the page. This assumes, of course, that there aren't any dependencies within Swing on JDK 1.2, 1.3, or 1.4 (or 1.5 when it ships). And the further away we get from JDK 1.1, the less likely this is going to be the case.

For the most part, aside from their ubiquity, applets are a dead-end UI solution, and I suggest that you take a look at JNLP and Java Web Start (see the upcoming subsection) before falling back to applets. Applets are dead; let them rest in peace.

The URLClassLoader class

On top of all these options, there's always the classic roll-it-yourself approach. The java.net.URLClassLoader class allows code to be loaded across an HTTP (or FTP, or any other URLProtocolHandler-recognized protocol) link; thus, an end user can install a simple Java shim client that in turn pulls down the "real" application from the server:



public class RemoteLauncher
{
  public static void main(String[] args)
    throws Exception
  {
    // Construct the ClassLoader to pull the code across
    //
    URL[] urls = new URL[]
    {
      new URL("http://intranetserver/DeployedApps/HRApp.jar")
    };
    URLClassLoader urlcl = new URLClassLoader(urls);

    // Pull the main class across and launch it
    //
    Class mainClass =
      Class.forName("com.javageeks.HRApp.Main", true, urlcl);
    Method mainMethod =
      mainClass.getMethod("main",
                          new Class[] { args.getClass() } );
    mainMethod.invoke(null, new Object[] { args } );
  }
}

Numerous things could be done to make this launcher more generic—allow the name to be passed in via a command-line parameter, dynamically construct the URLs for the URLClassLoader, and so on—but this demonstrates the basic principle.

While simple, this approach does suffer a major drawback in that every class must be pulled across the network every time the application is executed, meaning this is really suitable only for clients with high-speed, high-bandwidth connections. For the most part, that pretty much means onsite clients behind the corporate firewall.

JNLP and Java Web Start

JNLP is a Java specification for delivering client-side Java code to the user's machine via an HTTP request. In many respects, it's the essence of the URLClassLoader example, but with an added benefit: once delivered, the code is stored on the local hard drive. From that point forward only updates are downloaded across the wire. JNLP provides the ability to download and install versions of the JDK onto the user's machine and supports side-by-side installations—JDK 1.3, 1.3.1, and 1.4 can all coexist without conflict. Sun provides a JNLP implementation as part of the J2SE installation, called Java Web Start. JNLP supports a more fine-grained security model than applets, although in its initial revision it supports only three security modes (in increasing order of capability): applet, J2EE client, and application.

A typical JNLP application is a Swing-based client, with all the richness and power of the Swing API available—tool bars, menu bars, theme support, switchable look-and-feels, and so on. JNLP also provides access to a number of underlying operating system capabilities, such as the clipboard, without requiring digital signatures. JNLP is also being considered as a candidate for future inclusion into J2EE, so it's not as far removed from J2EE as you might think.

Building a JNLP-based application isn't much different from building a standard Java application; create your user interface, typically a Swing-based application, in the usual fashion. Once the Swing user interface is complete, copy the .jar file to an HTTP-exposed location, so that users can reach it via an HTTP request from the browser.

At this point, the real development work is more or less finished; the last step is to create a .jnlp file, an XML file that contains information for Java Web Start about the application: where to find the .jar files that make up the application, what sort of security requirements the application has, and so forth. Although this is hardly the place to go into excruciating detail about the JNLP Specification, a simple JNLP descriptor file appears here:



<?xml version="2.0" encoding="utf-8"?>
<jnlp spec="1.0" version = "1.1"
  codebase="http://www.neward.net/ted/samples/"
  href="http://www.neward.net/ted/samples/Hello.jnlp">
  <information>
  <title>Hello World</title>
  <vendor>None</vendor>
  <offline-allowed/>
  </information>
  <resources>
  <j2se version="1.2+"/>
  <jar href="helloworld.jar"/>
  </resources>
  <application-desc main-class="Main">
    <argument>Hello</argument>
    <argument>World</argument>
  </application-desc>
</jnlp>

Put the .jnlp file into an HTTP-exposed location so that users can reach the .jnlp file directly from the browser.

Now, when a user wishes to use the application, point the browser to the .jnlp file, and if Web Start is already installed on the user's machine, the Web Start browser plug-in (registered to the x-jnlp MIME type) will kick off, parsing the downloaded .jnlp file and using that as a guide to download the .jar file, the version of the JDK required, any support libraries, and so on.

The JNLP Specification provides a number of APIs for accessing the client machine in a secure and safe manner, such as the clipboard or small amounts of drive storage, without having to digitally sign the .jar file downloaded to the client machine; see the JNLP Specification for more details.

JNLP isn't picture perfect, however. (Sigh. Nothing ever is.) Once again, like Flash, JNLP relies on a client-side installation to be present to make everything kick off correctly; in this case, the Java Web Start client (or equivalent JNLP client) needs to be installed and integrated with the browser, so it can recognize the application/jnlp MIME type and start up the necessary JNLP download magic. Unfortunately, unlike Flash, the Web Start client isn't even close to ubiquitous, and unless Sun somehow pulls a miracle out of its hat and negotiates a deal with Microsoft to include Web Start as part of the standard Windows installation foot print,[1] it's not likely to become ubiquitous any time soon. Again, like Flash, installing the Web Start client isn't a difficult task for those users who are already computer-inclined, but your average user, who's barely aware of the difference between the browser and the Internet as a whole, won't necessarily be comfortable doing so.

[1] This is a lot more likely now that the two firms have patched up their legal differences, but it would still require a serious round of negotiations.

Everything's a rich client?

Just to reiterate, however, the point of this item is not to suggest that use of a rich client is necessary for all scenarios but to suggest that for a certain collection of Web-centric applications, it is appropriate. HTML is, in many respects, the "lowest common denominator" UI technology for the Web, and there's no reason that applications, particularly those being deployed to a bound set of users (such as those within an intranet), should have to suffer from its limitations.

In the long and short of things, JNLP probably works best in an intranet environment within a company, whereas Flash probably works better for Internet-wide applications. The URLClassLoader approach is probably best used "under the covers" for rapidly changing components as part of a larger server-side (potentially clustered) system, not generally something that the average J2EE application will need. Applets are, of course, dead and should be left that way.

In the meantime, however, several commercial products are also exploring this space, and it's worth a look to see if they will fit your particular application needs. Droplets, Thinlets, Curl, Sash, and several others are already available, and more are sure to come as developers wrestle with the idea of exactly where they want to be on the UI continuum. The important thing is to recognize that this isn't a binary thin-client/fat-client decision and to pick your spot on the continuum as appropriate to your project.