| By Anil Gurnani Published by Addison-Wesley Professional ISBN-10: 0-321-56329-8 ISBN-13: 978-0-321-56329-3 |
This chapter is an excerpt from, Web Development with TIBCO General Interface: Building AJAX Clients for Enterprise SOA, authored by Anil Gurnani, published in the Addison-Wesley Professional Developer’s Library, ISBN 0321563298, Feb. 2009, Copyright 2009 Pearson Education, Inc. For more info please visit informIT and Safari Books Online subscribers can access the book here: http://techbus.safaribooksonline.com/9780321563293..
This chapter provides a high-level architecture of TIBCO General Interface and its framework components and describes how General Interface applications work in the browser.
One of the strengths of General Interface is its capability to work with XML and XSL. All widgets use XML/XSL to render the component onscreen. JavaScript is used for handling user actions. This strategy helps General Interface applications run faster than JavaScript code in the browser because the XSL processor used by the browser runs at high speeds, whereas the JavaScript processor runs outside the browser and must first be compiled every time and then executed. Additionally, GI Builder—the interactive development environment (IDE) that's included with TIBCO General Interface—makes it possible to visually build prototypes very quickly using more than 100 ready-to-use widgets from a component palette.
Applications that are built with General Interface should take advantage of General Interface's architecture for best performance. It is possible to build applications entirely in JavaScript using the framework APIs; however, the performance of JavaScript is about 10 times slower than that of XML/XSL processing. Therefore, it is important to understand how General Interface works and exploit it in building applications to get the highest levels of performance. General Interface's architecture includes many ways to use XSL processing to improve performance. TIBCO General Interface's JavaScript framework includes numerous classes and methods to load, cache, and parse XML documents as well as transform documents using XSL style sheets at runtime.
Model View Controller Architecture
Model-View-Controller (MVC) is a proven pattern for building graphical user interfaces since Smalltalk-80. GUI frameworks, such as Microsoft Foundation Classes (MFC), Java Swing, WinForms, and Struts for Java-based web applications, all use the MVC pattern. This pattern offers some key benefits to GUI developers: First, it modularizes the code and breaks a large problem down to many smaller ones and allows for faster team development. It also makes the code much more maintainable because each part of the code is dealing with its own set of variables and behaviors. One of the most important advantages of using MVC for GUI frameworks is that it makes the framework easily expandable and customizable. For example, it becomes possible to extend a View class to create a customized view. Multiple views can be attached to a single model if needed. Views can also use the observer pattern to update themselves when the model changes.
In an MVC pattern, three primary classes are involved: a Model class that owns the internal state of the data that drives the view, a View class that owns what is displayed on the screen and has direct access to make changes to it, and a Controller class that orchestrates user actions. When a user clicks a button, it is first felt by the corresponding View class. It then immediately passes it along with any parameters necessary to the Controller class. Logic to handle this click is in the Controller class, which performs the necessary steps and updates the Model class if necessary. The Model class then notifies the View class that something has changed, and the View class then picks up the new data and updates the display accordingly.
This architecture opens up the possibility for actions coming from anywhere—for example, a back-end process could invoke an action on the Controller to deliver a message that needs to be displayed to the user. Multiple different View classes can be associated with the same model to display the data in a different representation. For example, a Model class that represents tabular data could be displayed via two independent views—one that shows a grid onscreen and another that shows a chart from the same data. Figure 2.1 shows a high-level representation of the MVC pattern in use.
Figure 2.1
High-level representation of MVC.
All controls and widgets in General Interface use XML as data and are driven by a combination of XSL style sheets and JavaScript code. General Interface defines a format called the 'Common Data Format,' or CDF, which is a form of XML. General Interface also includes a large collection of XSL style sheets that transform the backing CDF into HTML elements such as grids, lists, and menus. JavaScript code that orchestrates the behavior of the widgets is structured in packages, classes, and interfaces. General Interface follows a style similar to the Prototype framework for JavaScript code to define interfaces and classes that support object-oriented concepts of inheritance, polymorphism, and encapsulation. This style makes JavaScript code look almost like Java code. However, keep in mind that JavaScript is not a true object-oriented language, and therefore not all the features of a modern language such as Java or C# are available to developers.
General Interface Application Life Cycle
A General Interface application begins by executing some JavaScript code that can be called the boot loader. In the General Interface package is a JavaScript file, JSX30.js, that contains the functions to bootstrap a General Interface application and begin running it. The Deployment utility generates the code to load this file using HTTP protocol with the appropriate parameters for the application. As the HTML page that contains the General Interface application is loaded by the browser, a call to JSX30.js is made, and it begins to load the application.
The first file that is loaded for any application is the config.xml file, which defines application files and various properties. Among other things, config.xml has a list of JavaScript files that begin to be loaded into browser memory. In the file config.xml is a reference to a file that defines the startup screen. The startup screen definition is also an XML file that contains the layout of the General Interface application as well as controls and widgets and/or subcomponents within it.
At this point, an instance is created of the global Application Controller, which is the main orchestrator for the application being loaded. It serves as the global context and contains all other widgets and controls for the application. Figure 2.2 shows the typical life cycle of a General Interface application.
Figure 2.2
General Interface application life cycle.
General Interface supports a dynamic class loader, which loads only the JavaScript and XML files that are needed. This allows you to modularize your application to make sure it is responsive and does not have to download large files. Only the files needed for the opening screen are loaded, and instances of the startup screen and the controls in it are created and rendered; next, the execution control is passed on to the user, who then drives the application. Additional JavaScript and XML/XSL files are loaded and processed as needed.
Components such as dialogs and other controls contained within those dialogs do not need to be loaded initially. The General Interface framework provides methods to dynamically insert these components into the Application Object Model as needed. For example, when the user clicks the Save button, the application can call a method to display the Save dialog, which is defined in a separate XML file. This component XML file is loaded by General Interface into memory. After the file is loaded, General Interface instantiates JavaScript classes that are referenced in that file, and then it inserts the new component into the Application Object Model hierarchy and renders it onscreen. When the dialog is closed, it is removed from the Application Object Model. After they are downloaded, the components can be cached in the browser memory so that another fetch will not be required when this component is needed again.
General Interface also includes a utility to compress and obfuscate JavaScript files. In a nutshell, this utility takes in a number of JavaScript files and combines them into a single JavaScript file. It also changes the names of variables and methods to use as few characters as possible to reduce the size of the resulting JavaScript file. This is in direct contrast to the concept of dynamic class loading. Application developers have to analyze and understand the impacts of each strategy and adopt one that suits their requirements and environment. For very large applications, it is possible to use a hybrid approach, where classes are grouped into a few key groups and compressed using a merge utility into a few separate files that are loaded dynamically on demand.
Application Object Model
General Interface defines screens and controls at a higher level of abstraction than that of the HTML Document Object Model. This model, called the Application Object Model (AOM), maps to the native browser's DOM. This enables General Interface applications to run in any browser where General Interface's AOM is implemented. Figure 2.3 shows a designer view of application canvas for a sample application in TIBCO General Interface, and Figure 2.4 shows the XML definition of the same appCanvas.
Figure 2.3
Application canvas in Design view.
Figure 2.4
Application canvas in XML view.
As you can see, every element's properties are defined in XML, and it is associated with a JavaScript class. As the General Interface controller loads the components, it creates an instance of the associated JavaScript class to handle events and behaviors for the component. This provides a great degree of encapsulation for classes and widgets. It is possible to make use of the familiar concepts of object-oriented programming to extend built-in widgets (or create new ones). As you build your canvas in GI Builder, it builds this file, and you can view a user-friendly representation of this file in the Component Hierarchy quadrant in the GI Builder.
Common Data Format
As stated earlier, all General Interface controls and widgets that consume data are driven by a backing XML model. The data must be in a format known as 'Common Data Format,' or CDF. CDF is a very simple format that defines a few key elements and leaves the attribute space open. Attributes are mapped to data elements in controls. The main advantage of CDF is that it can drive any widget in TIBCO General Interface, which makes it possible to have the same backing CDF for a grid as well as a chart. The Model part of the MVC pattern in General Interface can be thought of as a CDF in TIBCO General Interface.
JavaScript Object Notation (JSON) is a simple format for accessing and manipulating object properties. It is based on a subset of JavaScript Programming Language Standard, but is text based and is therefore language neutral. Because it is based on the JavaScript standard, it is inherently supported by TIBCO General Interface.
CDF Format also makes it very easy to manipulate the associated objects using a JSON paradigm. Each node in a CDF can be thought of as a JSON object where XML attributes map to JSON properties. It is possible, then, to use XSL/XPATH to manipulate this CDF when using an XSL style sheet, and at the same time, it's possible to update the fields using JSON syntax (for example, obj.property = x). Because TIBCO General Interface combines JavaScript and XML, this becomes a key convenience when dealing with the data structures in TIBCO General Interface applications.
JavaScript Framework
Prototype framework version 1.5 was released in January 2007 and introduced the concepts of object-oriented programming to JavaScript. Prototype framework started out as a small set of functions written in JavaScript to make it easy for developers to write modular code in JavaScript.
Object-oriented programming has been very successful in the rest of the development world, but the JavaScript language does not inherently support the concept of classes, interfaces, inheritance, and polymorphism. JavaScript does, however, have the capability to create objects that may have properties, and it does support the concept of a function pointer. So a clever group of people used those features as building blocks to create a framework in JavaScript that allows developers to use object-oriented concepts to write JavaScript code. For example, you could create a class called Button and have a method in it called click()
, and extend the class to create other types of buttons, such as ImageButton
, RollOverImageButton
, and so on.
The Prototype framework consists of a single JavaScript file that defines various functions that can be used to define custom classes. The Prototype framework now includes support for AJAX by providing some classes to wrap an AJAX request and response object. Figure 2.5 shows the documentation page for General Interface's JavaScript framework, which is loosely based on the Prototype framework.
Figure 2.5
General Interface framework API documentation.
TIBCO General Interface's JavaScript framework adds a Java-like package structure and organizes the code in class files, interfaces, and packages. This goes a long way toward making JavaScript look and feel like Java. There is even a dynamic class loader in TIBCO General Interface that can download classes as needed. General Interface framework adds functions to signal to the General Interface class loader when another class is required. All JavaScript code is written in smaller classes. Although a single source code file can contain multiple class definitions, it is advisable to keep the files small and define only one class in a single source file. This also helps with dynamic class loading because each class can be loaded quickly when needed. Remember, the classes are in JavaScript files, which live on the server but are used on the client, so class loading is done using an HTTP request. After they are loaded in the client, the JavaScript files are cached by the browser. It would be nice if this could be compiled code and executed much faster than JavaScript on the client side. Also, a compiler would aid at development time. The IDE provided with General Interface offers some assistance in this regard, but it's not really a compiler.
For more details on how to take advantage of the object-oriented approach in the General Interface framework, refer to Chapter 7, —Object-Oriented JavaScript—Extending General Interface Widgets."
JavaScript API
TIBCO General Interface's JavaScript API is organized into packages similar to the Java Development Kit. The root package name for all JavaScript classes is jsx3. Base framework classes to manage defining classes and packages are in the jsx3.lang package. A word of caution here is that the concept of package is somewhat similar to that in Java, except that if a package is defined using the jsx3.lang.package it cannot be dynamically loaded by General Interface's class loader. TIBCO General Interface packages allow pulling together several classes into a single package and allow JavaScript programs to discover classes, methods, and properties of a package. Although that is a good feature, it is possible, and in fact even advisable, to not use a package at all. Packages can also be created by using appropriate namespaces in class names. The following subpackages are available:
- Jsx3.app—Contains the highest-level classes for a General Interface application; for example, the application controller and General Interface global cache among others.
- jsx3.chart—Contains classes related to General Interface charts.
- jsx3.gui—Contains GUI widget classes and event and notification-related classes.
- jsx3.html—Contains very few classes that are related to the HTML that's rendered by General Interface.
- jsx3.ide—Contains classes related to the GI Builder IDE.
- jsx3.lang—Contains the General Interface class framework, which can be used without the rest of General Interface to build reusable components in JavaScript.
- jsx3.net—Contains classes that allow an application to communicate with the back-end services.
- jsx3.util—Similar to the java.util package; contains simple utility classes such as List, Iterator, and so on.
- jsx3.vector—Contains classes related to vector graphics in General Interface. Available only if Charts are used.
- jsx3.xml—Contains General Interface's abstraction layer for XML documents and CDF.
- window—Allows access to browser-level JavaScript functions such as window.alert().
Commonly Used Classes
TIBCO General Interface has a very rich set of features, and its framework includes numerous classes and methods. Product documentation includes a comprehensive API reference document similar to that available for Java. This section presents some of the more commonly used classes and APIs with specific use cases and sample code snippets.
Application Controller
General Interface has a high-level application controller that orchestrates various functions in a General Interface application. A single instance of this controller is created for every application. The name of this global controller class in General Interface is jsx3.app.Server
. It is used frequently in custom code because it allows access to other parts of the same application. For example, from an event handling code in a Select component, if you need to call a method on the grid component of the same application, you could use the following:
this.getServer().findJSXByName('mygrid').getSelection();
In this statement, this refers to the instance of Select control that is making the call. If you are a Java or C++ developer, it's the same this pointer that is used to refer to the current instance of a class. Refer to Chapter 7 for details on writing custom classes in General Interface.
Cache
Cache is the global memory space that is available to an application with smart management similar to Java's garbage collection. In this class, General Interface has provided a very smart mechanism for storing data within the browser that can be accessed by any other function or at a later time. This class is also used to keep some key data for some of the controls. For example, the grid control keeps its backing data in an instance of the jsx3.app.Cache
class. Applications can use this to store larger result sets locally in the client memory. However, care must be taken to not load too much into the client browser and avoid a memory overload of IE (or Firefox).
Custom Classes in JavaScript for General Interface
The exhaustive set of functions available in General Interface's framework makes it possible to write complex logic in a very few lines of JavaScript code that can also be embedded within the properties of controls similar to event handlers like onClick in HTML elements. JavaScript that accompanies any General Interface application can be written in the usual way in files with the .js extension. When you start a new project in General Interface, it opens a file logic.js in the workspace where small JavaScript scriptlets to handle event handling or validation logic can be placed. However, the best practice when writing JavaScript for General Interface is to develop JavaScript classes similar to Java classes. Each .js file should have only a single class defined in it. The way to define a class in General Interface is to use the defineClass() function from the jsx3.lang package. Listing 2.1 shows partial source code for a class written using TIBCO General Interface's framework:
Listing 2.1 Custom Class Defined in General Interface
jsx3.lang.Class.defineClass (
"com.tibcobooks.gi.chapter2.CommandHandler",
com.tibcobooks.gi.chapter2.BaseHandler,
part of Java class definition
[],
function ( CommandHandler ) {
CommandHandler.prototype.buyURL =
'http://www.anilgrnani.com/gibook/chapter2/by';
CommandHandler.prototype.sellURL =
'http://www.anilgrnani.com/gibook/chapter2/sell';
CommandHandler.prototype.init = function()
{
};
}
);
This framework can be used independently of General Interface by simply including some of the JavaScript files from the General Interface distribution. General Interface framework is open source, so there is no licensing nor cost implication of using it this way. It certainly makes JavaScript code much more modular and therefore easy to maintain.
The process of loading the class essentially downloads the JavaScript source file and executes it using the JavaScript method evaluate()
to insert it dynamically into the current set of available JavaScript files. After the class has been loaded, other parts of the program can create instances of the class, or they may call any static methods or access static properties by directly referencing it with the fully qualified class name—for example:
com.tibcobooks.gi.chapter2.CommandHandler.sellURL =
'http://www.anilgrnani.com/gibook/chapter2/newSellURL'
XSL Style Sheets
To deliver high performance, TIBCO General Interface relies heavily on the XML/XSL engine to render HTML instead of using DOM manipulation using JavaScript. It includes a large number of XSL style sheets in the distribution. Framework's XSL style sheets are stored in the JSX\xsl folder within the General Interface installation directory. A quick look in that directory shows the following xsl files:
cf_creator.xsl
cf_resolver.xsl
jsxlib.xsl
jsxmatrix.xsl
jsxmen.xsl
jsxselect.xsl
jsxtable.xsl
jsxtree.xsl
xml.xsl
Additionally, there are two subfolders: ie and fx. They contain XSL style sheets for the now deprecated classes List and Grid and are provided for backward compatibility with previous versions of General Interface.
Onscreen rendering of controls in General Interface is always done using these XSL style sheets. The XML data in CDF format is merged with one of these XSL style sheets to render the HTML for the browser. Editing these style sheets is not generally recommended because they are part of the General Interface product and may change with versions.
General Interface provides some hooks into these style sheets to allow customization. This technique helps the developer in another way—the developers do not have to write long and complex style sheets to do complete rendering; instead, they need to write only small fragments known as 'value templates,' which are inserted by the General Interface runtime before running the merge with one of these prebuilt style sheets.
Value Templates
A common requirement when displaying large lists of data is to be able to apply styling depending on the contents of the cell. In Microsoft Excel this feature is presented as Conditional Formatting in the Tools menu in Office 97 through 2003 and in the Home tab in the Styles palette in Office 2007.
In General Interface applications, this sort of formatting or coloring of data is achieved using fragments of XSL style sheets known as 'value templates.' Columns of a Matrix component have a property field called value 'template' where XSL can be placed to affect the output during runtime. Value templates are discussed in detail in Chapter 8, "Advanced Features of Matrix."
XML Transformers
Back-end systems do not always produce CDF. They should not be expected to produce it, either. Therefore, General Interface runs the XML through an intermediate style sheet that can be supplied by developer. XML Transformer is a property of data-driven General Interface controls that can contain a reference to a style sheet, which will be used to transform XML data before rendering it onscreen using the General Interface style sheet for that control. This allows for very elegant application design where the back end can supply data in a standard XML format, and clients such as General Interface can transform that data to the format they can use. XML Transformer can also be used to manipulate the data before rendering it onscreen; for example, data can be sorted on several keys before passing on to the General Interface handlers. General Interface allows fields to be designated as sort keys. However, XML Transformers can be used to sort the data using a fixed XPath expression before applying the single column sort offered by General Interface.
Note that when you have full control over the back-end XML generation, and/or the sole purpose of generated XML is to feed it to TIBCO General Interface front end, it is best to produce CDF directly because it saves one step in General Interface processing. Transformers are a fast and efficient way to convert XML that is already being generated by some back-end application or when there are other client applications that require the full power of XML.
Chapter 4, "Working with XML and XSL," and Chapter 8 in this book discuss XML Transformers in more detail and provide a complete example of using XML Transformers in General Interface applications.