5.3. Background to Mainframe Interoperability

5.3.1. Current Mainframe Technology Update

The New IBM Mainframe

The IBM z/Series mainframe is a new product line of legacy S/390 mainframe hardware that provides backward compatibility for previous legacy operating systems using logical partitions (LPARs). The operating system z/OS provides support for multiple operating systems, including MVS, VSE, Linux, and OS/390 Unix Services.

OS/390 can be emulated on a notebook running Linux with a USB dongle and a valid license key. Fundamental Software has produced a Linux package called FLEX-ES (http://www.funsoft.com/index-technical.html) that developers may use as a development platform or for unit testing.

Under the z/OS, the management console is still based on TSO for managing jobs and executing console commands interactively. The System Authorization Facility (SAF) manages the security requests by integrating with the Resource Access Control Facility (RACF), and collaborates with LDAP/390 (previously SecureWay Security Manager LDAP Server) to provide Directory Server with some proprietary extensions. Understanding the architecture of z/OS and different mainframe integration options is crucial to building Web Services from legacy applications.

Figure 5-1 shows IBM's z/OS mainframe that has two logical partitions sharing a common high-performance filing system called HFS. Both logical partitions are connected to a Workload Manager and a System Logger, which will allocate workload and service requests to the business applications running on the logical partitions. Each logical partition is a virtual host, running its own operating system with multiple CICS regions, a J2EE application server, a Directory Server, and so forth. Business data is stored in the HFS, and thus it can be shared among different logical partitions. The shared business data is protected under RACF and can be accessed by CICS APPC calls, WebSphere MQ, or other customized data access methods such as VSAM (Virtual Sequential Access Method).

Figure 5-1. IBM z/OS Mainframe Components Overview


The modernized z/OS includes the WebSphere application development environment, where developers can share the same physical mainframe hardware and data resources. WebSphere version 4 is certified to be J2EE-compliant. The legacy database, such as VSAM and IMS, which were only accessible via COBOL/CICS before, can be accessed using a thin client browser. IBM provides Java classes (in jar files) under the CICS Transaction Gateway.

Typically, in a mainframe environment, Web server and application server instances are deployed in the same physical machine or even in the same logical partition. Nevertheless, these instances can be deployed in multiple logical partitions and even interoperate with other Web servers or application servers outside the mainframe.

Linux on Mainframe

The Open Source Linux distribution can be installed in a logical partition under z/OS (this is also known as Linux/390). Applications developed and run on Linux need to be recompiled under z/OS. Under Linux/390, developers can run WebSphere or other Linux-based J2EE application servers. Applications developed under Linux/390 can also access legacy data stored under an MVS partition, for instance, using shared HFS file systems and the Java classes of the CICS Transaction Gateway.

Figure 5-2 describes how the Linux/390 partition can interoperate with other logical partitions (such as MVS operating system) within a z/OS mainframe. As long as the data objects under the Linux operating system are stored in the shared filing system HFS, z/OS is able to provide data access and connectivity to any operating system of other logical partitions within the physical mainframe. Of course, the data access needs to be granted by RACF. Under HFS, if the business data is stored by a Linux application in a relational database such as IBM's Universal Database (previously, DB2), then a CICS/DB2 application from the MVS partition will be able to access the data. If the business data is stored in a proprietary or vendor-specific format, then the business data may look like a blob of binary data to other logical partitions, even though data access right is granted.

Figure 5-2. Linux/390 Interoperating With z/OS and MVS


IBM has been evangelizing Linux on mainframe for the past two years, but there is a limited installation base so far. www.linux390.com provides a good resource regarding the compatibility and implementation issues of Linux on mainframe.

5.3.2. Integration Technology for Legacy Mainframe

There are two different types of integration technology for legacy mainframe systems. The first type is asynchronous messaging, where all service requests and transactions are represented in business documents, and they can be sent via a message-oriented middleware such as WebSphere MQ or a JMS-compliant middleware product. The business documents can be then wrapped in a SOAP envelope and delivered via SOAP messaging over MQ or JMS. The second type is synchronous messaging, where all service requests and transactions are initiated using CICS ECI, EPI, or ESI calls. A server-side SOAP component (SOAP tier or skeleton) can be created to initiate the remote business transactions on the mainframe via these ECI, EPI, or ESI calls. There are a few integration options available, and they will be discussed with some details in this section.

Asynchronous messaging for mainframe integration (such as WebSphere MQ or previously IBM MQ Series) is queue-based messaging, and it does not support real-time processing. Details of WebSphere MQ can be found at http://www-3.ibm.com/software/ts/mqseries/.

In two different books (see “References” at the end of this chapter), Phil Wakelin and his colleagues have identified a few legacy mainframe integration options based on different infrastructure configurations. The business functionality provided by these legacy applications can be wrapped as Web Services using the XML-RPC approach. Wakelin, Benedete, et al. (2002, pp. 13–61) and Wakelin, Keen, Johnson, and Diaz (2002, pp. 9–33) have identified different mainframe integration options. The key implications of the architecture design and how Web Services can be applied will be elaborated in the following sections. There are more resources that discuss different technology options to initiate remote calls to CICS transactions via synchronous messaging in the “Reference” section at the end of this chapter.

Many customer environments do not support a message-oriented middleware infrastructure. Integrating with mainframe systems may be restricted to remote calls to CICS transactions. Thus, this section will cover some details of mainframe integration using synchronous messaging and RPC-based Web Services.

CICS Transaction Gateway
Design Features

The CICS Transaction Gateway (CTG), currently in version 3.1, has the following components:

  • Gateway Daemon— A gateway function that listens to a specified TCP/IP port using TCP, SSL, HTTP, or HTTPS, for Java clients to access CICS applications.

  • Client Daemon— Provides client–server connectivity to CICS applications via External Call Interface (ECI), the External Presentation Interface (EPI), and the External Security Interface (ESI) calls.

  • CTG Java Class Library— ctg.jar is a set of Java classes used to initiate ECI, EPI, and ESI calls and to access VSAM and IMS datasets.

  • Configuration Tool— Is a graphical user interface to configure the properties for the Gateway Daemon and Client Daemon in the CTG.INI file.

  • Terminal Servlet— A Java servlet that emulates the 3270 CICS application.

According to Wakelin, Benedete, et al. (2002) in Revealed! Architecting Web Access to CICS (pp. 13–61), CTG can be deployed in three possible design configurations based on the application architecture (for example, whether the Web server, the application server, and back-end CICS systems are on the same machine), integration strategy (for example, direct connection to CICS with no intermediate component), and performance constraints (for example, whether multiple ports are required to connect to the target CICS applications). The deployment configuration is likely to depend on whether an architects' long-term strategy is to extend the mainframe usage (for example, deploy all Web servers, application servers, and back-end applications on one single mainframe) or to use the mainframe as a Resource Tier (which may allow more technology options to scale up the application services and interoperate the mainframe applications with applications running on other platforms).

Same Platform.

A servlet uses the underlying CICS-proprietary EXCI/MRO protocol, which utilizes a subset of ECI calls, to invoke a remote CICS application. CTG cannot make EPI or ESI calls. The communication between the EXCI program and the target CICS region is a typical SNA connection. The target CICS region must be the CICS Transaction Server version 1.2 or higher. It is not aware that the client request comes from a Java application.

This design configuration is useful when the HTTP Web server, application server, and CICS region reside on the same z/390 machine. It also gives the benefit of invoking native business functions from the existing CICS applications with minimal impact on the back-end architecture design.

Figure 5-3 depicts the design of a CTG running on the same z/390 platform with CICS and the Web server. In this scenario, a SOAP client (using a browser) can initiate a Web Services functionality (such as my mortgage account balance inquiry) provided by the J2EE application server. The remote business service is provided by the back-end CICS application via ECI calls. There is a Java class that exposes the ECI call as a service end-point URL. The SOAP client can initiate an RPC call to the remote business service by looking up the service end-point URL via a Service Registry and invoking it.

Figure 5-3. CTG—Same Platform Design Configuration


Under the same platform configuration, all architecture components residing in the Presentation Tier (such as HTTP Web Server), Business Tier (such as J2EE application server), Integration Tier (such as CTG), and Resource Tier (such as are within the same z/OS machine). (Chapter 4 of this book introduces how to architect service components in different tiers and platform layers.) The reliability, availability, and scalability for each component will be also dependent on the z/OS platform. For instance, the flexibility of the z/OS platform configuration will have a major impact to administrators if they want to increase the physical memory for the J2EE application server only.

Distributed Platforms.

A servlet initiates an SNA APPC or LU 6.2 connection using the CTG Client Daemon with ECI, EPI, or ESI calls. The HTTP Web Server, Application Server, and CICS region reside on different machines. The connection between CTG Client Daemon and the target CICS region is SNA LU 6.2, not TCP/IP.

This design configuration is useful to integrate Web and application servers running on Unix platforms with legacy mainframe CICS. It is also suitable for the design constraint where the legacy mainframe platform cannot be modified or enhanced. The benefit is better scalability for different applications in each tier, and developers do not need to build every component in the same mainframe platform.

Figure 5-4 depicts the design of a CTG running on a different host that communicates with CICS applications on a z/OS host. In this scenario, a SOAP client (using a browser) can initiate a Web Services functionality (such as my mortgage account balance inquiry) provided by the J2EE application server under the Business Tier. The remote business service is provided by the back-end CICS application via ECI, EPI, or ESI calls. There is a Java class that exposes the ECI/EPI/ESI call as a service end-point URL. The SOAP client can initiate an RPC call to the remote business service by looking up the service end-point URL via a Service Registry and invoking it.

Figure 5-4. CTG—Distributed Platform Design Configuration


Under the distributed platform configuration, HTTP Web server resides in the Presentation Tier, and J2EE application server resides in the Business Tier. If the data traffic increases, architects can scale up these components vertically (for instance, by adding CPUs) or horizontally (for instance, by adding other server instances). This allows less complexity and more flexibility to manage scalability and performance tuning on individual server components, when compared to scaling multiple server components within the same mainframe platform.

Figures 5-5 and 5-6 show a Java Front Controller servlet initiating ECI calls and EPI calls, respectively. (Front Controller handles presentation logic, and can be used to initiate Web Services calls. The term Front Controller is discussed in Alur, Crupi, and Malks [2001, pp. 172–185], Core J2EE Patterns.) These program excerpts are extracted and slightly modified from CTG samples for illustration. In the first sample ECI program (Figure 5-5), the objective is to invoke a CICS transaction id, which will return the response in the COMMAREA. Developers need to specify the CTG gateway URL, SSL class name, SSL password, user id, password, server name, and program (transaction id here is PHALL). Then the command ECI Request will initiate the target CICS transaction id (shown in bold). The data and program response can be retrieved from the variable COMMAREA. The rest of the code is similar to a servlet. The sample ECI program (that is modified from the sample programs provided in the CTG software) can be modified slightly and wrapped as an RPC-based Web Services call.

Figure 5-5. Sample CTG ECI Call
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import com.ibm.ctg.client.*;

public class myECI extends HttpServlet
{
    ...
    public void init(ServletConfig sc) throws ServletException
    {
        super.init(sc);
        // specify the gateway URL
        gatewayURL = sc.getInitParameter ("GatewayURL");

        if (gatewayURL == null)
        {
            gatewayURL = DEFAULT_URL;
        }

        gateway = new JavaGateway();

        // specify the SSL class name and password
        String sslClassName = sc.getInitParameter ("SSLClassname");
        String sslPassword = sc.getInitParameter ("SSLPassword");

        if (sslClassName != null && sslPassword != null)
        {

SslJavaGateway.setKeyRing(sslClassName.trim(), sslPassword.trim());
        }
    }

    public void destroy()
    {
        try
        {
            if (gateway!=null)
            {
                if (gateway.isOpen())
                {
                    gateway.close();
                }
            }
        }
        catch (IOException e)
        {
            StringWriter exceptionOut = new StringWriter();
            e.printStackTrace(new PrintWriter(exceptionOut ));
            String trace = exceptionOut.toString();
            log(trace);
        }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
    {
        HttpSession session = request.getSession(true);
        response.setContentType("text/html");
        try
        {
            synchronized(this)
            {
                if (!gateway.isOpen())
                {
                    gateway.setURL(gatewayURL);
                    gateway.open();
                }
            }
            this.displayInitialPage(session, response);
        }
        catch (IOException e)
        {
            this.displayException(e, response, session);
        }
    }

    private void displayInitialPage(HttpSession session, HttpServletResponse response)
 throws IOException
    {
      ...
    }

    private void getServers(PrintWriter out) throws IOException, Exception
    {
        ECIRequest eci = ECIRequest.listSystems(99);
        int returnCode = gateway.flow(eci);

        this.checkReturnCode(returnCode, eci);

        Vector servers = eci.SystemList;

        if (eci.numServersReturned > 0 && servers != null)
        {
            int serverListLength = servers.size();
            boolean display = true;

            out.println("Server:<BR><SELECT NAME = "Server">");
            for (int i = 0; I<serverListLength; i++)
            {
                if (display)
                {
                    out.println("<OPTION VALUE = "" + servers.elementAt(i)
                                + "" >" + servers.elementAt(i));
                    display = false;
                }
                else
                {
                    display = true;
                }
            }
            out.println("</SELECT>");
            out.println("<BR>");
        }
    }

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException
    {
        HttpSession session = null;

        try
        {
            session = request.getSession(true);
            response.setContentType("text/html");

            this.runTransaction(session, request);
            this.displayOutput(response, session);
        }
        catch (Exception e)
        {
            this.displayException(e, response, session);
        }
    }

    private void runTransaction(HttpSession session, HttpServletRequest request)
    throws IOException, Exception
    {
        String userId = request.getParameter ("UserId");
        //  Replace the UserId with your CICS server id
        String password = request.getParameter ("Password");
        //  Replace the Password with your CICS server password
        String server = request.getParameter ("Server");
        //  Replace the Server with your CICS server name
        String program = request.getParameter ("Program");
        //  Replace the Program with your CICS server program name

        int commAreaSize;
        if (program.equals(PHALL))
        {
            commAreaSize = 50;
        }
        else
        {
            try
            {
                commAreaSize = Integer.parseInt(request.getParameter("CommAreaSize").trim());
            }
            catch (NumberFormatException e)
            {
                commAreaSize = DEFAULT_SIZE;
            }

            if (commAreaSize>MAX_COMMAREA_SIZE)
            {
                commAreaSize = MAX_COMMAREA_SIZE;
            }

            if (commAreaSize<MINIMUM_SIZE)
            {
                commAreaSize = MINIMUM_SIZE;
            }
        }

        byte[[]] commArea = new byte[[commAreaSize]];
        ECIRequest eci = new ECIRequest (ECIRequest.ECI_SYNC,
                                        server.trim(),
									userId.trim(),
									password.trim(),
									program.trim(),
									null,
									commArea,
									commAreaSize,
									ECIRequest.ECI_NO_EXTEND,
									ECIRequest.ECI_LUW_NEW);

        int returnCode = gateway.flow(eci);
        this.checkReturnCode(returnCode, eci);
        session.putValue("SESSION_ECI_OBJECT", eci);
    }

    private void checkReturnCode(int returnCode, ECIRequest eci)
    throws Exception
    {
        if (returnCode!=0)
        {
            if (eci.getCicsRc()==0)
            {
                throw new Exception("Gateway exception: Return code number:"
                                    + returnCode
                                    + " Return code String: "
                                    + eci.getRcString());
            }
            else
            {

                if (eci.getCicsRc()==ECIRequest.ECI_ERR_SECURITY_ERROR
                    || (eci.Abend_Code != null
                        && eci.Abend_Code.equalsIgnoreCase("AEY7")))
                {
                    throw new Exception("Server is unable to validate " +
                                        "UserId or password");
                }
                else
                {
                    throw new Exception("CICS exception: Return code number:"
                                        + returnCode
                                        + " Return code String: "
                                        + eci.getCicsRcString());
                }
            }
        }
    }
}

In the following CTG EPI program excerpt (that is modified from the sample programs in CTG software) in Figure 5-6, the objective is to invoke a 3270-based CICS transaction id. The flow events govern the manipulation of data fields and interaction. Developers need to specify the 3270 terminal parameters in the EPIRequest.addTerminal method (shown in bold). Then they initiate the target 3270 screens using the method startTran. Because EPI calls require a series of screen actions and event manipulation, developers can customize the actions in the flowRequest and obtainEvent classes. This may be tedious if many 3270 screens are invoked. The sample EPI program can be modified slightly and wrapped as an RPC-based Web Services call. However, due to the nature of EPI calls, any change in the user interface (such as screen position or screen name) will break the RPC call. Thus, this approach to wrapping EPI calls is not architecturally elegant.

Figure 5-6. Sample CTG EPI Call
import java.io.*;
import com.ibm.ctg.client.*;

public class myEPISample {

   ...
   public static void main(String[[]] args) {
      try {
         ...
         javaGatewayObject = new JavaGateway(myUrl, myPortNumber);
         ...
         flowRequest(myEPIRequest);
         myEPIRequest =
									EPIRequest.addTerminal(myCICSServerName, //CICS server
									null,             //CICS terminal resource name
									null);            //CICS terminal model name
									flowRequest(myEPIRequest);
									myEPIRequest.startTran(null,     // this is the CICS Transid
									mybyteArrayData, //Byte array of 3270 datastream
									// (CANNOT be null)
									7);       //Size of datastream to be passed
									// to Transaction, in bytes
									flowRequest(myEPIRequest);
									obtainEvent(myEPIRequest);

         while (myEPIRequest.getEvent() != EPIRequest.EPI_EVENT_END_TERM) {
            if (myEPIRequest.getEvent() == EPIRequest.EPI_EVENT_END_TRAN) {
               System.out.println(" End of transaction; end reason "
                                  + myEPIRequest.get EndReasonString()
                                  + "
");
               myEPIRequest.delTerminal();
               flowRequest(myEPIRequest);
            } else {
               dumpDatastream(myEPIRequest.data, bDebug);
            }
            obtainEvent(myEPIRequest);
         }
         System.out.println(" Terminal deleted; end reason "
                            + myEPIRequest.getEndReasonString() + "
");
         if (myEPIRequest.getEndReason() != EPIRequest.EPI_TRAN_NO_ERROR) {
            System.out.println(" EPI returned: "
                               + myEPIRequest.get EndReturnCodeString());
         } else {
            System.out.println(" Event type "
                               + myEPIRequest.get EventString()
                               + " Received from CICS.");
            dumpDatastream(myEPIRequest.data, bDebug);
         }

         // Now terminating EPI session

         if (javaGatewayObject.isOpen() == true) {
            javaGatewayObject.close();
         }

      } catch (UnsupportedEncodingException exceptCode) {
         System.out.println("The " + strEncoding + " format is not "
                            + "supported.");
      } catch (Exception exceptCode) {
         exceptCode.printStackTrace();
      }
   }


   private static void flowRequest(EPIRequest myRequest) {
      try {
         int iRc = javaGatewayObject.flow(myRequest);

         switch (myRequest.getCicsRc()) {
         case EPIRequest.EPI_NORMAL:
            if (iRc != 0) {
               System.out.println("
Error from Gateway ("
                                  + myRequest.getRcString()
                                  + "), please correct and rerun this sample");
               if (javaGatewayObject.isOpen() == true) {
                  javaGatewayObject.close();
               }
               System.exit(0);
            }
            return;

         case EPIRequest.EPI_ERR_MORE_EVENTS:
            if (myRequest.getEvent() == EPIRequest.EPI_EVENT_END_TERM) {
               return;
            }
            if (myRequest.getEndReason() != EPIRequest.EPI_TRAN_NO_ERROR) {
               System.out.println(" EPI returned: "
                                  + myRequest.getEndReasonString());
            }
            return;
         }
         System.out.println("
EPI returned: "
                            + myRequest.getCicsRcString());
         if (javaGatewayObject.isOpen() == true) {
            javaGatewayObject.close();
         }
         System.exit(0);

      } catch (Exception exceptCode) {
         exceptCode.printStackTrace();
         System.exit(0);
      }
      return;
   }


   private static void obtainEvent(EPIRequest myRequest) {
      try {
         myRequest.getEvent
         (EPIRequest.EPI_WAIT, //Wait for event
          iBufferSize);        //MAXIMUM size of data to be returned, in bytes
         int iRc = javaGatewayObject.flow(myRequest);
         switch (myRequest.getCicsRc()) {
         case EPIRequest.EPI_NORMAL:
            if (iRc != 0) {
               System.out.println("
Error from Gateway ("
                                  + myRequest.getRcString()
                                  + "), please correct and rerun this sample");
               if (javaGatewayObject.isOpen() == true) {
                  javaGatewayObject.close();
               }
               System.exit(0);
            }
         case EPIRequest.EPI_ERR_BAD_INDEX:
         case EPIRequest.EPI_ERR_FAILED:
         case EPIRequest.EPI_ERR_MORE_EVENTS:
         case EPIRequest.EPI_ERR_MORE_DATA:
         case EPIRequest.EPI_ERR_NO_EVENT:
         case EPIRequest.EPI_ERR_NOT_INIT:
         case EPIRequest.EPI_ERR_WAIT:
         case EPIRequest.EPI_ERR_NULL_PARM:
         case EPIRequest.EPI_ERR_IN_CALLBACK:
            System.out.println(" Event type "
                               + myRequest.get EventString()
                               + " Received from CICS.");
         }

      } catch (Exception exceptCode) {
         exceptCode.printStackTrace();
      }
   }

   private static void dumpDatastream(byte[[]] data, boolean debug) {
      try {
         int total = data.length;
         if (debug == false) {
            System.out.println("
 Data returned: " +
                               new String(data, 2, (total - 2), strEncoding));
            return;
         }
         int row = 0;
         int column = 0;
         int character = 0;
         int width = 16;
         System.out.println("
 Datastream returned:");
         for (row = 0; character < total; row++) {
            System.out.print("   ");
            while ((column < width) && (character < total)) {
               if (data[[character]] != 0) {

System.out.print(Integer.toHexString(data[[character]]));
               } else {
                  System.out.print("  ");
               }
               character++;
               column++;
            }
            System.out.print("   " +
                             new String(data, (row*width), column, strEncoding)
                             + "
");
            column = 0;
         }

      } catch (UnsupportedEncodingException exceptCode) {
         System.out.println("The " + strEncoding + " format is not "
                            + "supported.");
      } catch (Exception exceptCode) {
         exceptCode.printStackTrace();
      }
   }
}

Remote CTG

This is a variant of the previously discussed distributed platforms configuration. The servlet can invoke CICS applications using TCP/IP, SSL, HTTP, or HTTPS protocol. The Gateway Daemon, which resides on the same machine as the target CICS region, will process and forward client requests to the target CICS applications via EXCI. The Gateway Daemon reformats the client requests using the Java Native Interface (JNI).

This design configuration is desirable for achieving a pure TCP/IP-based connectivity (using TCP/IP, SSL, HTTP, or HTTPS) between the client and the server. The benefit is that CTG can configure to work with multiple TCP/IP ports and balance client requests across multiple CICS regions for better scalability if available.

Figure 5-7 depicts the design of a remote CTG, where the CTG Gateway Daemon resides in the remote z/OS platform. In this scenario, a Java server-side program invokes the remote CICS applications in the mainframe via CTG Java classes. It uses an HTTP (or HTTPS) connection to the CTG Gateway Daemon. The CTG Gateway Daemon looks up the configuration context via JNI and invokes the CICS executable EXCI. EXCI is able to route ECI, EPI, or ESI calls to the relevant CICS applications. The data parameters for the CICS calls, or the transaction result fetched after the CICS calls, can be placed in the common area region COMMAREA.

Figure 5-7. Remote CTG Design Configuration


Implication

CTG provides wider integration options for architects who do not desire the Web-based functionality tightly coupled with the legacy CICS platform. Architects can deploy CTG on Unix or Windows platforms with a distributed server topology (n-tier architecture). This enables more options to scale up the capacity. Invoking legacy CICS applications using ECI calls with CTG can shield off complex SNA LU 6.2 protocols from developers. This does not require architects and developers to have an in-depth knowledge of the legacy mainframe systems.

The choice of CTG configuration depends on the server topology (same platform, distributed platforms, or remote CTG). Architects need to make conscious design decisions up front when choosing which CTG configuration to use, as switching to other configuration in the midst of or after deployment could be painful.

To enable Web Services using CTG, architects and developers need to generate an XML-RPC call (for example, using Java Web Services Developer Pack's wscompile or Apache Axis's org.apache.axis.wsdl.wsdl2 java utility; refer to the exercises in the chapters Web Services Technology Overview and The Next Frontiers for details) from a Java client that initiates ECI, EPI, or ESI calls. If they are using ECI calls, they need to identify the target CICS transaction id and check out whether any modification to the existing CICS applications or COMMAREA is required. If they are using EPI calls, they may need to ensure the data fields in the legacy 3270 screens have not changed, otherwise they must update the EPI calls. If the legacy mainframe functionality is likely to be reused by multiple parties, it is more scalable and reusable to use Java technology approach (such as EJB or JCA) to enable them as Web Services.

CICS Web Support
Design Features

ICS Web Support (CWS) comes with CICS Transaction Server for OS/390 or VSE version 1.3. These are CICS-supplied programs, which provide ASCII-to-EBCDIC code page conversion (Web Attach Processing programs CWXN, DFHCNV, and Analyzer), conversion between 3270-based screens and HTML pages (3270 Web Bridge), decode/encode for Web page presentation logic (Alias Transaction program including CWBA), and analysis of HTTP requests to invoke CICS applications (Alias Transaction program or Business Logic Interface).

There are three different design configurations when using CWS, as shown in Figure 5-8:

Figure 5-8. CWS Overview—Three Different Design Configurations


Direct Connection

A client browser can directly connect to CICS applications via the CICS Web Support programs CWXN (Web Attach Transaction) and CWBA (Alias Transaction). This requires the installation of an OS/390 Communications Server and assumes the use of the CICS TCP/IP Listener (CSOL) to be running under the CICS region, which intercepts HTTP requests over TCP/IP via a CICS Socket. The HTTP request header and input data need to be converted to EBCDIC using the DFHCNV conversion program. The Analyzer program will then process the incoming HTTP request to look up the alias name (the default CWBA transaction code is DFHWBA), the converter program, the user id, and the user program of the target CICS region (refer to Figure 5-9).

Figure 5-9. CWS Direct Connection


This design configuration is appropriate when developers do not require an HTTP Web Server but use the CICS TCP/IP Listener to process HTTP requests. The benefit is that there is no architecture change in the legacy CICS applications on the VSE platform in order to invoke legacy CICS applications from a client browser. The current limitation is that CICS Web Support only allows a maximum of 32KB of data to be received and utilized by the application. With direct connection to CICS without a Web Server, compliance with Open Standards and subsequent integration would be difficult.

Figure 5-9 elaborates the process of direct connection with more details. The browser client issues an HTTP request to access a Web server, which will route the HTTP request to the communications server. The communications server determines that this is a request to access CICS resources in the Resource Tier. It intercepts the CICS resource requests from the CICS Socket (CSOL). The Web Attach program CWXN and the Alias program CWBA (these are CICS programs running in the same CICS region) handle the conversion of the code page from ANSI to EBCDIC (which the mainframe can understand). The DFHCNV process converts input data from the HTTP request to ASCII, which will then be converted to EBCDIC. The CWXN analyzer will look up the alias name, converter, user id, and user program before passing the CICS request to the Alias program CWBA (default is DFHWBA, and the alias program can be customized). The Alias program CWBA functions as a converter, which encodes and decodes CICS data. It then invokes the appropriate user application program to process the CICS requests. It receives the presentation logic decoded in CICS format. It sends the CICS results in encoded data that can be handled by the presentation logic (such as HTML Web pages).

A SOAP server-side component (also called the SOAP tier or SOAP skeleton) can be created to wrap the CICS request using a CICS Socket and the CICS Web Support programs. This approach is suitable if there are browser-based programs currently accessing the back-end CICS resources via a CICS Socket. It can also create a new information aggregation Web Service (such as aggregating my personal wealth portfolio from different bank accounts) by collaborating with Web Services information aggregation tools (such as bowstreet). Nevertheless, the CICS Web Support technology heavily relies on 3270 screens (via 3270-to-HTML conversion), and it may not be a scalable approach to extend new functionality.

A sample DFHCNV ASCII-to-HTML code page conversion configuration may look like the following (see Figure 5-10):

Figure 5-10. Sample DFHCNV Conversion Configuration
DFHCNV TYPE=INITIAL
*
DFHCNV TYPE=ENTRY,RTYPE=PC,RNAME=DFHWBHH,USREXIT=NO,
SRVERCP=037,CLINTCP=8859-1
DFHCNV TYPE=SELECT
DFHCNV TYPE=FIELD,OFFSET=0,DATATYP=CHARACTER,DATALEN=32767,
LAST=YES
*
DFHCNV TYPE=ENTRY,RTYPE=PC,RNAME=DFHWBUD,USREXIT=NO,
SRVERCP=037,CLINTCP=8859-1
DFHCNV TYPE=SELECT
DFHCNV TYPE=FIELD,OFFSET=0,DATATYP=CHARACTER,DATALEN=32767,
LAST=YES
*
DFHCNV TYPE=FINAL
END

CICS Web Server Plug-in

Figure 5-11 depicts the interaction process between components when using the CICS Web Server Plug-in. The proprietary program DFHWBAPI, a CICS Web Server Plug-in, runs on top of the IBM HTTP Server. It performs the same functionality as the previously mentioned Web Attach Transaction, which invokes the ASCII-to-EBCDIC code page conversion routine. It also builds an EXCI request, decodes the HTTP requests into CICS transactions, and passes the HTTP data stream to the Business Logic Interface for CICS applications in the COMMAREA.

Figure 5-11. CTG Web Server Plug-in


This design configuration is useful when the HTTP Web Server and the target CICS region reside on the same machine and the same sysplex, and developers do not want to add another middleware such as the CICS Transaction Gateway. It has similar advantages and disadvantages as other CWS design configurations.

A server-side Web Services component can be created to invoke remote business functionality residing in the back-end CICS region via DFHWBAPI. The SOAP server tier (or SOAP skeleton) can initiate the EXCI call. It is a simpler architecture to access CICS resources compared with the previous direct connection or the 3270 Web Bridge depicted below.

3270 Web Bridge

Figure 5-12 depicts the interaction process between components using the 3270 Web Bridge. HTTP requests from the client browser can be processed via the Web Attach Transaction and Alias Transaction (that is, Direct Connection design configuration), or the CICS Web Server Plug-in. If these requests and responses need to be formatted and presented in 3270 screen maps or HTML, then 3270 Web Bridge is a flexible solution for 3270-to-HTML conversion using a 3270 HTML conversion program and an HTML template rule database. 3270-based CICS applications (in this example, myapps1) can then be invoked by a URL directly from the host mycics.nextfrontiers.com using port 8080 (for example, http://mycics.next frontiers.com:8080/cics/cwba/dfhwbtta/myapps1).

Figure 5-12. CWS—3270 Web Bridge


The excerpt in Figure 5-13 shows a sample BMS mapset definition using the DFHWBOUT and DFHMDX macros (highlighted in bold). The DFHMDX macro maps 3270 data fields to the HTML data fields and attributes.

For 3270 screen mapset and HTML mapping, Eugene Deborin and his colleagues (1999, pp. 257–308) discuss the details of how to define the mapping using a DFHMAPT procedure with the mapset definition macros DFHWBOUT, DFHMDX, DFHMDI, DFHMDF, and DFHMSX.

This design configuration is useful to facilitate easy mapping between 3270 screen maps to HTML conversion using an HTML template rule engine. Nevertheless, the screen mapping is tedious and unavoidably labor-intensive. Chris Smith (2001) has identified a few restrictions on the 3270-to-HTML conversion capability (for example, no dynamic modification of attribute bytes and BMS paging not supported, among others).

Similar to the scenario of using a CICS direct connection, a server-side Web Services component can be created to wrap the CICS request using a CICS Socket and the 3270 Web Bridge. This approach is suitable if there are browser-based programs currently accessing the back-end CICS resources via a CICS Socket and a 3270 Web Bridge. It can also create a new information aggregation Web Service (such as aggregating my home and utility phone bills from different service providers) by collaborating with Web Services information aggregation tools (such as Bowstreet). Nevertheless, the 3270 Web Bridge technology heavily relies on 3270 screens (via 3270-to-HTML conversion), and it may not be a scalable approach to extend new functionality.

Figure 5-13. Sample 3270 Mapset-to-HTML Mapping
TITLE 'Testing display with 3270 bridge '
PRINT ON,NOGEN
PHALLGRP DFHMSD TYPE=MAP,LANG=COBOL,MODE=INOUT,STORAGE=AUTO,SUFFIX=
TITLE 'BMS: PHALLPNL PHALLPNL '
PHALLPNL DFHMDI SIZE=(24,80),MAPATTS=(COLOR,HILIGHT),DSATTS=(COLOR), *
COLUMN=1,LINE=1,DATA=FIELD,TIOAPFX=YES,OBFMT=NO
* -----------------------------------
DFHWBOUT 'DFHWBOUT places text in the HTML header and adds text to HTML page'
*
DFHMDX MAPSET=PHALLGRP,MAP=PHALLPNL, X
TITLE='3270 Web bridge Test Transaction', X
BGCOLOR=#F4CEC4, X
PF3=EXIT, X
ENTER=SUBMIT, X
RESET=NO, X
SUPPRESS=((23,1),(24,1))
* -----------------------------------
DFHMDF POS=(1,1),LENGTH=8,INITIAL='JUL/2001',ATTRB=(ASKIP,NORM*
)
DFHMDF POS=(1,63),LENGTH=16,INITIAL='ACBJ3270.PHALLPNL', *
ATTRB=(ASKIP,NORM)
DFHMDF POS=(2,34),LENGTH=13,INITIAL='Prentice Hall', *
ATTRB=(ASKIP,BRT),COLOR=RED
DFHMDF POS=(4,25),LENGTH=31, *
INITIAL='Java Web Services Book',ATTRB=(ASKIP,B* RT),COLOR=NEUTRAL
DFHMDF POS=(6,25),LENGTH=32, *
INITIAL='3270 Web bridge Test Transaction',ATTRB=(ASKIP,*NORM)
DFHMDF POS=(11,29),LENGTH=9,INITIAL='Option =>',ATTRB=(ASKIP,N*ORM)

To use the 3270 Web Bridge, developers need to configure some specific parameters during the CICS Transaction Server system setup (for example, TCPIP=YES, WEBDELAY=(terminal-wait-time, state-data-keep-time)) and increase EDSA storage. Most of the CICS-related configuration is lengthy but straightforward. A basic knowledge of Web servers and HTML is essential. However, not all CICS applications may work unchanged. Please refer to Chris Smith (2001) for more details.

Implication

CWS provides a simple pan-CICS design approach to Web-enabling legacy CICS applications from a URL. This technology does not require installing additional application servers or gateway components, and thus it is lightweight. Nevertheless, the integration capability will be constrained by 3270 screen-based or EPI-based technologies. In other words, if developers want to manipulate any data or to invoke a specific business function where there is no CICS screen available, then they have to modify the back-end applications or perhaps create a new CICS screen.

There is a misconception that any browser-based application is a Web Services solution. With CWS and SNA gateway technology, it is possible to access mainframe applications from a browser. CWS technology handles the conversion from CICS to HTML Web pages. This is not a real Web Services solution because CWS does not generate an XML message containing the data contents required from the legacy systems. Architects and developers need to wrap the HTML data fields in a SOAP message or create another XML-RPC to wrap the data contents generated from CWS. Thus, it would be more flexible to use Java technology to enable Web Services.

Java Technology
Design Features

IBM has implemented the Enterprise Java Bean (EJB) Server in the CICS Transaction Server version 2.1. The EJB environment includes TCP/IP Listener, request receiver (DFHIIRRS), request models, request stream directory (DFHEJDIR), request processor, EJB container, object store (DFHEJOS), Java Virtual Machine, CORBA server, and deployed JAR files. Wakelin, Benedete, et al. (2001, pp. 32–34) have details depicting the EJB server components in CICS, and how it operates. Using Java technology to integrate and interoperate with legacy mainframe applications is simpler and architecturally cleaner. The following sections discuss variants of Java technology that can be wrapped as Web Services.

EJB Support

The use of EJB enables a legacy CICS application to be delivered as a session bean and legacy data to be accessed or updated as an entity bean. The EJB container manages the life cycle of the beans. In other words, it provides session management, ensures data integrity, and enables database connection pooling for better performance and scalability. With the support of EJB, a client browser can invoke a servlet (usually presentation logic), which in turn initiates session beans from the local server or a remote CICS region (CICS Transaction Server EJB Server). (See Figure 5-14).

Figure 5-14. CICS EJB Support


Figure 5-14 shows that architects can create an EJB Web Service, which can be a stateless EJB (either a session bean or an entity bean) invoking RPC calls to CICS resources via CICS Transaction Server version 2.1 EJB Server. The EJB handles the session information using session beans, manages business data residing in the back-end database (such as DB2) using entity beans, and communicates with other service components using a Message Driven Bean (MDB) and Java Messaging Service (JMS). Entity beans from the J2EE application server can exchange business data with another entity bean residing on the EJB server of the back-end mainframe via the RMI/IIOP protocol. The benefit of using EJB Web Services is that EJB has built-in functionality to manage the life cycle of the session, business data with connection pooling, and session failover. This is appropriate for handling business transactions.

Java Connector for CICS

The Java Connector Architecture (JCA) is a more structured way to provide Open Standards-based connectivity to legacy systems and database resources. For each connection, the Java connector establishes a “service contract” with the target legacy systems. This standardizes the effort to customize different legacy systems, as well as reduces the development effort for proprietary interfaces. Please refer to the chapter Enterprise and Cross-Enterprise Integration for more details.

Legacy mainframe systems can be wrapped as Web Services by using Java Connectors. For instance, a SOAP client (or an EJB Web Service) can invoke a stateless EJB that handles online bill payment for telephone services and utilities. The stateless EJB is connected to a back-end mainframe CICS application using a Java Connector. The benefit is that Java Connector is a standards-based connectivity with legacy back-end systems, and developers do not need to build proprietary extensions to integrate with legacy technologies such as CICS applications.

The excerpt in Figure 5-15 is extracted and modified from sample EJB programs from IBM CICS Transaction Gateway using Java Connector for CICS. It illustrates a stateless session bean that initiates “ECIInteractionSpec” with key methods highlighted in bold. In essence, the connection to CICS using ECI calls requires creating an ECIInteractionSpec instance. Once the ECIInteractionSpec instance is created with the required attributes set (for example, setCommaLength, setReplyLength), the CICS transaction id (in this example, PHALL) will be invoked. Developers can customize their provider class and connection factory methods under getConnection().

Figure 5-15. Sample Java Connector for CICS Using ECI Calls
import com.ibm.connector2.cics.*;
import javax.resource.cci.*;
import java.rmi.RemoteException;
import javax.resource.*;
import javax.ejb.*;

public class myEJBwithECI implements SessionBean {
    private javax.ejb.SessionContext mySessionEJB;
    transient private Connection eciConn;
    transient private Interaction eciInt;
    transient private ECIInteractionSpec eciSpec;

    public void ejbCreate() throws javax.ejb.CreateException, java.rmi.RemoteException {
        eciSpec = new ECIInteractionSpec();
    }
    ...
    public String execute() throws ResourceException, Exception {

        getConnection();

        JavaStringRecord jStringRec = new JavaStringRecord();

        eciSpec.setCommareaLength(20);
									eciSpec.setReplyLength(20);
									eciSpec.setFunctionName("PHALL");  // CICS transaction id
									eciSpec.setInteractionVerb(ECIInteraction Spec.SYNC_SEND_RECEIVE);

        try {
            eciInt.execute(eciSpec, jStringRec, jStringRec);
        }
        catch (ResourceException resEx) {
           ...
        }
        dropConnection();
        return jStringRec.getText();
    }
    ...

    private void getConnection() throws Exception {

        ConnectionFactory connFactory = null;

        try {
            javax.naming.Context iContext = new javax.naming.InitialContext();
            connFactory = (ConnectionFactory)iContext.lookup("java:comp/env/ECI");
        }
        catch (Exception resEx) {
           ...
        }
        ...
    }

    private void dropConnection() {

        try {
            eciInt.close();
            eciConn.close();
        }
        catch (Exception resEx) {
            resEx.printStackTrace();
        }
        eciInt = null;
        eciConn = null;
    }
}

Web Services Support

Legacy CICS applications using CTG and/or CICS EJB Server can be easily enabled as Web Services. Developers need to identify the business functionality as coarse-grained Web Services. In other words, not all methods or APIs need to be exposed as XML-RPC. Do not define each CICS transaction id or program name as an individual Web Service call. It is a good practice to define a few Web Services, where different methods or APIs can be invoked by passing parameters to the Web Services call. The same principle holds when creating EJBs—it is not necessary to map each EJB to an individual Web Services call.

Wrapping Java beans or methods using CTG and/or CICS EJB Server on a mainframe platform as XML-RPC Web Services calls is similar to doing so on a Unix or a Windows platform. Examples of the tools include the Java Web Services Developer Pack's xrpcc and Apache Axis's wsdl2java.

Implication

Unfolding the mystery of mainframe integration and interoperability can facilitate and ease enabling Web Services on legacy CICS applications. Hewitt Associates (U.S.), as reported in Hilgenberg and Hansen (2002), dedicated two to three architects to enable Web Services for their legacy HR services on z/OS within three to four months. They note that the critical success factor is the right architecture that can be scalable and reliable to support up to 4 million transactions per day.

SOAP Proxy on Mainframe

It is possible to enable legacy CICS applications as Web Services without using any of the three technology options. The Sun ONE Integration Server EAI edition (previously Forte 4GL for OS/390) has utilized Apache SOAP and a customized transaction adapter to provide SOAP messaging.

Design Features

Figure 5-16 depicts the high-level application architecture. Apache SOAP (SOAP proxy) must be installed under the Unix Services of the OS/390. For instance, the Sun ONE Integration Server has a customizable adapter (known as the Forte Transaction Adapter), which runs under the MVS of the OS/390, and communicates with local or remote CICS, VSAM, and IMS resources using the LU 6.2 protocol. There is a server portion of the adapter (the application proxy with a transaction adapter) running under the OS/390 Unix Services partition, which acts as an APPC client to the CICS applications of the local or remote CICS. The Forte Transaction Adapter (acting as an APPC client) receives data in a data buffer (aka COMMAREA) from the APPC conversation and provides a proxy function that can be accessed from the client browser. The proxy can be exposed as a SOAP proxy using Apache SOAP (or Apache Axis) to support XML and SOAP messaging.

Figure 5-16. SOAP Proxy on Mainframe


The Sun document Using Forte 4GL for OS/390 (2000, pp. 49–74), provides four sample programs for illustration. The excerpt in Figure 5-17 depicts the Forte Transaction Adapter establishing an APPC conversation with the remote CICS application FR02 using the method APCApiSO.NewConversation. Upon successful connection, it initiates an APPC conversation verb or data request in the data buffer using the method conv.Write. Under the synchronous APPC conversational programming, the remote CICS application will respond by placing the response or data contents in the data buffer. The transaction adapter can simply retrieve the data using the method conv.Read, and close the conversation.

Figure 5-17. Sample Program Excerpt for Forte Transaction Adapter for a Remote CICS Transaction
--
-- Step 1:
-- Create an APPC session
conv = APPCApiSO.NewConversation();

-- Create COBOL buffer and COBOL field objects
buf : COBOLBuffer = new;
cobAddress: COBOLField = new;
cobAmount: COBOLField = new;
cobComment: COBOLField = new;
cobDate: COBOLField = new;
cobName: COBOLField = new;
cobNum: COBOLField = new;
cobPhone: COBOLField = new;
cobRecStat: COBOLField = new;
cobStatus: COBOLField = new;

-- Define COBOL record layout
loc = cobStatus.Define(location=0,picture='X',usage='DISPLAY'),
loc = cobNum.Define(location=loc,picture='X(6)',usage='DISPLAY'),
loc = cobName.Define(location=loc,picture='X(20)',usage='DISPLAY'),
loc = cobAddress.Define(location=loc,picture='X(20)',usage='DISPLAY'),
loc = cobPhone.Define(location=loc,picture='X(8)',usage='DISPLAY'),
loc = cobDate.Define(location=loc,picture='X(8)',usage='DISPLAY'),
loc = cobAmount.Define(location=loc,picture='X(8)',usage='DISPLAY'),
loc = cobComment.Define(location=loc,picture='X(9)',usage='DISPLAY'),
loc = cobRecStat.Define(location=loc,picture='X',usage='DISPLAY'),
reclen = loc;

-- Step 2:
-- Establish APPC conversation with target CICS
dest = 'FRTCEXSI'; — must match your symbolic destination name
tp = 'FR02'; — must match your CICS transaction name
conv.Open(dest=dest,tp=tp);

-- Step 3:
-- Send input data to CICS
len = custRec.NUM_LENGTH;
conv.Write(dataBuffer=custRec.Num,writeLength=len);

-- Step 4:
-- Receive data response from CICS
len = reclen;
conv.Read(dataBuffer=buf,readLength=len);
							

Implication

IBM has been dominant in providing mainframe integration and interoperability technology tools. The Sun ONE Integration Server provides an alternative approach to using Apache SOAP and APPC technology. Tracking the history, Forte 4GL and its application proxy have been around since before SOAP was available. Architecturally, Forte 4GL and its Application Proxy are similar to the SOAP proxy concept, and the Forte Application Proxy can be exposed as a SOAP proxy using Apache SOAP (or Axis). This has provided a more open platform approach to addressing the mainframe interoperability challenge.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.140.206