Client Architecture Discussion

Note: This page is related to fixed pages in the application.

The web browser client communicates with the Web Application Server via HTTP, and receives two kinds of dynamic content:

  • Views - HTML entities that describe how things look

  • Model - Pure data in a convenient representation

The views are served as HTML that contain labels and HTML <SELECT> elements (drop-downs) that are localized to the user's language. Since drop-downs are fairly static, the view objects are cached on the browser via the HTTP 1.1 Cache-Control directive in order to avoid repeatedly accessing the Web Application Server for the same content.

The web server creates HTML using XSLT technology. The technique is as follows: the original metadata that defines HTML documents is copied from the database into XML files residing in the server. These files are shipped as part of a OUAF system deployment. At runtime the server converts these UI metadata documents into HTML in two steps. First, the logical structure is converted into a nearly-final HTML structure, lacking only language-specific information (labels and <select> lists), via XSLT, using one of a handful of standard XSLT template files. The result object is then transformed again, in order to inject language-specfic elements, creating the final HTML.

As a special case, for performance reasons the HTML for grids (lists and search windows) is created using client-side XSLT (MSXML).

Data is provided via servlets, of which there are only a few. The data is represented as literal JavaScript, which happens to be very convenient to handle by the browser (since it includes a native JavaScript parser). The model takes the form of a "tree" of JavaScript object nodes and values, with a distinguished root node. The model is converted into an XML document string when submitted to the server, using the HTTP POST method. This is convenient for the Web Application Server because it is equipped with powerful Java-based XML parsers.

Here is a table of servlets, and a brief description of each:

Servlet Name

HTTP Method

Usage

loginInfo

GET

Provides useful global data at login, retained for life of session, such as a map of all system URLs and a definition of menu structures.

pageRead

GET

Returns a data model object given one or more key/value pairs.

pageChange

POST

Accepts a data model representing modifications that should take place against an existing database entity, returns modified model.

pageAdd

POST

Accepts a data model representing a new entity that should be inserted into the database, returns new model.

pageDefault

POST

Accepts a data model describing a triggered "default" operation, returns a model object containing default values.

pageDelete

POST

Accepts a data model representing a database entity to be deleted, returns nothing.

pageCopy

POST

Accepts a data model representing a model that should be duplicated, returns the duplicate.

listRead

GET

Accepts key/value pairs describing a list of database entities, returns said list.

Search

GET

Accepts key/value pairs containing search criteria, returns list of objects satisfying said criteria.

StringSort

POST

Allows locale-sensitive sorting of strings. Used for sorting strings in grids when user clicks on the column header.

It is important to remember that the servlets deal with "pure" model data, and have no visible representation. Since actual business logic and database access resides in the app server, the servlets take the role of dispatchers and most servlets accept a "service" parameter describing which app server back-end service to invoke.

The model data is combined with the view on the browser client whenever the model changes or the view needs to be refreshed. This is done by a name-matching scheme where every HTML element that shows a model value has a name that "picks out" a corresponding value from the current model. All such HTML fields must include the string "data" in their HTML class.

The simplest case is showing a value from the "root" object, in which case the field name, also referred to as the "JS name" simply matches the model's attribute name.

There is more complexity in the case of lists. Every list in the model has a unique name, regardless of nesting depth, so a JS name that combines the list name with the property name suffices to uniquely identify a section of the model.

There are two sub cases of displaying properties of lists. The first is where the desired index into the list is known (e.g. grids). In this case, the JS name combines the list name, index, and property name as follows: <LIST_​NAME>:POSITION$ELEMENT_​PROPERTY, e.g. ACCTS:3$ACCT_​ID. Note indexes are always 0-based in the browser (in accordance with JavaScript arrays). This example refers to the fourth element of the ACCTS list, and retrieves the ACCT_​ID.

The other case is where the desired index is inferred as the "current" index (e.g. scrolls). Every list in the model keeps track of its current position index, which is used when no external index is provided. Hence the JS name ACCTS$ACCT_​ID refers to the ACCT_​ID property of the currently selected/visible element (presumably in a scroll) of the ACCTS list.

In the rare case that header fields should be displayed, they can be accessed using the JS name pattern LIST_​NAME#HEADER_​PROPERTY.

Generally, whenever a value is changed in an HTML element or focus is moved after making a change, the system attempts to "commit" the change back to the model. This involves several steps:

  • Validating the input for syntax, possibly according to the current locale (e.g. dates)

  • Identifying the relevant model node to receive the change

  • Updating the node

  • Marking the node dirty

The last step is important because we wish to know whether the user has made any changes to the model.

Saving changes to the server generally involves the following steps:

Identifying the servlet to be invoked (e.g. pageChange vs. pageAdd) depending on whether the model represents a new or already persistent entity.

Converting the model tree into a literal XML string representation.

Submitting the XML string to the Web Application Server via the appropriate servlet using the POST method, including a parameter describing the service. This is accomplished via the Internet Explorer XMLHTTP ActiveX object, using a synchronous calling mechanism.

The servlet, constituting a core piece of the Web Application Server "web presentation" layer, retrieves the service parameter, obtains the XML-based metainfo describing the service, and converts the XML request string into a Java object tree, ready to be passed to the "data service" layer.

The data service layer converts the Java object tree into a Jolt data buffer.

The relevant app service is invoked passing in the data buffer.

The result buffer is converted into a Java object tree.

The Java object tree is converted into a literal JavaScript representation (as needed) and transmitted to the browser.

The returned data (literal JavaScript) is mapped into a new live JavaScript object model.

The user interface is refreshed with the new data.

The portal screens use zone configuration to create HTML. Each distinct zone within the portal is created by a Java object known as a zone type. The zone type is responsible for acquiring data and rendering the displayed HTML. The portal framework takes care of common features such as zone expand/collapse.