devxlogo

SOA: Refactoring Mainframe Applications into Dynamic Web Applications, Part 2

SOA: Refactoring Mainframe Applications into Dynamic Web Applications, Part 2

his article is the second of a two-part series discussing how to use service-oriented techniques to refactor a mainframe application into deployable Web services within a standard Java servlet framework. The first part discussed how to apply SOA to a mainframe-dependent system. This part completes the discussion by showing how to use XMLHttpRequest background requests from a browser to invoke the Web services and provide data directly to the client application from the mainframe rather than screen-scraping and reformatting to provide data to a desktop application.

First, here’s a brief recap of the high-level application architecture design.

A Review of the Application Architecture
For this article, the application framework follows a four-tier design, including a client tier, an application tier, a business tier, and an integration tier. Each tier serves to support different functionality within the overall framework, as shown in Figure 1:

The Integration Tier
The integration tier defines objects, components, and adapters that allow easy integration with enterprise information systems.

The Business Tier
The business tier defines objects, components, and services that encapsulate business logic for a given enterprise. You expose this business logic publicly as services to take advantage of SOA’s benefits.

 
Figure 1. The Application Framework: Each tier shown in the diagram supports different functionality within the overall framework.

The Application Tier
The application tier consists of one or more FrontController servlets that handle incoming HTTP requests; dispatch the requests to services that execute business-domain logic; format the responses for the client devices; and return the formatted responses. The model-view-controller (MVC) pattern is followed to ensure a clear separation of concerns.

You can see a complete discussion of the FrontController and its implementation in the first part of this article, but basically, the FrontController supports a push-styled, event-driven model that makes the framework more responsive and dynamic. The class assumes that each incoming event has been initiated from a client device driven by the XMLHttpRequest object, which resides in the client tier.

The Client Tier
The client tier for this article consists of a simple HTML page with one form that’s used to retrieve a list of users from the server. The form contains two TEXTAREA fields and two buttons?”Submit” and “Reset.” The Reset button simply clears the form. The Submit button calls a JavaScript function that makes a request to a URL pointing to the FrontController.

The Application
The goal for the sample application accompanying this article is to retrieve a list of users from a mainframe system and display it in a browser without using screen scraping technologies. More generally, you can use the techniques discussed here to apply XMLHttpRequest object techniques to any browser-based application to take advantage of background-request data-refreshing without redrawing the entire browser window. For the sake of simplicity and clarity, the HTML page used to display the list of users in the sample application contains two TEXTAREA fields; one for displaying the list of users and one to display the raw data returned from the server.

 
Figure 2. The User Form. This sample form lets you make background requests via the XMLHttpRequest object from a browser to the FrontController servlet and then displays the results.

The FrontController class dispatches each request sent to the server to a UserAccount service containing the business logic that obtains the list of users. The UserAccount service interacts with the mainframe system using resource adapters.

After retrieving the list of users from the mainframe system, the UserAccount service returns the list to the FrontController class, which formats the response and returns it to the browser. The FrontController class handles each request/response in a simple model-view-controller manner.

Figure 2 illustrates the sample user form running in a browser.

Initiating a Request to the Server
When users click the Submit Query button on the form in Figure 2, the JavaScript function invokes the callService function, which makes a request to the server via the XMLHttpRequest object. I’ll discuss the XMLHttpRequest object in more detail below, but first, observe the HTML form:

   

Notice that the code invokes the JavaScript function callService when the user presses the Submit button. This function makes a request to the FrontController URL via the XMLHttpRequest object. The callService function is as follows:

   var httpObj;   var isWorking = false;      function callService(url)   {     if (!isWorking)     {       httpObj.open("GET", url, true);       try       {          httpObj.setRequestHeader("Content-type",             "text/plain");       }       catch(e)       {          // setRequestHeader not in some Opera versions       }       isWorking = true;       httpObj.onreadystatechange =          handleServiceResponse;       httpObj.send(null);       return true;     }   }   

The open method of the XMLHttpRequest object in the preceding function takes three parameters:

  1. A string defining the HTTP method (GET, POST, etc.) to call.
  2. The URL to which to direct the call.
  3. A Boolean that controls whether the call should be made synchronously or asynchronously.

The callService function handles duties for object creation, event handler assignment, and submission of an HTTP GET request via the XMLHttpRequest’s open method. The callService function assumes that the global variable httpObj has been previously instantiated and that a JavaScript callback function named handleServiceResponse exists that will handle changes to the state of the XMLHttpRequest object.

The XMLHttpRequest Object
The XMLHttpRequest object is a built-into-the-browser (in IE and other recent browsers) JavaScript or ActiveX object that enables JavaScript to make HTTP requests to a remote server and receive HTTP responses from a remote server without the need to reload the page. There are two distinct implementations, depending upon the browser. Internet Explorer uses an ActiveX object, while non-IE browsers use a native JavaScript object. Despite its name, the XMLHttpRequest object is not limited to sending or retrieving XML, it can request or send any type of content.

The framework for this article uses a JavaScript function called getHTTPObject to create the XMLHttpRequest object. The getHTTPObject function has two separate code blocks to meet the needs of both IE and non-IE browsers as shown below:

   function getHTTPObject()   {      var xmlhttp = null;      var success = false;            // List of MS XMLHTTP versions - newest first      var MSXML_XMLHTTP_PROGIDS = new Array(          'MSXML2.XMLHTTP.5.0',          'MSXML2.XMLHTTP.4.0',          'MSXML2.XMLHTTP.3.0',          'MSXML2.XMLHTTP',          'Microsoft.XMLHTTP'      );         // test for IE implementations first      for (var i = 0; i 

Notice how the getHTTPObject function first tests for IE implementations of the XMLHttpRequest object and then tests for non-IE implementations. You can use both implementations in a similar fashion?in other words, once you have a reference to an XMLHttpRequest object, the method calls and properties are functionally similar, regardless of the underlying implementation.

After creating an XMLHttpRequest object, you simply set a few properties on it and invoke the open and send methods on it to send data to the server. The callService JavaScript function illustrated previously demonstrates the send process.

When you make an asynchronous call to the XMLHttpRequest object, it repeatedly executes the callback function handleServiceResponse (previously stored in the XMLHttpRequest object's onreadystatechange property) until the server response is complete.

The handleServiceResponse function queries the readyState property of the XMLHttpRequest object to determine the completion state of the response. The readyState property can have one the following possible values:

  • 0 (UNINITIALIZED): open() has not been called yet.
  • 1 (LOADING): send() has not been called yet.
  • 2 (LOADED): send() has been called, headers and status are available.
  • 3 (INTERACTIVE): Data is downloading.
  • 4 (COMPLETED): Finished with all operations.

When the readyState property indicates that the response has completed, you can retrieve the response data from the XMLHttpRequest object using either the responseText or the responseXML property. The responseText property returns a string representation of the data and the responseXML property returns an XML document object that you can then traverse as desired. The following code shows the handleServiceResponse JavaScript function:

 
Figure 3. The Populated User Form. After completing the background XMLHttpRequest call, the application displays both the raw XML data received and the extracted list of user names.

Figure 3 shows the populated user form after a receiving a response from the server.

   function handleServiceResponse()   {     if (httpObj.readyState == 4) // completed     {       isWorking = false;       if (httpObj.status == 200) // server "OK" response code       {         // the responseXML property retrieves an XML Document         var xmlDoc =            httpObj.responseXML.documentElement;                       // the responseText property retrieves a string         document.ServiceRequestForm.result.value =            httpObj.responseText;                  document.ServiceRequestForm.users.value = "";                  // display the user list from the XML Document         var users = xmlDoc.getElementsByTagName("User");         for (var i = 0; i  0)            {               document.ServiceRequestForm.users.value +=                  "
";            }            document.ServiceRequestForm.users.value +=               users.item(i).firstChild.data;         }       }     }   }

The preceding function retrieves the HTTP response as an XML document and then traverses that document to find the desired nodes. It then uses the data from these nodes to populate fields in the HTML form.

XMLHttpRequest Object Methods and Properties
The XMLHttpRequest has a set of methods and properties common to all supported environments (browsers). Table 1 shows the most frequently used XMLHttpRequest object methods.

Table 1. The table lists frequently used XMLHttpRequest object methods.

Method Description
abort() Stops the current request
getAllResponseHeaders() Returns complete set of headers (labels and values) as a string
getResponseHeader("headerLabel") Returns the string value of a single header label
open("method","URL"[,asyncFlag[,"userName"[,"password"]]]) Assigns destination URL, method, and other optional attributes of a pending request
send(content) Transmits the request, optionally with a POST string or DOM object data
setRequestHeader("label", "value") Assigns a label/value pair to the header to be sent with a request

The XMLHttpRequest object also shares a common set of properties across all supported environments. Table 2 shows the XMLHttpRequest object properties.

Table 2. The table shows a list of frequently used XMLHttpRequest object properties.

Property Description
onreadystatechange Event handler for an event that fires at every state change
readyState Status:0 = uninitialized1 = loading2 = loaded3 = interactive4 = complete
responseText String version of data returned from server process
responseXML DOM-compatible document object of data returned from server process
status Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
statusText String message accompanying the status code

At this point, you've seen how to refactor a mainframe application into deployable Web services using service-oriented techniques and a standard Java servlet framework. This article discussed how to access that framework using queries from a the now-ubiquitous browser-based XMLHttpRequest object to invoke the Web services and provide data from the mainframe directly to the client application rather than screen-scraping and reformatting to provide data to a desktop application.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist