Revasoft Revasoft Banner
HomeOur ExpertiseOur ServicesOUR ProductsAbout UsCareersContactsupport
Print this page Architecture Overview
Motivation and Overview
Class Overview
Model-based Widgets
Optimizing Server Round-Trips

Motivation and Overview

ULC stands for Ultra Light Client (ULC). It is an architecture that supports the deployment of applications with very light weight clients. It thereby enables centralization of system maintenance and administration, decreasing the cost of desktop management.

The principal idea is to run applications on a centrally controlled application server. Only the presentation part of an application is run on the client's desktop. The presentation part is implemented by a universal user interface engine (UI Engine). The following diagram illustrates how the ULC architecture partitions an application.

ULC Application Client-Server Partitioning

Figure 1: ULC Application Client-Server Partitioning

All that runs on the client is the UI Engine which can be used universally from various ULC applications. Since no application specific code is executed on the client there is no need for application specific administration of the desktop machine.

An application communicates with the UI Engine through a high level user interface protocol. This protocol is designed to scale down to low bandwidth thin pipe communication links. The ULC application developer is shielded from this protocol with a special toolkit that takes care of the distribution. In other words application developers don't have to be aware that they are developing a distributed application. All distribution is handled behind the scenes. To visually construct user interfaces ULC leverages the existing VisualAge Composition Editor.

ULC is intended to be run as an integrated part of a Web browser. The UI Engine can be run either as an applet inside the browser or as an external helper application.

In contrast to classical Web applications based on the Hyper Text Markup Language (HTML) ULC developers don't have to deal with dynamic HTML page generation and server extension mechanisms like CGI. ULC applications are developed with conventional programming languages like Java and Smalltalk. Heterogeneous technologies (HTML, Plugins, Java, and JavaScript) are neither required on the client, nor on the server. This improves both robustness as well as ease of development. In addition, user interfaces are not constrained by HTML. HTML was designed as a document markup language and not as a means to describe an application's user interface.



ULC is a client/server architecture: applications(i.e. clients) connect to a server which implements the user interfacefor them (see Figure 2). Because this UI server runs on the end user's PC or workstation (which is typically called "desktop") and the applications (clients) run on some application server the terms client/server are quite confusing (Note: this paradox is identical to X11, where the X11 server is the user's desktop and X11 applications run on an application server.) Therefore we will try to avoid the terms client and server altogether and always call the User interface portion as the "UI Engine" and the client as "application." or ULC application.

 UI Engine in Server Mode

Figure 2: UI Engine in Server Mode

The above architecture is based on the assumption that the UI Engine is running as a server process and that different applications connect to that server. Under this setup an application can only serve a single end user. In order to support multiple UI Engines from one application server the ULC architecture supports a server mode for applications as well. (see Figure 3).

UI Engine in Client Mode

Figure 3: UI Engine in Client Mode

Figure 3 shows two UI Engines talking to two application threads inside a single Application Server.It is obvious that the architecture is very similar to the one depicted in Figure 2. The most important difference is that the application code runs in parallel inside a single address space. Therefore synchronization problems have to be addressed by protecting your data from concurrent access.

The resulting symmetry of the ULC architecture is reflected in the command line arguments of the UI Engine and the applications. To run the UI Engine or application in server mode a port argument has to be supplied. For running in client mode a tcp/ip address and an optional port are required. In addition to running multiple instances of an application it is possible to run instances of multiple applications inside a single application server. In this case an additional name can be used to select an application. As a convenient means to specify address, port, and application name as a single argument the well known URL format is employed.


The following table gives an overview of the possible options(Note: the non-standard protocol name of the URL is "ulc").

Figure 4: Table of possible options

Building ULC applications requires a special set of objects or widgets. These widgets have an API and functional behaviour which is not different from "normal" widgets sets but they completely lack a user interface. These widgets can talk to a corresponding "real" widget in the UI Engine by a socket-based communication mechanism. They act as a proxy to the real widget.

Because every widget is split into an API and a real user interface element we call the widgets on both sides "half objects", where the application half is the "faceless half" and the UI half is the "UI half" (see Figure 4).

Half Objects

Figure 5: Half Objects

Applications communicate with the UI Engine via the "Half Object Protocol" which consists of requests, events, and callbacks. The application sends requests to the UI Engine. User interaction typically results in some low level events ("mouse click") which are handled by the UI Engine first and then converted into a semantic event ("execute action") which is passed back to the application. These events are typically used to synchronise the other half of the object and then to trigger some application specific action. If the UI Engine needs some data from the application's half object it sends a callback. Callbacks are identical to normal requests but their direction is reversed.

Half objects form a hierarchy: at the root is an Application object which provides methods for manipulating the global state of the application (terminating etc.) and maintaining a list of windows or "Shells." A Shell represents a top-level window with an optional menubar (a tree of menus with menu items) and a content area. The content area is a tree of composite widgets. Composite widgets form the inner nodes of the tree and implement the layout. Simple widgets are the leaves of the tree. Figure 5 shows a part of the tree from the sample application Dossier. A more detailed description of the objects used is here.

Half Object Tree of Dossier Example

Figure 6: Half Object Tree of Dossier Example

Maintaining state across this half object split is a tricky business. You don't want to render the application unusable just because there was a communication problem or your client machine crashed. Therefore the UI Engine is "conceptually stateless", that is all state is kept in the application. Of course, some state is held in the UI Engine too (e.g. the widget hierarchy) but only as a type of cache. It is always possible to clear that cache (for instance by killing the UI Engine) and re-transmitting all information from the application to the UI Engine.

This functionality has a major impact on the communication philosophy between half objects. Methods of the faceless half objects typically modify some state on their half and then try to synchronise their half with the UI half. If there is no UI half (e.g. because the communication timed out or the UI Engine is down), the synchronise step will be a no-op but the faceless half will be in a consistent state. If the UI Engine comes back later the application reconnects to it and synchronizes to the current state.

ULC is designed to scale down to thin pipe connections.Therefore network latency and network bandwidth influences some design decisions. Communication between both half objects has to be minimized and requests should always be batched together as a single message to avoid a sluggish user interface. ULC minimizes communication overhead by only transmitting presentation data which is visible (e.g. just the visible 10 rows in a table with 10000 rows) or where chances are high that it will become visible soon (e.g. the next 10 rows in that table).

To address high latency environments ULC has to batch single requests. But batching is only possible if requests are mostly asynchronous, that is, if they don't require an immediate answer and don't block the sender. As a consequence communication between the application and the UI Engine is mostly asynchronous. For example if the UI Engine has to draw a table it sends a request back to the application to request the data for the visible part of the table. The engine doesn't expect to get the requested data immediately and draws a placeholder instead. Because it doesn't wait for the data to arrive the UI Engine doesn't block and remains responsive. Depending on the network latency and application responsiveness the requested data will asynchronously arrive sometime later and will replace the placeholder data.


Class Overview

The ULC classes fall into the following five categories:

  1. Resources
    are all objects which are not user interface elements themselves but are used to configure these elements and therefore should live in the UI Engine as well as the application. Examples are fonts, bitmaps, images, and cursors.
  2. Widgets
    are all kinds of user interface elements ranging from simple ones like buttons, labels, editable fields, menus and menu items to more complex ones like one-dimensional scrolling lists and two dimensional tables.
  3. Layout
    Widgets in this category are composite widgets implementing a specific layout policy for their children.
  4. Shells
    Shells are the top level widgets forming the root of every widget tree. A shell is typically represented as a modal or non-modal window and optionally has a menu bar. The shell controls the collaboration of these elements. Examples for shells are the "standard" Shell, Dialogues, Alertsand the root shell ("Application") which manages the overall application.
  5. Models
    This category contains classes which can be used as a data source for some of the widgets from the Widget category above. Models are identical to the models of the MVC paradigm and widgets represent the view and controller components.


Model Based Widget

Most ULC widgets from the widget category support two different APIs. The first API assumes that every widget has a built-in model and provides an API for accessing and changing the model (see Figure 6). For example a Field has a text model and methods setText and getText. In addition the widget provides methods for specifying the visual appearance of the user interface element, e.g. what font to use or how many characters to display.

Widgets with
Built-in Model

Figure 7: Widgets with built-in model

The second API uses an external model which is a separate object (Figure 7) and can be shared between different widgets (multiple views of the same object).

Widget with
External Model

Figure 8: Widget with external model

Under this paradigm the application typically creates and configures both the model and the widget and then forgets about the widget. Whenever the application has to update data presented in the UI Engine it talks to the model. When the application wants to retrieve changed data it asks the model for it, not the widget.

An example for this API is the Table widget and the TableModel (in fact the Table widget doesn't have a built-in model and only supports the model-based API). The TableModel implements a two dimensional data structure with rows and columns. The UI Engine half of the object contains a cache so that data access requests of the Table widget can be fulfilled immediately. If the cache doesn't contain valid data the TableModel returns place holders and asynchronously requests new data from the application half object. When this data arrives the dependant widgets are notified and updated.

The update policy used between the two halves of the TableModel is configurable. One synchronisation policy optimizes communication for low bandwidth, low latency connections by reducing the amount of data transmitted. Another policy for high bandwidth, high latency reduces the number of requests going back and forth but doesn't minimise the size of the data transmitted.

The FormModel is another example for the model based API. A FormModel represents a set of named and typed attributes, similar to a heterogeneous dictionary. Most ULC widgets from category 2 can be initialized with a FormModel and an attribute name. Fields can be used on string atributes, CheckBoxes on boolean attributes and groups of RadioButtons on enumeration type attributes. These widgets will ignore their built-in model but will track changes and allow updates of the named attributes of the specified FormModel.

Similar to the TableModel different synchronisation policies can accommodate different network characteristics. One policy updates the application half of the FormModel on every attribute change. Another policy collects all changes and sends them back to the application in a single call back only on explicit request.


Optimizing Round Trips

In order to reduce the number of round trips between the UI Engine and the application ULC provides built-in mechanisms for the following commonly used functionalities:

  • Enabling and Disabling
    Special conditions on some widgets can be used to enable/disable other widgets without any communication between the UI Engine and application. Examples are empty/non-empty Fields, empty/non-empty selections in List and Table widgets.
  • Validation
    Predefined Validator and Formatter objects can be attached to some Widgets in order to perform validations like range checking and syntax checking without any communication between the UI Engine and the application. This is especially useful in FormModel based widgets, where changes are not transmitted immediately but batched.
  • Optional Events
    From R1.3 onwards events that are deemed optional are sent to the application only if there is a registered handler for the event.



Because the implementation of the UI Engine can be based on different widget sets, different look-and-feels, and different fonts, the layout specification attempts to be visually appealing in different environments. Explicit placement of widgets doesn't work very well in this situation because the widget's sizes are not known in advance. Moreover, the precise horizontal and vertical alignment of widgets and the specification of the resize behaviour is a tedious task even with the help of the Composition Editor. This led to the integration of layout management in ULC, based on a hierarchical and high level layout description rather than on the explicit placement of widgets, and which handles resize behaviour automatically.


Here is a more detailed description of the available layout widgets and how to use them.


Back to Products Print this page Back to ULC Demo
Getting Started
Release Notes
Running the Samples
Architecture Overview
Internal Architecture
Using Layout
UI Engine Extensions
Web Integration
Bringing the Advantage of Thin Client Computing to JAVA
The ULC Tour

top of page
Home | Our Expertise | Our Services | Our Products | About Us | Careers | Contact Us | Support
ULC Demo | ULC Tour | ULC R4.0 | Download | FAQ

 © Copyright 2001 Revasoft Private Limited.