The increased popularity of Web 2.0 is due largely to the flexibility of the current generation of web browsers. These browsers use Ajax to communicate with the server to interchange XML data and then employ DHTML to navigate the XML and present it to the user. The browser capabilities enable them to be used as thick clients in a web based application.
These base technologies gave birth to a number of new technologies and initiatives to meet the growing popularity of Web 2.0. New helper libraries like Dojo and Sarissa have been created to make using XML less painful, and there has been increased support for Scalable Vector Graphics (SVG). Embeddable widgets like Google and Yahoo Maps, data syndicatoin and integration methodologies such as RSS and Atom feeds, and a new paradigm of developments using data mashups have all been developed to meet the growing demands of the Web 2.0 culture.
As Figure 1 illustrates, the common glue in all the technologies is XML. The XML in the feeds makes it possible to publish and ingest complex data structures over the web. DOM application programming interfaces (APIs) in DHTML and XPath support in Sarissa allow efficient navigation of the XML for reading and writing in the client.
Figure 1. Web oriented architecture
Note : In the Web 2.0 world where data sources are viewed as feeds and services, database drivers are extended to support REST, FEED and SOAP calls. Once security implications have been resolved, you will be able to access database routines directly using SOAP or REST calls not only from an application server, but also from a web client, without having to create unnecessary mappings. In the next article, the author creates a sample SOAP driver for DB2®.
Leveraging the XML model in the client
Since many of the surrounding XML technologies are common to the application server and the browser, you can extend the XML data model seen in the first article to the client as well. In this article, learn how to extend the XML model in order to create rich clients using XML data transferred from the application servers. Discover how to use DHTML to present the XML, XPath to navigate the XML and the DOM to modify and serialize the XML back to the application server.
Similar to the DOM wrapper that you created in the application server, you will create a DOM wrapper for the client. This wrapper not only isolates the JavaScript visualization and business logic code from the DOM APIs, but also makes the code very similar to the Java ™code in the application server layer. To achieve this, you will use the open source library Sarissa that provides XPath APIs to the JavaScript code running in the browser. The wrapper code is available with this article (see downloads).
<script type="text/javascript" src="sarissa/sarissa.js"></script> <script language="javascript" type="text/javascript" src="xmlparse.js"></script> |
The following sections build on the insurance examples created in the previous articles of this series (see Resources). The following functionality is provided by the web client.
1. Allow users to view and modify the first and last name in their profile.
2. Calculate the insurance rates for each item purchased based on the insurance provider the user selects.
It is important to note: The code in this and the previous articles is only for explanation purposes. Only parts that explain the relevance of the XML model are fully coded. The rest of the logic is pseudo-coded with the assumption that the reader can extrapolate the standard code expected for that functionality. The next article discusses a complete business scenario that will be fully coded.
Allow user to view and modify their name.
Retrieve the customer information from the application server and present it to the client for modifications.
Client JavaScript code
The
profilediv
is used to publish the HTML string created from the XML data to the user.
<div class="profilediv" id="profilediv"></div> |
The customer ID (cid) is entered when the user logs into the site. This customer ID is passed to the
getCustomerInfo
function when the user selects Update profile in the client. The client sends an
HTTP request to the server using the XMLHttpRequest API provided by the Sarissa
library. As a part of the request, the callback function is also defined. This
function, customerInfoCallback, is invoked when the
response comes from the server. Listing 1 shows how to retrieve customer
information:
Listing 1. Client requests customer information
<script>
function getCustomerInfo(cid)
{
var xmlhttpObj= new XMLHttpRequest();
var addr=hosturl+"?cmd= getuserprofile&msg="+cid;
var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('GET', addr, true);
xmlhttpObj.onreadystatechange = function() { customerInfoCallback(xmlhttpObj); };
xmlhttpObj.send("");
}
|
Application server Java code
Listing 2 shows what happens in the application server when it receives the clients HTTP request. The server first checks if the HTTP request was a POST or a GET and then, based on this information, retrieves the command and data values from the parameters of the HTTP call.
Listing 2. Application server retreives customer information
public void service( HttpServletRequest _req, HttpServletResponse _res)
throws ServletException, IOException
{
String cmd, msgtext, returnvalue;
if(_req.getMethod().equalsIgnoreCase("POST"))
{
String message = getPostBody(_req.getReader());
XMLParse msgxml=new XMLParse(message);
cmd= msgxml.getValue("//request/@cmd");
msgtext= msgxml.toString("/request/*");
}
else
{
cmd= _req.getParameter("cmd");
msgtext= _req.getParameter("msg");
}
|
Since the command is to get the user's profile, the application server accesses the customer information from the database and returns it to the client. Listing 3 only shows the SQL statement necessary to get the information; it is expected that the reader already understands how to use the Java Database Connectivity (JDBC) APIs to connect to the database and get the query result.
Since the customer information is stored in the database as an XML document, you don't need to do any transformations to the data in order to return it to the client. Please note that the content type of the returned data is set to XML in the response HTTP header.
Listing 3. Application server's response
if(cmd.equalsIgnoreCase("getuserprofile"))
{
//returnvalue= select CUSTXML from customer_table where customerid =msgtext
}
_res.setContentType("text/xml");
_res.getWriter().write(returnvalue);
_res.setHeader("Cache-Control", "no-cache");
|
Client JavaScript code
When the client receives the response from the application server, the function
defined in the callback event is invoked.
Listing 4 shows the request for the userinfo. Please
note that the userinfo is declared as a global variable
since it is modified when you send the updates made by the user to the first or last
names.
Listing 4. Request for userinfo
var userinfo=null;
function customerInfoCallback (xmlhttp)
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
|
Since the returned value from the server is XML, you pass it directly to the constructor of your DOM wrapper.
userinfo= new xmlparse(xmlhttp.responseXML, false); |
Next, you extract the first and last names from the XML using XPath.
var firstname = userinfo.getValue("/Customer/@firstname",null);
var lastname = userinfo.getValue("/Customer/@lastname",null);
|
Listing 5 shows how to use DHTML to create a graphical user interface (GUI) for the user name modification
and insert it into to the div tag, profilediv, that you declared in your HTML page.
Listing 5. DHTML that creates a GUI
var htmlstr="<table class='inputtable'><tr>";
htmlstr+='<td>firstname:</td><td><input id="fname" value="'+firstname+'"/></td>';
htmlstr+='<td>lastname:</td><td><input id="lname" value="'+lastname+'"/></td>';
htmlstr+='<tr><td/><td><input type="button" value="save"
onClick="javascript:updateCustomer()"/></td>';
htmlstr+='</tr></table>';
document.getElementById("profilediv").innerHTML=htmlstr;
}
}
|
Once you have done the modifications, click on the
Save button to invoke the updateCustomer
function. The DOM userinfo containing the customer information is updated with the user modifications. Here again,
you use XPath to navigate to the data nodes that need to be modified.
Listing 6. use XPath to update customer information
function updateCustomer()
{
var fname=document.getElementById("fname").value;
var lname=document.getElementById("lname").value;
userinfo.setValue("/Customer/@firstname",null,fname);
userinfo.setValue("/Customer/@lastname",null,lname);
|
A new request is created and the updated DOM is serialized and appended to it. Listing 7 shows the request string then being sent (POST) to the server.
Note that since the message format is XML, the content type in the HTTP header of the request is set to XML.
Listing 7. Request string sent to the server
var msg='<request cmd=" updateuserprofile">'+userinfo.toString("/")+'</request>';
var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('POST', hostname, true);
xmlhttpObj.onreadystatechange = function() { profileUpdated(xmlhttpObj); };
xmlhttpObj.setRequestHeader('content-type', 'text/xml');
xmlhttpObj.send(msg);
}
|
Application server Java code
The incoming customer XML data from the request is parsed using the DOM wrapper.
Since customerid
is an attribute in the original customer profile that was sent to the client, there is no need to send an extra parameter for the customer ID in the request.
Listing 8 shows how to extract the customerid from the
XML and use it to create an update SQL command for the database. The customer profile data from the HTTP
request is passed as a parameter to the update statement; no modifications are needed.
Listing 8. Create an update SQL command
else if(cmd.equalsIgnoreCase("updateuserprofile"))
{
XMLParse custxml=new XMLParse(msgtext);
String cid= custxml.getValue("/Customer/@customerid");
//update customer_table set custxml=? where customerid=cid
//stmt.setString(1,msgtext);
}
|
Notice the similarity in application code that is used to navigate the XML in both the client and the server. Also, note that the applicatoin server in both the HTTP requests acted simply as a go-between for the client and the database -- no data was manipulated in the interchange.
Calculate the insurance rates for items purchased
The user selects an insurance company from a drop down list that contains the names of all insurance carriers. The insurance company has a web service that can be queried to get the current insurance rates. The rate information is provided as an XML document and is used by the application to calculate the insurance on each item.
Client JavaScript code
The URL for the associated web service provided by that insurance company is also selected from the list. Since Ajax prevents URL redirection, you need to invoke the web service from the application server. You pass the URL in the request to the application server for calculating the insurance cost of each item purchased. Listing 9 shows tihs process:
Listing 9. Client selects URL
function itemsPurchased(url,cid)
{
var msg='<request cmd="getPurchaseInfoWithInsurance"><data customerid="cid">
<![CDATA['+ url+']]></data></request>';
var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('POST', hostname, true);
xmlhttpObj.onreadystatechange = function() { temsPurchasedCallback (xmlhttpObj); };
xmlhttpObj.setRequestHeader('content-type', 'text/xml');
xmlhttpObj.send(msg);
}
}
|
Note : Since the URL might contain special characters, we have embedded it inside a CDATA section to prevent the request XML from becoming malformed.
Application server Java code
The request message is parsed using the DOM wrapper and the insurance URL is extracted from it. Listing 10 shows how the application uses this URL to make a call to the web service of the insurance provider to retrieve the XML document containing the insurance rates.
Listing 10. Application server retrieves insurance rates
else if(cmd.equalsIgnoreCase("getPurchaseInfoWithInsurance"))
{
XMLParse dataxml=new XMLParse(msgtext);
String url= dataxml.toString("/data/text()");
String insurancestr=callWebServiceUsingHTTPClient(url);
|
Note : The insurance rate XML is defined in Part 2, in the section entitled "A more elaborate example." .
The customer ID is also extracted from the message and is used to query the database for information on the items purchased by the customer.
String cid= dataxml.getValue("/data/@customerid");
|
The rest of the business logic for creating the purchased item list is implemented in either of two ways:
- Make a call to the database stored procedure created in Part
2>Listing 6.
// returnvalue = call customerItemsWithInsurance (cid, insurancestr);
- Code the logic in the application server using the code from the first article.
Using the
customerXMLfrom Part 1: Listing 6 , loop through each item, calculate the insurance cost, and add it to the item information.Replace lines 9-11 in the original code with the following:
Listing 11. Replacement for lines 9-11XMLParse insurancexml=new XMLParse(insurancestr); customerXML.find("/Customer/Items/item",true); String currency= insurancexml.getValue("//rate/@currency"); for(int i=0; customerXML.currentFind.getLength()>i;i++) { price = customerXML.getValue("@price",i)); if(price>500) rate= insurancexml.getValue("//rate[@price=""]/@rate")); else If(price>100) rate= insurancexml.getValue("//rate[@price="500"]/@rate")); else rate= insurancexml.getValue("//rate[@price="100"]/@rate")); String iteminsurance="<insurance currency="+currency+ ">"+price*rate+"</insurance>" customerXML. appendElement(customerXML.createNode (iteminsurance), customerXML.getNode (null,i), false ) } // returnvalue = customerXML.toString();
If you compare the above code to the query in the customerItemsWithInsurance
stored procedure of Article 2, you will note that there is a lot of similarity between
the two, especially in the XPaths that were used. This fact once again reinforces the
advantage of using the XML model and the ease of pushing business logic into the database.
Also note the power of XPath expressions to search and navigate inside the hierarchical XML Data Model . Replicating this kind of search in an Object Data Model using java code would require a great deal of effort. Using XPath simplifies the process and allowes it to be done with a single string expression.
Client JavaScript code
The server response invokes the itemsPurchasedCallback
function in which the returned XML data is parsed using the DOM wrapper. Listing 12
shows how to do this:
Listing 12. XML is parsed using the DOM wrapper
function itemsPurchasedCallback (xmlhttp)
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
var itemInfo= new xmlparse(xmlhttp.responseXML, false);
|
First extract the user name from the returned XML:
Listing 13. Extract user name
var firstname = userinfo.getValue("/Customer/@firstname",null);
var lastname = userinfo.getValue("/Customer/@lastname",null);
var htmlstr="<table class='inputtable'>"
htmlstr+='<tr><td>firstname:<td colspan=5>'+firstname
htmlstr+='<tr><td>lastname:<td colspan=5>'+lastname
|
Then iterate through all the items in the document and extract the relevant information to create the HTML string that is used to publish this information to the user.
Listing 14. Extract HTML that allows publishing
itemInfo.find("//item",null,true);
htmlstr+='<tr><td>itemID<td>description<td>date<td>price<td>insurance';
for(var j=0;itemInfo.currentFind.length>j ;j++)
{
var id= itemInfo.getValue("@ID",j);
var description= itemInfo.getValue("@description",j);
var purchaseDate= itemInfo.getValue("@purchaseDate",j);
var price= itemInfo.getValue("@price",j);
var insurance= itemInfo.getValue("insurance/text()",j);
var currency= itemInfo.getValue("insurance/@currency",j);
htmlstr+='<tr><td>'+id+'<td>'+description+'<td>' +purchaseDate+
'<td>' +currency+price++'<td>' +insurance;
}
document.getElementById("profilediv").innerHTML=htmlstr;
}
|
Note the similarity between the JavaScript code in the client that used XPath to search and iterate over the item elements to that of the Java code in the application server defined before.
Even if you had used a standard Object data model approach, your application layer data objects would still need to be serialized to a format that is understandable by the client. Since the objects are complex, you would have basically two options:
1. Generate the client page in the application layer and fill in the data in the appropriate section of the web page (ASP/JSP approach). Then expose multiple APIs to accept any user modifications to the data. The problems with this approach are:
- It mixes client and application server code which creates a sloppy architecture;
- It requires more APIs to be created and documented in order for the client to pass back any major modifications to the data.
2. Generate a data structure that can be sent to the client as a string. The most acceptable format for representing such a serialized data structure is XML. The problem with this approach is that:
- You have to now write extra code to do the serialization.
- If the updated data from the client is XML, then more code is needed in the application server to interpret the modified XML back to application data objects.
An obvious question that arises is: If you have to resort to the XML Data Model for communicating with the client, then why not use it in the application layer itself?
You still need to manipulate the information that you got as a result to the insurance
rate web service. Since this information is in XML, you need to first decompose it to
your object model. If your data was stored in the database as XML, you could pass the
XML to the customerItemsWithInsurance
stored procedure. The problem with this approach is that if you are storing the
data as XML and you are using the Object Model in the application, all kinds of
mapping and transform issues arise.
If the data was stored in the database in a relational schema, your queries to the database would become more complex. Plus, you would have to write additional code in the middle tier to map the relational data to an Object Data Model or an XML Data Model.
In a Web Oriented Architecture, data needs to be serialized across different layers of the application. The most acceptable way of transferring complex data between a web client and application server is XML. In each layer, the data can be queried, transformed, and updated, so if the XML nature of the data is maintained, then it is possible to use XML based technologies like XPath, DOM and XQuery to manipulate the data. This is the XML Data Model of programming and in the challenging world of business data integration it might well be the panacea.
| Description | Name | Size | Download method |
|---|---|---|---|
| DOM and XPath wrapper class for javascripts | xmlparse.zip | 9 KB | HTTP |
Information about download methods
Learn
-
"Programming with XML for DB2, Part 1": Understand the XML data model.
-
"Program with XML for DB2, Part 2": Leverage database support for XML in your application architecture.
-
"ISV success with DB2 Viper": Prepare your applications, routines, and scripts for migration to DB2 Viper.
-
Technical articles on DB2 XML: Find more articles regarding DB2 and XML.
-
"Get off to a fast start with DB2 Viper" (developerWorks, March 2006): Create database objects for managing your XML data and how to populate your DB2 database with XML data.
-
"Query DB2 XML Data with SQL" (developerWorks, March 2006): Query data stored in XML columns using SQL and SQL/XML.
-
"Query DB2 XML data with XQuery" (developerWorks, April 2006): Query data stored in XML columns using XQuery.
-
XML Programming with PHP and Ajax: Put DB2 9's XML capabilities to work in service-oriented architectures and other business scenarios.
-
"Use DB2 native XML with PHP" (developerWorks, Aug 2005): Learn about the effectiveness of using the native XML capabilities coming in the next version of DB2 Universal Database for Linux, UNIX, and Windows to simplify application code and the relational schemas.
-
Compare and contrast DB2's new XML support with traditional relational database technology.
-
Visit the developerWorks resource page for DB2 for Linux, UNIX, and Windows to read articles and tutorials and connect to other resources to expand your DB2 skills.
-
Learn about DB2 Express-C, the no-charge version of DB2 Express Edition for the community.
Get products and technologies
-
DB2 Viper 2 Open Beta
-
Download a free trial version of DB2 Enterprise 9.
-
Now you can use DB2 for free. Download DB2 Express-C, a no-charge version of DB2 Express Edition for the community that offers the same core data features as DB2 Express Edtion and provides a solid base to build and deploy applications.
Comments (Undergoing maintenance)





