Welcome!

AJAX & REA Authors: John Funnell, Bob Little, Kevin Hoffman, Maureen O'Gara, Onkar Singh

Related Topics: AJAX & REA

AJAX & REA: Article

Real-World AJAX Book Preview: Server Side - Controller Servlet

Real-World AJAX Book Preview: Server Side - Controller Servlet

This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs for the special pre-order price, click here for more information. Aimed at everyone from enterprise developers to self-taught scripters, Real-World AJAX: Secrets of the Masters is the perfect book for anyone who wants to start developing AJAX applications.

Server Side - Controller Servlet
The controller servlet orchestrates interaction between the client- and server-side components that serve as the real data sources or service providers. The client uses XML messages to send details of server invocations. The controller servlet interprets the XML messages and delegates calls to actual services. It might have to transform these XML messages to different protocols based on what's supported by each service. It may use a set of existing libraries or middleware to do so. In the reverse direction, the controller servlet gets data from the server-side components, converts them to XML, and sends them back to the client. We'll discuss XML message formats in the subsequent sections.

We chose to route all our calls through a servlet controller, one or more instance of it, because:

  1. It enables prototyping and development of a real UI without first implementing real services and data sources. XML files can be used as data sources and the services can be mocked up using simple code written in Java, C, C#, or a scripting language such as Python.
  2. Development using XML files as data sources and mocked-up services not only delivers early demos to the end user for feedback, it helps in firming up the contract between the server components and the UI.
  3. The controller servlet provides an abstraction for server-side tiers, allowing the client and the server implementation to change independently of each other.
  4. The server-side team doesn't need a real UI for testing its implementation. It can simply use a browser to test the flow of messages.
  5. In the production application, the controller servlet can act as an extra layer of security.
In a nutshell, this is the much touted service-oriented architecture (SOA).

Client Side
At a high level, the client side consists of a bunch of HTML pages and JavaScript code embedded in those pages or loaded from files. The main point of this chapter is to discuss how to structure the HTML pages and JavaScript to build a UI for complex business scenarios. We'll answer questions such as: What different patterns are followed? How do the various pages interact? What is the lifecycle of a page? What is the static part of a page and what is a dynamic part? What are the various techniques for handling the dynamic part? How is a domain modeled and how is the application data consumed by the client? What are the various techniques to integrate a designer's or artist's work? How to make the entire process repeatable and scalable? Once again, we'll discuss some of these points at a high level first and then go deeper as the chapter progresses.

  • At a top level, the client-side components can be kept to three buckets using the classical Model-View-Controller (MVC) pattern. MVC, in the context of an AJAX UI, is shown in the Figure 5.2 and detailed in the following sections. You should notice that the Model and Controller have counterparts on the server side, whereas the View is eliminated from the server side in an AJAX-based UI. The server-side controller primarily handles high-level application messages between the server components and the client. It's freed from handling events that are generated by the user interface such as a mouse click. The client-side controller handles these events. This makes the UI responsive and rich. Not only that, but the division of responsibility makes the UI architecture flexible and modular.

    Model
    Model represents the application data, the structure of the data, and the services that can be performed on the data. In other words, it's a description of the domain. For an AJAX UI, the important pieces of information to be modeled are:

    1. The messages between the server and client
    2. The client-side data model
    Each of these is either a subset of the domain model on the server side or the whole of it. The Unified Modeling Language (UML) is popular for modeling a domain. And we can continue to use UML for modeling data for the AJAX UI. The application data modeled using UML can be easily represented as XML, a JavaScript object or JavaScript Object Notation (JSON). Let's use the term "dataset" to define the data exchanged between the server and client or used by the client. A dataset is typically one of the following types:
    • An object, example, or customer record
    • A list of objects of same the type or example, a list of customers
    • A tree of interrelated objects or examples, a customer, pointing to list of orders, each order containing a list of line items
    • A list of root nodes of object trees
    Client-side modeling is best handled depending on the UI scenario. Scenarios involving a single object instance or list of objects are easier to handle and are well understood. An example is a list of customers or a customer detail form. But a typical UI scenario always has to deal with a tree of interrelated objects. For example, an order form might have a list of items ordered, the shipping address, and the billing address. These are typically modeled as Order class; LineItem, and Address classes associated with the Order class as shown in Figure 5.3.

    A tree represents objects in a relationship such as the one discussed earlier. The root node of the tree is the top-level object. It might have scalar attributes (attributes of basic types), array attributes, objects as attributes, and lists of objects as attributes. In UML, an object as an attribute represents a one-to-one association. A list of objects as an attribute represents a one-to-many relation. In XML, the tree can be represented using nested elements where the attributes of the element can also specify properties such as class and object identifier. Each scalar attribute can either be represented as a nested XML element or the element's attribute. Related objects are represented using nested elements. The same tree can be represented using JSON. At runtime, in the client space, this tree can be represented as a tree of JavaScript objects. JavaScript, being an interpreted language, doesn't require an upfront declaration of classes and provides a very flexible notation for addressing parts of objects constructed from the XML. The objects and attributes can be accessed using conventional dot notation. All this helps in building a flexible and dynamic UI.

    Let's consider the example below to illustrate the modeling aspects completely. An XML representation of a hypothetical list of customers is given, where each customer contains a list of orders.

    Listing 5.1 - Customer List in XML Form

    <CustomerList>
       <customer id="00001">
         <name>ABC Inc</name>
         <phone>123-234-3456</phone>
         <orderlist>
           <order id="1">
             <description>Pens</description>
             <qty>300</qty>
           </order>
           <order id="2">
             <description>Pencils</description>
             <qty>400</qty>
           </order>
         <orderlist>
       <customer>
       <customer id="00002">
         <name>Doe Inc</name>
         <phone>789-345-9876</phone>
         <orderlist>
           <order id="1">
             <description>Notebooks</description>
             <qty>700</qty>
           </order>
           <order id="2">
             <description>Folders</description>
             <qty>100</qty>
           </order>
           <orderlist>
       <customer>
    <CustomerList>

    The XML above represents a dataset called CustomerList. It's a list of two customer objects. Each customer contains a list of two orders. XML can be represented by instances of JavaScript objects that form a tree. The in-memory representation of the corresponding JavaScript objects is shown in Figure 5.4.

    The equivalent code that constructs a JavaScript objects tree from the XML is shown in Listing 5.2. Note that this is only "equivalent code." In reality, an XML parser is used to construct the tree.

    Listing 5.2 - Code to Build JavaScript Objects Tree

    var customerList = new Array();
    var customer = new Object();
    customer.name = 'ABC Inc';
    customer.phone = '123-234-3456';
    var orderList = new Array();
    var order = new Object();
    order.id = '1';
    order.description = 'Pens';
    order.qty = 300;
    orderList.push(order);
    order = new Object();
    order.id = '2';
    order.description = 'Pencils';
    order.qty = 400;
    orderList.push(order);
    customer.orderlist = orderList;

    customerList.push(customer);

    // similar code will be executed for the second customer and so on.

    // the resulting 'customerList' is a list of Object trees that will be

    // used by the client.

    To summarize, UI scenarios can be modeled using UML and the data can be represented using XML, JSON, or JavaScript. One form of the representation can be transformed to another. XML or JSON can be used for the information exchange between the server and client. JavaScript is used for in-memory representation of the information in the client space. JavaScript allows dynamic creation of such a tree at runtime and provides convenient notation to address the nodes of the tree. We didn't cover JSON in our discussion but it is a notation similar to C-language structure. More information on JSON is available at www.json.org/.

    Next let's discuss certain aspects of the model that are useful for information exchange and data integrity.

    Object Identifier
    For information exchange between the server and the client, each dataset and object within has to be uniquely identified.

    A dataset can be uniquely identified by its "name" or "ID." For example, in the case above "CustomerList" might be a unique name of the data. The client sends a message to the server, which means "get CustomerList." The server responds with the above XML. Another message can be "get NewCustomerList" and the server may respond with a subset of the CustomerList. In this case, "NewCustomerList" might be used as the name of the dataset.

    An object inside a dataset can be identified by an identifier and its position in the dataset. For example, 1st order of 1st customer, 1st order of 2nd customer, and so on. Here each "order" object might not have a unique identifier. Two orders may be called 1st, meaning that each has an id=1st. Together with its position in the hierarchy each is uniquely identified. This is the same as the XPATH in the XML domain or the dot notation of JavaScript. In this scheme, each object is identified relative to its ancestors. We can say that they have "relatively distinguished names." The top-level object is identified by the dataset name, or it can have a globally unique identifier within its domain. When a client or server sends information about an object, the message is constructed so that it identifies the object. For example, a message informing the new quantity for the 2nd order of the 1st customer will be:

    <customer id="00001">
       <order id="2">
         <qty>400</qty>
       </order>
    </customer>

    Client Data Cache
    We've discussed the modeling of data and how to identify data. In a typical UI there will be a wide variety of data flowing between the server and client. The next question is how we track and manage this information in a client. Since the dataset can be identified uniquely, a singleton cache or repository of data can be built on the client side. Model, View, and Controller code can refer to the data in this cache by fully qualified names. For example, a view can use a fully qualified name for the data binding with a form or table view.

    The primary purpose of the local cache is to provide a name space for data access. Assuming that a common reference is maintained across the different parts of the view, it's easy to reflect the changes made in one place at the other places. The secondary purpose is to improve the user experience during an interaction. For example, if the user goes back and forth between views, the UI can be made responsive by returning data from the local cache. We don't expect that local caching introduces any cache coherency or concurrency issues. It's more of a design concept on the client side. The concurrency issues are the same as getting an HTML page with embedded data in it using JSP/ASP or any other server-side technology.

    Immutable References
    On the client side, an XML node or JavaScript object refers to a business object. It's likely that the values from the same object are displayed at multiple places in a UI. One example is a list-detail view, where details about a selected object in the list are displayed in a form on the same page. In such a case, care should be taken to use the same object by reference everywhere. Special care should be taken not to replace it with a new reference when the user makes changes. Similarly, list-references should be preserved for collection-type data. For example, in the XML earlier if an order is deleted from the list of orders, it should be ensured that no new reference is created for the list. Instead the same list (or JavaScript array) is trimmed. In this case the deleted order is mutated, but the reference to its collection from the parent is intact. If this guideline is followed correctly, UI change propagation becomes easy to implement. Similarly, the change set can be easily computed. There's nothing new about it. It's a reminder to ensure the referential integrity of the data. This aspect is sometimes overlooked on the client side.

    This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs, click here to order.

  • More Stories By Anil Sharma

    Anil Sharma is a founder of Vertex Logic and architect of its AjaxFace product. He is working with Vertex Logic's customers and helping them deploy WEB 2.0 applications built using AjaxFace. These applications are in the areas of online printing, community WEB sites and social networking. He is driving future products of Vertex Logic. Prior to Vertex Logic, he was CTO and founder of Softrock Systems and Component Plus. There he built a model driven application platform using J2EE. His primary interests include user interface infrastructures and model driven applications. He is one of the contributors of the book "Real World AJAX - Secrets of the Master".

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.