Ajax and the Spring Framework with TIBCO General Interface

Java Development News:

Ajax and the Spring Framework with TIBCO General Interface

By Brian Walsh

01 Jul 2006 | TheServerSide.com

Introduction

Ajax

Ajax (Asynchronous JavaScript and XML) means many things to many people. However, one thing is certain: To users it implies a higher level of functionality and an improved experience. To the developer, another certainty follows: More work. The only question is how much work and to what end.

There are at least three separate tracks to consider: Communications and messaging, user interface components, and client side scripting. Since in the Ajax world the server no longer sends down html to the browser, your developers need to agree on a message format. The user's expectations of a dynamic UI are high. They want a desktop experience and Web simplicity. You will need to develop or obtain components to meet many requirements: Legacy integration, micro-content, predictive fetch, drill down, visual effects, specialized and generic UI widgets.

Finally, your developers need to integrate all of the above and inject your organization's value add and business rules.

You can start by downloading random chunks of JavaScript and integrating them with the browser's XMLHttpRequest object using Notepad or vi as the main productivity tools. Certainly five years ago this was the case. Some organizations produced great work; others produced un-maintainable hodgepodges unreadable to all but the original authors.

Where GI fits in

Alternatively, you can take advantage of mainstream adoption of Ajax by leveraging others' work. TIBCO Software's Ajax tools, known as TIBCO General Interface and "GI" for short, provide a solidly engineered set of JavaScript libraries to power Ajax solutions. In addition the GI libraries also power the visual tools TIBCO provides for rapidly authoring these solutions. GI's individual JavaScript class objects are integrated into a unified framework that executes at the client, not the server, using MVC principles to generate and update the GUI. Accordingly, DHTML and JavaScript generation occurs using the client CPU, not the server CPU. The Ajax framework is comprised of a well thought-out class structure that provides an intelligent abstraction of the browser event model, a wide variety of UI components, a client-side data cache and a service architecture for messaging.

Solution Objectives

Below we will examine in detail how GI MVC running in the client works with Spring MVC, a leading Java server framework. You will see how GI can extend and coexist with your Spring JSP investment.

Before we jump into it lets review the technical requirements of this use case. Application owners and developers alike predictably want to increase productivity and reduce time to market. This type of rapid implementation gives us several imperatives:

  • No wholesale replacement of our Spring investment.
  • Incremental change of existing server code as opposed to wholesale change to, for example, SOAP Web services
  • Continued support for non-Ajax clients
  • Re-use of existing code wherever we can. Develop the GI application along side the JSP layer.

Since GI generates the view at the client, Spring need no longer generate HTML at the server. Instead, we'll modify our Spring configurations such that Spring can also return raw data in form of XML that can be consumed as a service by the Ajax processes in GI.

Spring

Spring's MVC implementation

The Spring framework (http://www.springframework.org/) includes an elegant MVC (model-view-controller) module for building Web applications. Spring is fairly unique in its ability to support plugins at all levels in its stack, from database access to transaction control to MVC layer. In addition to standard JSP and JSTL, many different view technologies have been used with Spring (Struts, Velocity, Freemarker, XSLT, Web Flow,etc.). You can choose which MVC layer to use. Furthermore you can choose which rendering engine to use within the MVC layer. The Spring framework supports all these views equally, without preference, so customizing the framework to support a new one is a common use-case.

Simplified sequence diagram of Spring MVC

 

 

Lets get started

Below we will show you how to get integrate GI with Spring's MVC.

Before we integrate with GI, we need to verify Spring in a 'stock' MVC/JSP environment. See the spring tutorial Spring MVC step by step. It's important that you understand this example because we will use this specific application as a basis for GI integration.

Our starting points are the latest and greatest versions of Spring, Xstream and GI. Our use case requires that we display a price list of products and modify the prices by entering a validated percentage the system will apply to all prices. Then, the price system will validate the percentage input and display error messages if the percentage is invalid.

Spring setup

Customizing build for your environment

Review the resources section below to see what components you will need to install on your system. At a minimum you will need Java (1.4.2 or higher), Ant (1.6.2), Spring (1.2.8) and Tomcat (5.5.x) and your favorite IDE. You'll also need to customize the build.properties and log4.properties files for your environment. See the Spring MVC step by step tutorial and ensure you can view the JSP pages.

Spring Architecture

  • Spring's View layer

  • Spring configuration in detail

Take a look at the application context defined at src/main/Webapp/Web-INF/gi2spring-servlet.xml. Here we can see the two controllers established for the two actions (list products and increase products). Both have the product service (productManager) passed to them. The price increase controller also has a form and a validator associated with it. Note that the form and validator are POJOs (Plain Old Java Objects). There is no dependency between them and the Spring framework or JSP layer. Also defined here are the mapping between the controller names and the URLs. We made a change to the Spring example application controllers. We made the success view and form view values configurable as opposed to hardcoded. This is a best practice for Spring controllers in any event. It will become important shortly as we configure Spring to interoperate with GI .


Click for full-size image

One last configuration to examine is the view resolver.


Click for full-size image

The view resolver is a plugin that tells Spring how to render the output from a controller. Here the view properties returned from the controller ("hello" and "priceincrease" ) get mapped to actual JSPs ("/Web-INF/jsp/hello.jsp" and "/Web-INF/jsp/priceincrease.jsp") . The view class is the component that in turn actually takes the output from the controller and renders it.

Configuring support for XML output

Since GI is a view technology, it makes sense to start our GI integration here at the view resolver.

Any Ajax implementation makes certain demands of the server. A key pre-requisite is a structured message. GI, like most Ajax libraries, is highly optimized around this concept (though GI also provides a less optimal means to consume and display server generated chunks of HTML as well). Therefore we need Spring to produce a simple, consistent XML payload.

Spring makes our life easy in this regard. Spring can chain view resolvers, passing the requested view to a series of resolvers until it one responds with a view that can render the model. Our first change will be to add a XMLViewResolver. The XMLViewResolver is a Spring provided class that reads a configuration file of view names that we want rendered into XML.


Click for full-size image

The views.xml configures our view implementation, a single class that renders xml.

Our system now looks like this ...

 

 

Create XML from model using XStream

It doesn't take much code to create an XML document.


Click for full-size image

This xml structure maintains the basic contract between the controller and view, a simple map of arbitrary objects. The client application would use the XPath "/map/entry/*[position()=1]" to access the map's set of keys. Similarly the XPath /map/entry/*[position()=2] provides the value set.

The same contract applies to exceptions. Exceptions are simply entries in the map using exception class name as the key.


Click for full-size image

Now we have extended the system to incorporate our new view.

 

Controller layer

Now that we have two different rendering technologies in the view layer we need to indicate which one to use. One way to do this would be to define a request parameter or session attribute that would be maintained at each layer. This would require changes to our existing controllers and creates a contract with the client. A requirement like this scattered layers and platforms can introduce errors and overhead. A better alternative is to simply reconfigure the controllers creating new instances of each desired controller class, each configured with the new GI view name.

Our final configuration change completes the GI enabled Spring application. Our controller layer now supports two different paths, one mapping for GI in addition to the original JSP.


Click for full-size image

 

 

GI Setup

You will need to download the community edition of the GI toolkit (http://www.tibco.com/mk/gi/) as a pre-requisite. This will provide both the run time support for our application's client pages and a browser based development IDE.

JSX directories

"JSX" is GI's arbitrary namespace convention. It stands for JavaScript and XML, the key technologies GI uses. You'll see it used throughout GI solutions.

To get GI optimally set up, put GI's JSX and JSXAPPS directories at the root of the Webapp directory. The JSX directory is a simple copy and paste of the /TIBCO/gi/3.1/JSX directory. The JSXAPPS directory contains a single subdirectory with your application in it. This directory convention is a requirement of GI.

For additional productivity during development, you may wish to copy the GI Builder directory into the Webapp directory. Simply copy the doc, GI_Builder directories and GI_Builder.html from /TIBCO/gi/3.1 to the root of your Webapp directory. You will not want to deploy the GI Builder assets to your production Webserver. However, having them in this location allows you to edit GI artifacts in place without a constant copy and merge cycle from the TIBCO installation directories to your workspace.

Your directory structure should look like this:

 

 

GI Development

Ajax UI Design Requirements

Our first step in design is to sketch out our UI design. We start from the existing legacy JSP pages as a starting point. Since a major goal of Ajax is to provide multiple views without refreshing the entire page, we need to select a motif or theme to convey this to the user. A fairly conservative choice is a tabbed pane displayed in a standard header/body/footer layout. The table of prices we would like displayed in a sortable list. One additional requirement is to display a manageable, friendly error details tab.

 

 

 

 

 

GI user application architecture

Below is simplified hybrid diagram of our client application (showing only the classes, methods and properties we interact with). It is important to note that most of the files below are generated from GI Builder. The output of GI Builder is mostly XML models of GUI definitions and client-server communication processes. These models, served as .xml files from any HTTP server, are interpreted at runtime by the GI Framework so as to generate instances of GI JavaScript class objects on the client. Thus the developer's job is mainly concentrated on visually assembling GUI components then linking and orchestrating the services. One does get into JavaScript programming using the JavaScript APIs to the GI class objects for purposes of implementing client-side behaviors and interaction logic. Value adds on the client include parsing the Spring exception message and marshalling form attributes.


Click for full-size image

Message Properties / JSS

The first part of building any UI layer is to define a configurable message store to enable configurable display strings external from the codebase. GI is no exception in this regard. JSXAPPS/gi2spring/jss/messages.jss defines a level of indirection for messages. JSS is short for JavaScript Style Sheets. This is a convention unique to GI that encapsulates concepts of CSS for dynamic styling, but extend the concept to any property of any object - not just the visual ones. In the same way a jsp author would code "" the GI Builder allows the designer to define widget content by selecting from a drop down.

 

 

 

 

Automated creation of JSS

For convenience we developed a command line ant task tool to perform this conversion look for Properties2Jss.java under srctoolsjava.

After applying Properties2Jss this becomes:

 

 

Mapping Rule Service

Next step in construction is to handle the messages created by the XMLView to and from the server. GI provides a high level service (jsx3.net.Service) for you to extend.

The GI Service has several responsibilities:

  • Marshalling UI screen component content to a request message
  • Sending that request to the server
  • Un-marshalling the response message to UI components
  • Calling user provided event handlers (success, error, timeout)

The Service interprets a set of message transformation and object binding rules stored in a rules/*.rule file. These rule files are created with the XML Mapping Utility, a rule editor within GI Builder. Rules files enable message formats, urls, data, and UI mappings to change independently of the JavaScript controller that orchestrates them.

In order to use the rule editor we save a copy of the server output in JSXAPPS/gi2spring/xml as displayprices.xml. Next, we'll need to create a XML mapping rule for each of the three flows coming from the server (price list, price increase and error).

Creating the Mapping Rule

Our application is not a SOAP Web service so we choose XML/XHTML/Schema rule type. Our Spring process will be invoked using a GET action with a standard URL. Therefore there is no outbound document we'll pass to Spring. Our inbound document is pointed at our sample document. Placing the Mapper Log into trace level gives us additional insight into the process.


Click for full-size image

Parsing the document produces:


Click for full-size image

Mapping the response to the List component

Of particular importance in this document is the list of products. We will define a rule to transform this document from the response format to a CDF format suitable for the jsx3.gui.List. CDF stands for Common Data Format. CDF is a GI convention for normalized client-side data so that multiple GUI components can provide views into single sets of data (e.g. the same data can be viewed as a List, a Chart, and a Menu, etc... all at the same time just by binding those GUI components to the CDF object). The List infers a flat, non-hierarchical set of nodes. We do that by selecting one of the Product Nodes and defining a CDF rule. Let's create one in the XML Mapping Utility rule editor.

For the list node we specify that the rule should create a new CDF document and place it in GI's data cache with a name of "priceList". This key is important as we have specified the list gui component with the same key.


Click for full-size image

Click for full-size image

Next we define the rows in the document.

 

 

Finally we define the attributes on the record. Note the attribute names are the same as the path property in the list column.


Click for full-size image

Specifying the server URL

Finally we add the endpoint and method to the rule set. The endpoint "hello_gi.htm" was configured in the Spring "urlMapping" bean above.

 

 

 

JavaScript integration

Now we are ready to orchestrate the mapping rule with our application. First save the mapping rule file in /rules then with the Operation (Transaction) node selected, press the Generate button in the XML Mapping Utility. This produces several JavaScript functions for you. Paste the resulting JavaScript into your js/logic.js file.

Modify the service.onSuccess code block as follows:

 

 service.onSuccess = function(objEvent) { //update status setStatus("The service call was successful."); // repaint fields whose data was updated by the rule gi2spring.getJSXByName('productList').repaint() ; };

Here we specify what we want the application to do when the response is returned. In this case we want to update our status (footer area) and repaint the product list.

Validating and marshalling server request

We take a hybrid approach to sending our price increase request. At this time the jsx3.net.Service class does not support mapping to legacy forms. We will need to validate the user's input and create our form.

The intersection between client side and server validation is fairly arbitrary. At the end of the day you will need to support both. A common sense approach is to implement type checking on the client and leave business rules on the server. This is the approach we have taken here. However, your situation may differ and you may elect to implement rules in the client as well. GI supports both.

 

 // validate current input ... var jsxPercentage = gi2spring.getJSXByName('percentage') if (! jsxPercentage.doValidate() ) { // find the errors in our .jss dynamic properties var message = jsxPercentage.getServer() .getDynamicProperty("typeMismatch.percentage" , jsxPercentage.getValue() ) ; // show the error displayError( 'percentage', message) ; return ; // early return }

Within the priceIncrease service we leverage properties defined in the service when we create our form.

 

 // create a form var form = new jsx3.net.Form(method,endpointURL) ; // form.server = objService.getServer() ; form.setField("percentage",jsxPercentage.getValue()) ;

Handling server validation errors

For each response we get from the server we interrogate it for errors. Since we have modeled our UI jsxnames and jss properties after the server, it is a simple matter of unmarshalling the server's response and returning a collection of error messages complete with resolved arguments.

 

 service.onSuccess = function(objEvent) { //extract response from event var objHTTP = objEvent.target; var doc = objHTTP.getResponseXML() ; var errorMessages = extractErrorMessages(doc,objHTTP.server); if ( errorMessages.length == 0 ) { gi2spring.getJSXByName('tabHome').doShow() ; setStatus("The priceincreaseService call was successful."); gi2spring .getJSXByName('tabErrors') .setVisibility(jsx3.gui.Block.VISIBILITYHIDDEN,true) ; // call the same service as the home tab eg.displayPricesService.processInbound(doc) ; } else { // update [field]Error for (var field in errorMessages) { // show the error displayError( field, errorMessages[field]) ; } . . .

Testing

A key point to this architecture is that all of the model, business logic and controller code in the server remains unaltered. Existing JUnit suites remain in place a can be developed independently of GI.

Functional testing of the look and feel of the GI screens remain a province of WinRunner and other client side tools. However, TIBCO has already performed the testing on GI's class libraries for multiple browser versions, security settings, plugins etc. This greatly reduces the number and nature of your testing.

Conclusion

It took much more time to document this application than it did to write it.

The following table illustrates the alignment of key client and server components.

Spring MVC GI Strategy
messages.properties messages.jss Generated by command line tool
model map Documented XML message Self describing format
controller jsx3.net.Service Generated by GI Mapping tool

We were able to develop this application by writing exactly one server side class. The rest was accomplished via configuration changes to the Spring application context.

On the client side we had slightly more work. We generated three mapping rules, developed one method to resolve Spring exceptions to client side messages and wrote some orchestrating glue code.

In the future even more of the process can be automated as GI adds additional features including Form support into the mapping tool.

Resources

Minimum requirements

Java Development environment

Other Resources

Source

About the Author

Brian Walsh is the founder of bwalsh.com, a Portland, Oregon consulting firm specializing in Internet and network-enabled product strategies and development. His areas of expertise include enterprise architecture, technical evaluations, infrastructure, software engineering and database design. Walsh's recent clients belong to a wide variety of industry segments; retail banking, insurance to telecos and network management firms. Always enjoying the hands-on approach, he divides his time between policy issues and technical challenges.