XMLControl or DataWindow Anywhere

 

Introduction.

An ability to deploy application on Internet or Intranet quickly becomes essential requirement of the application development. The other one is to develop new applications with Internet/J2EE compatible tools. For PB developers it means that instead of single high-level integrated environment they have to use quite a few low-level tools, multitude of languages and technologies, write more code yet delivering less functionality. The problem becomes even more apparent when they need to transfer existing applications to the Web.

                As we will see in this article, it is no longer has to be the case. Deployment to the Web / Intranet no longer means complete rewrite of the application. Rather, it is a painless conversion process with the changes only in the areas pertaining to the platform and not in the application code/functionality domain. In this article we will show how to deploy existing DataWindows (which in PB projects take most of the development effort) on the Web with virtually no rewriting.

                In the heart of the proposed solution is XMLControl - an incarnation of DataWindow for Web. It provides similar functionality while being 100% Java/JavaScript/XML/XSL based. This article highlights features of XMLControl that are important to the application developers. It also describes automatic deployment of legacy DataWindows as XMLControls on any J2EE application server including EAS, WebLogic, SilverStream, WebSphere, etc. For more implementation details please see March edition of XML Journal (“Leveraging XML in Converting your Client/Server Application to the Internet”)

 

Simple Report

Let’s start with a simple example - an HTML page displaying the report from the “employee” table of the sample database EASDemoDB (Error! Unknown switch argument.). This page contains just one XMLControl. In PowerBuilder, that would be a window containing a single DataWindow.  The following is the exact HTML of our page for Internet Explorer 5:

<HTML>

    <HEAD>

       <STYLE>  .XMLControl {behavior:url(/Common/htc/XMLControl.htc)} </STYLE>

       <SCRIPT FOR="window" EVENT="onLoad">

            dw_1.connectionPool = “samplePool”;

            dw_1.retrieve();

      </SCRIPT>

   </HEAD>

    <FORM id="dw_1" class=”XMLControldataSource=”employeeRoster” ></FORM>

</HTML>

Let’s take a closer look at this HTML page. It contains a single instance of XMLControl named “dw_1”:

     <FORM  id="dw_1" class=”XMLControldataSource=”employeeRoster”></FORM>

As a PowerBuilder analog you can consider a window with the Datawindow control, associated to “d_employee_rosterdataobject. The property dataSource points to a set of application server objects responsible for population of the XMLControl dw_1. We’ll be covering construction of dataSource objects later in the article. For now, you may think of the dataSourceemployeeeRoster” as pretty much the same thing as datawindow’s dataobject  d_employee_roster”, driving population of data buffers, setting up initial filter and sort values, etc.

The actual data retrieval happens after the page is loaded. Script corresponding to “onLoad” event invokes an asynchronous method retrieve():

dw_1.connectionPool = “samplePool”;

dw_1.retrieve();

This is being done in the same way as one would do to populate a datawindow in the “Open” script of a PowerBuilder’s window:

dw_1.SetTransObject(SQLCA)

dw_1.retrieve()

The slight difference here is that client/server transaction object is replaced by reusable connection, allocated off the application server’s connection pool.

As one can see from the above HTML, the implementation of XMLControl is packaged as an IE behavior - XMLControl.htc. Behaviors became available in IE5.0, which was also the first IE version to support XML. If we “upgrade” our HTML to level of IE 5.5, we’ll be able to use a dedicated custom tag – “xmlsp:XMLControl”, instead of <FORM>, improving readability of the code:

<HTML xmlns:xmlsp>

     <HEAD>

        <?IMPORT namespace=”xmlsp” implementation=”/Common/htc/menu.htc”/ >

       <SCRIPT FOR=”window” EVENT=”onLoad”>

            dw_1.connectionPool = “samplePool”;

            dw_1.retrieve();

      </SCRIPT>

   </HEAD>

    <xmlsp:XMLControl id=”dw_1”  dataSource=”employeeRoster” />

</HTML>

Listing 1

Figure 1. Simple report in XMLControl

Also, this example demonstrates in-built support of pagination and navigation from one data page of XMLControl to another. In our case, with employee data grouped by department, every group starts on a new page. XMLControl automatically inserts customizable navigation bar at the bottom of the screen in Figure 1.

 

Simple Data Entry Form

XMLControl can be used not only for the reports. Similar to PowerBuilder’s DataWindow, XMLControl treats data entry forms and reports seamlessly. It is all controlled by dataSource element – the same way it has always been controlled by dataobject in DataWindow. To illustrate data entry capabilities of XMLControl, we will make another example, also based on the EASDemo database. HTML page, shown on Error! Unknown switch argument. displays data from “contact” table.   The dataSource of the XMLControl in this page is set to “contactMaintenance”:

       <xmlsp:XMLControl id=”dw_1”  dataSource=”contactMaintenance” />

In fact, the above dataSource was automatically generated from
editable ”d_contact_maintenance” found in PB demo application. (The subject of automatic conversion of DataWindow dataobjects into dataSource and deployment of DataWindows as XMLControls is looked into later in the article).

Figure 2.Simple Data Entry Form

Generated dataSource resulted in rendering to browser <INPUT> tags, wherever original d_contact_maintenance contained a non-zero value for “Tab Order” on a column, thus supporting user input into the fields. What makes this page really different from the previous one, though, is the presence of three extra buttons – “Add”, “Delete” and “Update”:

       <IMG src=”add.gifonClick=”dw_1.insertRow(dw_1.getCurrentRowId())” />

       <IMG src=”delete.gifonClick=”dw_1.deleteRow(dw_1.getCurrentRowId())” />

       <IMG src=”update.gifonClick=”dw_1.update();” />

As you can see, functions insertRow() and deleteRow() specifically operate on ID of the current row, rather then on the display position of it, like it is in DataWindow’s case. It is also worth mentioning that update() function communicates data changes to the application server for execution rather then to the database. And, unless XMLControl is subscribed to a specific persistent server transaction, update() function results in  attempt to COMMIT/ROLLBACK all data changes within one XMLControl as a single unit of work. Short of these nuances, presented XMLControl’s API should be very familiar and easily acceptable by any PowerBuilder developer.

XMLControl API

The following Error! Unknown switch argument. presents abridged list of the supported properties, methods and events of XMLControl API. The data manipulation part of XMLControl API contains acceptChanges(),resetUpdate(),getItem() and setItem() methods in addition to retrieve(),update(), deleteRow() and insertRow() methods described earlier in this article. All of these methods are similar to their PowerBuilder’s counterparts.

The navigational part of XMLControl API contains getCurrentRowId() used in the latest example, as well as setRow(), scrollToRow(), scrollToFirstRow(), selectRow(), getNextSelectedRow() and isRowSelected(). In  addition, it includes doFilter(), doSort() and setFilter(), setSort() functions. The later two accept XSL Xpath expressions for filter and sort operations. This departure from PowerBuilder syntax is caused by the very nature of XMLControl, which keeps all data in XML format providing functionality far beyond flat two-dimensional databuffer.

Events fired on XMLControl include onEditChange, onItemChanging, onItemChanged, onPaintBegin, onPaintEnd, onRowFocusChanging, onRowFocusChanged, onKeyDown and onUpdateError. 

 

XML Control Properties

Property

Description

autoHeight

Flag (true/false) for auto calculation of Detail band height

connectionPool

Name of the connection pool on the application server

DataSource

Base name for application server objects providing data, style and metadata information, whether servlets, JSP or static files.

dataUrl

Overrides dataSource-based data url

selectionStyle

CSS attributes for row selection

styleUrl

Overrides dataSource-based presentation stylesheet url

XML Control Data Manipulation methods

Method

Description

acceptChanges()

Propagate latest edit changes into data model

getItem(rowId, colName)

Get value of the cell

DeleteRow(rowId)

Delete row corresponding to “rowId

insertRow(rowId)

Insert new row into data model prior to given one

retrieve([xmlArguments])

Populate and draw XMLControl data

resetUpdate()

Drop update status information from the data model 

setItem(owed, colName, newValue, [bShow])

Set value of the data model cell

update([bResetFlags])

Simple update of one XMLControl (with COMMIT)

 XML Control Data Navigation methods

Method

Description

doFilter()

Apply current filter expression

doSort()

Apply current sort expression

getCurrentRowId()

Get id value of the current row

getNextSelectedRowId(id)

Get id of the next selected row

getRowNode(id)

Return XML node of the given data model row

getRowCount()

Return number of rows in the data model

isRowSelected(id)

Determine whether given row is selected

scrollToFirstRow()

Make first row visible and current

scrollToRow(id)

Make given row visible and current

setFilter(filterExpression)

Set Xpath expression for filter

setSort(sortExpression)

Set Xpath expression for sort

setRow(id)

Make given row current

selectRow(id, onOff)

Select/Deselect data model row matching “id”

 XML Control Miscellaneous methods

Method

Description

getPageCount()

Get number of pages (in large page-by-page reports)

moveToNextPage()

Navigate to next page (in large page-by-page reports)

moveToPreviousPage()

Navigate to previous page (in large page-by-page reports)

showFilterDialog()

Bring up in-built filter dialog

showSortDialog()

Bring up in-built sort dialog

showQueryDialog()

Bring up in-built query by example dialog

userAddObject(xslProcessor)

Callback to plug-in custom namespace functions into XSL transformation

XMLControl Events

Event Name

Event parameters

onEditChange

rowId, colName

onItemChanging

rowId, colName, newValue ,oldValue

onItemChanged

rowId, colName, newValue ,oldValue

onKeyDown

rowId, colName, keyCode, modifiers

onPaintBegin

XslProcessor

onPaintEnd

 

onRowFocusChanging

newId, oldId

onRowFocusChanged

newId, oldId

onUpdateError

errorCode, sqlError, sqlStatement, rowed

 Table 1

DataSource Demystified

We were deferring the explanation of what dataSource property of XMLControl is all about. Now we are going to demystify dataSource to the extent allowed by the space of the article. Readers can get the additional details in the author’s article in March issue of XMLJournal (“Leveraging XML in Converting your Client/Server Application to the Internet”).

In one statement, dataSource is a base name for a set of J2EE application server objects which together support the functionality described in the traditional PowerBuilder’s dataobject. And, naturally, the anatomy of dataSource is easy to explain by comparing it to DataWindow’s dataobject. As a reminder, a dataobject defines how result set is mapped to the database, what it should look like on screen, what computations, filtering and sorting does it have to go through prior to be displayed. But dataobject itself is nothing without the PowerBuilder’s Virtual Machine behind it.  And here lies the key difference between DataWindow’s and XMLControl’s architectures. The dataSource objects needn’t be interpreted by a proprietary VM. Once generated and deployed, these objects start life of their own – in any J2EE server.

In particular, one of dataSource objects – Java Servlet, returns requested database data in XML format. (Thus, data model is human readable and easy to work with.)  Another object – XSL stylesheet, formats XML data for browser rendering. Functionality, supporting client-side computations such as conditional attributes, totals and other aggregations is embedded in JavaScript file(s). Authors developed a free on-line conversion tool, named “DW2Java”, which automatically generates and deploys all these objects in a J2EE server, given PSR of a particular DataWindow. The logical flow of this “DataObject-to-J2EE-Objects” conversion is presented in Error! Unknown switch argument.:

 

Figure 3.Deployment Process

Creation of dataSource objects

Generation of  dataSource objects, or, depending on how you look at it, conversion of legacy DataWindows to J2EE environment, is a one-step process.

Let’s make a sample generation of “employeeRosterdataSource, which was used in our first example. We can use “d_print_employee_roster_dw” from PB Sample Application. We will save it as PSR file on a local drive, say  c:\employeeRoster.psr”. It is advisable to retrieve some real data prior to saving the PSR, if we are going to bypass servlet in testing the results against the static XML file that DW2Java generates off that data.

 

Figure 4. On-line Conversion and Deployment

Upon filling in an e-mail and the full path of PSR we submit it for conversion by clicking on the “Next” button. That’s all it takes to create and deploy servlet employeeRoster.class, stylesheet employeeRoster.xsl  and JavaScript file employeeRoster.js. (See Table 2 for the full list of “employeeRosterdataSource files.) It does not get any easier then that!

 

File name

Desription

employeeRoster.java

Java Servlet that queries database and returns the data packed in XML format

employeeRoster.xml

Metadata extracted from datawindow object

employeeRoster.xsl

Stylesheet converting servlet-made XML data into DHTML

employeeRoster.log

conversion and deployment log

employeeRoster_static.htm

“Preview” page, which is using employeeRoster_data.xml instead of servlet’s output

employeeRoster.htm

Sample page which is using servlet’s output

employeeRoster_schema.xml 

XDR schema describing servlet’s output for other applications

employeeRoster_data.xml

Data extracted from PSR in XML format

employeeRoster.js

Client-side JavaScript validations, and calculations

employeeRoster.class

Compiled  servlet in Web Application deployment directory

employeeRoster.psr

Copy of the submitted  PSR

 Table 2.employeeRosterdataSource files.  

 

Power to the Client

While designing XMLControl, we wanted to fully retain robust client-side capabilities of DataWindow. Yet we did not want to penalize user with extra round-trip for any sort/filter actions or recalculations of computed values.

As a solution, we persist XML data within the HTML page where it can be accessed directly by JavaScript. And it is also within the page where transition to DHTML from XML (known as XML “transform”) happens.

C++ and Java programmers heavily utilize Model / View / Controller architecture. It means that data (Model) is independent from presentation rules (View) and they are being “visually merged” by presentation behavior (Controller). XMLControl is based on this architecture, XMD data being Model, XSL stylesheet as a View and placeholder DHTML as Controller.

Current implementation relies on Internet Explorer, which, at the time of this writing, is the only browser with 100% compliance to W3C recommendations on XML and XSL support.  IE continues to gain market share surpassing 87% of Internet users, according to the latest survey published by WebSideStory, Inc. (www.websidestory.com), and is de facto standard for Intranet business applications.

 

Getting advanced: Master/Detail and Data Sharing

We have shown that XMLControl completely separates data from presentation. Data, in XML format, is provided by a Java servlet, while presentation is handled with an entirely different object – XSL stylesheet. As a result, data sharing between instances of XMLControl is even more powerful and flexible than it was with DataWindows. For example, let us consider a page, which enables user to browse through customer records and edit the details (Figure 5)

 

Figure 5.Master-Detail Relationship and Data Sharing

                The following JavaScript is the only code needed for this page to function (see Listing 2 for full HTML of the page):

   main.shareData(detail); 

   main.singleRowSelection = true;       

   master.retrieve(  );

   detail.setDynamicFilter("@selected='true'");

As you can see, this data sharing technique is quite similar to standard PB one. Additionally, singleRowSelection attribute controls row selection and highlighting capabilities, something that in glorious days of PFC would be called a “row selection service”. It is worth mentioning that setDynamicFilter() method provides presentation-only filtering, not matched by PowerBuilder’s DataWindow. In case of a DataWindow, filtering (or sorting) of the master control was immediately hitting the buffer, thus affecting the detail one. In XMLControl architecture, there is two ways to filter/sort: traditional one, where data model (buffer) is affected, and “dynamic”, where (loaded in memory) stylesheet information is modified prior to “transform”.

Overall, XMLControl provides extra flexibility and incorporates many framework-type functions naturally expected in the modern PB applications.

 

<html><head><title>Presentation Sharing/Scrolling</title>

<STYLE>.XMLControl {behavior:url(/Common/htc/XMLControl.htc)}</STYLE>

<SCRIPT >

function onLoad() {

   main.shareData(detail);   main.singleRowSelection = true;       

   detail.retrieve(  );  detail.setDynamicFilter("@selected='true'"); }

</SCRIPT></head>

<body bgcolor="silver"  onload="onLoad();" scroll="no">

<FORM class=”XMLControl” id="main" dataSource= “viewDetailsMaster” style="BACKGROUND-COLOR:white;HEIGHT:140px;OVERFLOW:none;BORDER-style:inset;"></FORM>

<FORM class=”XMLControl” id="detail" ” dataSource= “viewDetailsDetail” > </FORM>

</body></html>

Listing 2.

 

Print Preview Mode and Advanced Printing

DataWindow’s “Print Preview” mode enables users to see the “printed” version of the report. Till recently on the Web, however, only specialized ActiveX based solutions like Acrobat Reader and specialized reporting packages like Actuate provided similar functionality.

That situation changed with Internet Explorer 5.5 introducing print-preview architecture out of the box. Every page, browsed in IE 5.5 can be opened in “Print Preview” mode. Unfortunately, reports printed with default browser settings, hardly can be accepted by business users: pages breaking in unwanted places, headers and footers displaying irrelevant (to business) information.

XMLControl provides “turn-key” solution for business level “Print Preview” functionality. In order to use our Print Preview functionality you need to use the following function call:

xmlControl.enablePrintPreview ([yourCustomTemplate])

To revert to the default browser’s implementation use:

xmlControl.disablePrintPreview ()

Figure 5 shows the “employeeRoster” report in “PrintPreview” mode. As you can notice, we added “Actual Size”, “Page Width” and “Full Page” buttons “borrowed” from Acrobat Reader, to the standard “Print Preview” toolbar of Internet Explorer.

XMLControl handles print-preview based on “print templates” approach provided by IE. Print templates are essentially HTML files that control the page layout and printing flow. The universal printing templates of XMLControl automatically recognize header, group, detail and footer bands and make sure that they are placed properly in the “hardcopy” layout. In addition, they guarantee that only report (and none of the surrounding HTML elements including other frames, etc.) is being viewed and printed.

Figure 6. Print Preview Sample

 

XML metadata “describes” it all

As it is shown in Error! Unknown switch argument., XML metadata plays a central role in conversion of DataWindow into J2EE objects. However, XML metadata is just as valuable at run-time, providing information alike to “Describe” function.

Figure 7 presents generic sort dialog (in-built in XMLControl) running against “Customer List” metadata, with the records sorted by “Last Name, First Name”.

Making this dialog user-friendly required access to business names of the columns.  We also needed data types to make sure we are invoking the right type of sorting. Similarly, making the in-built “Filter” or “Query-By-Example” dialogs required knowledge of appropriate presentation, i.e. whether particular column is a checkbox, edit field or selection list etc. This information is contained in metadata, and is available for custom enhancements. The appropriate XMLControl methods to bring up these in-built functions are showSortDialog(), showFilterDialog() and showQueryDialog() accordingly.

 

Figure 7. Generic in-built “Sort” dialog

Server-side “roots” of XMLControl

XMLControl is by it’s very nature a “distributed” object, in a sense that a large part of it works on the application server and requires server support. Here is a brief glance at server-side “roots” of XMLControl.

As a communication protocol XMLControl relies on Simple Object Access Protocol(SOAP). SOAP is the XML based, “over-the-HTTP” protocol. With SOAP you do not have to be concerned with firewall and accessibility issues. What makes it a winner over binary ones - DCOM, RMI, or CORBA - that it is cross-platform, extensible and can be understood by any server that “talks” HTTP.

XMLControl deploys validation and update code as EJBs. It creates wrapper JSP for EJB to be called from the client. It also creates WSDL (Web Services Description Language) file that allows browser client to enumerate available functions and get data type information and list of the arguments

XMLControl provides “gateway” to the server’s WebServices. It allows EJB server object methods – validation and update as the most frequent examples - to be accessed by client JavaScript. All security, packaging, binding and marshalling happen transparently to the application code.

 

Conclusion

In this article we briefly described the “evolutionary” approach to redeployment of PowerBuilder applications on Intranets and Web using J2EE environment. It is based on automatic conversion of DataWindow objects into J2EE ones with cutting-edge Internet technologies. As a result, most of PB specific application code becomes “Internet-enabled” with just minor cosmetic changes. More information, as well as a free on-line implementation of DW2Java conversion tool can be found at http://www.xmlsp.com.

Authors Bio

Victor Rasputnis and Anatole Tartakovsky are co-founders of CTI, a New-York consulting firm servicing financial institutions and Wall Street firms. They provide architectural design, implementation management and mentorship to the companies migrating to XML Internet technologies. Victor holds PhD in Computer Science from Moscow Institute of Robotics where he conducted research of advanced interactive systems. Anatole holds MS in Mathematics. He also attended the post-graduate program in Computer Science at Moscow Institute of Robotics with specialization in theory of expert systems. They can be contacted via e-mail: VictorRasputnis@teamcti.com and AnatoleTartakovskyh@teamcti.com