XML Legacy Migration XML Legacy Migration XML Legacy Migration XML Legacy Migration XML Legacy Migration
xml Home Forecross Corporation Xml Solutions Migration Solutions Integrity Solutions XML Links Information and News Investor Relations
Web Services
by
Don Estes

gradient.gif (3616 bytes)
Implementing Internal Web Services (continued)

In the first example, we use a transaction to allow us to edit an existing database entry. We begin by requesting a display of the existing data, which we decide to modify and then return a request for a modification screen. During the step 2 processing, the application will lock that database entry for update to prevent overlapping updates from multiple users reinstating obsolete data. Depending on the database management system, this might be a physical lock enforced by the system, or a logical lock enforced by the application. During step 3 processing, the lock is released.

Between step 2 and step 3 processing, the database row is left in a locked state, which is why this is considered a stateful transaction. If the third step never occurs, the database can be left in this locked state, which has to be reset somehow, probably through an expiration mechanism. This can create conflicts with other users of the database. At the very least, it can increase the complexity of queries, and disproportionately increase the probability of faults within the application. Finally, the user has three steps, when 2 will do, decreasing their productivity.

Example 1B: Stateless version of editing transaction.

Step User Mainframe Application
1 Request display of a database row Accesses database, formats data display to allow modification, saves a copy of the database row at that instant linked to the request, responds to the user with the data display; database row remains unlocked.
2a User decides to change the data, requests update screen Deletes the saved instance of the database row.
2b User modifies data in display, and requests the update Accesses the database and the saved instance to ensure that the data has not changed; if it has, the user is notified and the update is aborted; if not, the database is updated and the update is confirmed to the user.

A stateless version of this editing transaction might, as in this example, save the data to temporary storage linked to a unique transaction ID, and then use the saved data as in step 2b to ensure the database has not been changed in the interim. Purists might take exception to this strategy, since even the temporary storage constitutes a form of statefulness, albeit a fairly benign one. Alternatively, the application could send both a visible and an invisible set of information during step 1 processing, in effect using the transaction itself as the temporary storage, which should satisfy most purists, if at a cost of some bandwidth. Or, less elegantly, we might just accept the risk of reinstating obsolete data, and never lock the database entry at all.

Example 2: Create new database table entry using stateful transaction.

Step User Mainframe Application
1 Request new entry display for a specific, uniquely defined data ID Accesses database to ensure that the data ID does not exist, responds to the user with the first data entry screen.
2 User completes the first data entry screen Edits the data entered, if OK saves it to temporary storage, and sends the second data entry screen
3 User completes the second data entry screen Edits the data entered, if OK retrieves and clears the temporary storage, updates the database with the combined data, and sends confirmation to the user.

In the second example we use a two-step transaction to insert a new row of data into a database table. The first step takes the first half of the data, saves it in a temporary storage area, and then merges it with the input to the second step before updating the database. So what's the problem with this? Isn't it again a case where only the purists might object?

If we were to continue with the old world of dumb terminals, the objection indeed might be academic. But, once we consider browser use, we can see a real problem. The legacy application implicitly assumes that it has complete control over the state of the display, but a browser user has a BACK button, and can return to a previous display. In this example, the user might send the second data entry screen, get a response, and then realize there was an error on the second entry. Of course, the operator should go to the editing screen, but it is so easy to just hit BACK, change the data, and submit again, that it will surely happen not infrequently. It is equally easy to imagine that the application would abort when it got a second instance of the second data entry screen but with temporary storage already cleared.

A stateless version of this would accept all the data at once and update the database as a single step, so that nothing was ever saved in temporary storage. In example 1, the stateless version could be implemented with equal ease given a user employing either a dumb terminal or a browser. In this example, however, it is difficult to imagine a solution using a dumb terminal.

How do we do this if we are going to re-use the existing application logic? This is where we get into re-engineering the user interface, a full treatment of which is beyond the scope of this article. But, for this one example, one simple solution is to define what we call a "super-function", by which we mean a new, virtual transaction code associated with the input of a single XML document, but which links to a sequence of transaction processing modules rather than the normal 1:1 linkage. The first step is called and uses the data elements from the XML that it requires, creates its temporary storage entry, and exits. At this point we immediately call the second step, which accesses both the data elements from the input XML that it requires and the temporary storage from the first step, and completes the transaction sequence, leaving the system in a neutral state.

Having created this super-function via a sequence of XML enabled transactions, we create a browser form to link to it. The HTML page can slide up or down with plenty of visual room for entering the data from both the first and the second data entry screens. This is a solution that works fine with new user interface technology, but is not downward compatible with the old character based technology of 3270 terminals.

In these two examples, we have created a stateless transaction in the first case by modifying the host transaction-processing program, and in the second case by some clever processing between the browser and the application program. However, there is another technical strategy that can be applied to both cases: composite applications.

A composite application is the more advanced form of user interface re-engineering. Rather than changing the application in the first example, or getting intimate with CICS in the second example, we interpose a simple Java program between the host and the user. This program can expose a Web Services compliant interface, just as it can be J2EE compliant, ".NET" compliant, or indeed support any required external interface. The key is that the program will act as a protocol buffer with the legacy host application. How is this different from screen scraping? In addition to being much more powerful and much less fragile, it is easy. We have an example composite application on our web site that took 15 minutes to write and debug.

In example 1, our composite application can issue the query for step 1, and pass it on to the requestor as an XML message or formatted into an HTML page, leaving the host in a neutral state. The requestor can review and decide to modify the data. When the updated information is returned to the composite application, then it issues the step 2 query to the host, which locks the host database. From the response to the step 2 query, it determines whether the data has changed in the database. If it has changed, it sends an abort to both the host and the requestor, but if not it responds with the step 3 transaction. When it has confirmation from the host, it responds back to the requestor. After all input requests, the host is left in a neutral state.

Similarly in example 2, our composite application can collect both screens of information, perhaps performing some pre-editing on the data, and send both step 2 and step 3 transactions to the host one after the other. When it has confirmation from the host, it responds back to the requestor. After the input request, the host is left in a neutral state.

The attentive reader may have noticed that the composite application solution to example 1 has one fewer user step. Indeed, many sites with no interest in Web Services per se are interested in reducing the number of unnecessary steps a user has to traverse to perform their task, so this can be a significant side benefit to this approach. Conversely, those whose interest is primarily in Web Services may find additional justification for the approach from just this increase in user productivity.

Previous Next

Forecross is a registered trademark of Forecross Corporation.
Copyright © 1996-2008 Forecross Corporation
All Rights Reserved.