Connecting from Groovy to CICS using the CICS Transaction Gateway

This article shows you how to use modern agile scripting languages to increase your productivity when writing applications to access CICS data. It demonstrates how quickly you can write a standalone GUI front end to CICS transactions by combining the Groovy programming language and the plain old Java object (POJO) interface provided by CICS Transaction Gateway (CICS TG). The article provides a simple example in which you create a GUI utility that lets systems administrators validate connectivity with CICS TG and back-end CICS systems.

Simon Knights (sknights@uk.ibm.com), Software Developer, IBM

Photo of Simon KnightsSimon Knights is a Software Developer at IBM. He has worked for more than 10 years on CICS Transaction Gateway as both a Developer and Level-3 Technical Support Specialist. You can contact Simon at sknights@uk.ibm.com.



Russell Wilson (wilsonrs@uk.ibm.com), Software Engineer, IBM

Photo of Russell WilsonRussell Wilson is a Software Engineer at IBM. He has worked for more than 10 years on CICS Transaction Gateway and is currently a Level-3 Technical Support Specialist. You can Russell at wilsonrs@uk.ibm.com.



27 October 2010

Introduction

What are CICS and CICS TG?

IBM® CICS® is a transaction server designed for high-volume online processing and capable of many thousands of transactions per second. CICS Transaction Gateway (CICS TG) is a market-leading enterprise connector that provides access to CICS transactions from a wide variety of environments and runtimes, including C, C++, COBOL, J2EE, Java, and Microsoft® .NET.

What is Groovy?

Groovy is a dynamic object-orientated language that combines many of the features of Python, Ruby, and Perl, and closely integrates with the Java™ platform. It simplifies the Java syntax, gives you full access to Java functionality, and provides features not found in standard Java. Groovy applications can exploit Web 2.0 situational application development applications such as WebSphere sMash, take advantage of open source rapid development frameworks such as Grails, and use Groovy plug-ins developed by an active open source community. For examples of what you can do with Groovy, see the two developerWorks article series Practically Groovy and Mastering Grails.

Overview of the CICS TG API

CICS TG supports multiple application deployment topologies. In our example, you use the remote topology where a client application connects to a Gateway that issues requests to a CICS server. You will use JavaGateway and ECIRequest classes provided by the CICS TG Java API. JavaGateway represents a logical connection between a client application and CICS TG Gateway. ECIRequest represents a request to CICS using the External Call Interface (ECI). CICS TG also provides 3270 emulation (EPI) and security (ESI) APIs. For more information, see the CICS TG V7.2 information centre. An ECI request transfers data with CICS using a Communication Area (COMMAREA) or channels interface. A COMMAREA can represent any data, such as timestamps, customer information, and account details. For our simple utility, the COMMAREA deals with an ASCII date and timestamp. For a detailed description of the available APIs, see the CICS TG V7.2 information centre.

Introduction to the example

You will build a simple Groovy script to an extensible GUI application using the following steps:

  1. Invoke the CICS TG API from a simple Groovy script.
  2. Refactor script into an abstract reusable controller class to handle interaction between CICS and the user interface.
  3. Create a command-line utility to verify connectivity with CICS.
  4. Create a GUI version of the command-line utility.

Prerequisites

  • A copy of CICS TG installed and configured to communicate to a CICS system.
  • The CICS TG supplied EC01 transaction is installed in the target CICS system. EC01 returns the date and time, and is used like a "Hello world" transaction in CICS TG applications.
  • A DFHCNV macro configured on CICS to correctly translate the response from CICS into ASCII.
  • Groovy and Java runtimes are installed so that you can develop and run Groovy applications. For information on how to set up a Groovy development environment and get started programming in Groovy, see the developerWorks article Fluently Groovy.

CICS TG V7.2 provides a server remapping function so that the application does not need to explicitly specify a server name.

Invoking the CICS TG API from a simple Groovy script

First you need to ensure that the CICS TG classes are located on the classpath:

set CTGCLASSDIR=C:\Program Files\IBM\CICS Transaction Gateway\classes 
set CLASSPATH="%CLASSPATH%;%CTGCLASSDIR%\ctgclient.jar;"

Your Groovy application must import the relevant CICS TG API:

import com.ibm.ctg.client.*

To connect through to CICS, the Groovy application must first establish a JavaGateway object to let it connect through CICS TG. In this example, you communicate with a Gateway daemon running on the local system that passes requests to CICS:

def gateway = new JavaGateway("tcp://localhost",2006)

To handle the data being returned from CICS, you need a byte array object to use as the COMMAREA:

def commarea = new byte[18]

Next, you need to create an object that represents the request that will be executed on CICS. ECIRequest has several constructors and a mixture of getter methods and public variables. In Java you need to determine which constructor is most suitable, which fields to set within the constructor, and whether the fields are accessed through a getter, setter, or directly. In Groovy, you simply instantiate a basic request object and set the specific fields required:

def request = new ECIRequest(Server:"TMSTXS2",
    Program:"EC01",
    Commarea:commarea)

Compare this to the equivalent code in Java:

ECIRequest request = new ECIRequest(ECIRequest.ECI_SYNC, 
    "CICSTEST",
    null, null, "EC01", 
    null, commarea);

Now that you have a request object, use the JavaGateway's flow method to send the request to the target CICS system:

...
gateway.flow(request)
...

You needed only 8 lines of code to make a complete request to a CICS system! Of course, you need to be able to verify that the request completed successfully and the result was returned from CICS:

if (request.cicsRc==ECIRequest.ECI_NO_ERROR) {
    println "success!"
    print "\nResult in ASCII:\t"
    print new String(commarea)
} else {   
    println "request failed with ${request.cicsRcString}"
}

The code illustrates some nifty Groovy features:

  • Direct access to the cicsRc variable through an implied getter
  • Inline access to variables within strings through the ${...} syntax
The complete source to connect to CICS
    import com.ibm.ctg.client.*
// Create a connection object to the Gateway
def gateway = new JavaGateway("tcp://localhost",2006)
// Create a byte array to send and receive data from the server
def commarea = new byte[18]
// Create an object which holds the request parameters
def request = new ECIRequest(Server:"CICSTEST",
        Program:"EC01",
        Commarea:commarea)
// Flow the request
gateway.flow(request)
// Check it completed OK
if (request.cicsRc==ECIRequest.ECI_NO_ERROR) {
    println "success!"
    print "\nResult in ASCII:\t"
    print new String(commarea)
} else {   
    println "request failed with ${request.cicsRcString}"
}

Refactoring into a reusable controller object

The first section demonstrated how to issue a basic request on a CICS system. In real life, you would want to issue more than one call to a CICS system and deal with runtime network errors. You might also want to encapsulate the CICS TG logic to keep CICS TG code out of the presentation layer. Although this article deals with a simple example, rather than a real-world example, refactoring is a useful exercise because it demonstrates some code-saving features of Groovy and simplifies the GUI example in the next section. Start by creating a Groovy bean that contains all the data necessary to communicate with CICS:

public class CTGController{
    String gatewayURL     
    int  gatewayPort
    JavaGateway gateway
    String servername
    String program
    Byte[] commarea
    String result
    boolean success 
}

Groovy autogenerates boilerplate material such as getters and setters and makes methods public by default. Then create methods to:

  • Establish communication with the Gateway daemon
  • Execute requests against CICS
  • Close the connection with the Gateway daemon
boolean connect() throws IOException{
    }
void close() {
    }
boolean executeRequest() {
    }    ...

Code each method using the logic in the script. To issue a call to CICS using the new class, a Groovy script can simply instantiate a CTGController object, initialize the required properties, and then issue connect() and executeRequest() calls. After a call to executeRequest, the return code from the method indicates whether the call was successful. If the call succeeded, the result string will contain the COMMAREA contents; if the call failed, the result string will contain error text. If the connect, close and executeRequest methods were called in the wrong order by the presentation layer, or if a network exception (IOException in the Gateway API) occurred, you could end up with a null reference to the JavaGateway object. You can deal succinctly with this problem by using the Safe Navigation Operator. Insert a ? before a reference to prevent a NullPointerException from being thrown in the event of the object being null. For example:

public void close() throws IOException {
    gateway?.close()
}

replaces the equivalent Java code:

    public void close() throws IOException {
        if (gateway!=null) {
           gateway.close();
        }
    }

In another example, you can combine Groovy truth with the safe navigation operator to replace: if (gateway==null || !gateway.isOpen()) { with if (!gateway?.isOpen()){ .

This code works because the safe navigation operator returns null if it's asked to operate on a null method, and Groovy evaluates null as false. Therefore, the gateway reference being null and the gateway being closed both evaluate to the same thing. Here is the complete source code for the CTGController class:

import com.ibm.ctg.client.*;
    public class CTGController{
    String gatewayURL     
    int  gatewayPort
    JavaGateway gateway
    String servername
    String program
    Byte[] commarea
    String result
    boolean success 
     
        void connect() throws IOException{
            gateway = new JavaGateway(gatewayURL, gatewayPort)
    }
    void close() throws IOException {
            gateway?.close() 
        }

        boolean executeRequest() {
            commarea = new byte[18]	// Ensures a "clean" byte array 
            ECIRequest request = new ECIRequest(Server:servername,
                Program:program,
                Commarea:commarea)
            try{
                if (!gateway?.isOpen()){ 
                    success = false // problem encountered
                    result = "Connection to Gateway has not been initialised"
                } else {
                    gateway.flow(request)
                    if (request.cicsRc==ECIRequest.ECI_NO_ERROR) {
                        result = new String(request.Commarea)
                        success = true	// no issues during call
                    } else {
                        result = request.cicsRcString
                        success=false	// CICS returned an error
                    }
                }
            } catch (IOException ioe){
                success = false	// problem encountered
                result = ioe	// store exception for display later.
            } 
            return success
        }
    }

Writing a command-line utility to verify CICS connectivity

When the controller class has been created, you can write a sample Groovy script using the class in a few lines of code:

Sample command-line script.
    def controller = new CTGController()
    controller.gatewayURL="tcp://localhost"
    controller.gatewayPort=2006
    controller.servername="testcics"
    controller.program="EC01"
    controller.commarea=new byte[18]
    controller.connect()
    def maxiterations = 10
    maxiterations.times{
        print "Call ${it} - "  (check)
            if (!controller.executeRequest()){
                println "Error during request, error text ${controller.result}"
            } else {
                println "Call completed, result : ${controller.result}"
            }
    } 
    controller.close()

Writing a GUI utility to verify CICS connectivity

Use the Groovy SwingBuilder to create our GUI application. SwingBuilder is based on the Groovy markup generator. It uses a tree-based syntax. You create a closure to represent a parent object such as a panel or frame and simply declare child objects such as buttons or text fields inside. You can also use closures in place of inner classes, which reduces the need to instantiate objects, set values, create inner classes, maintain references, and attach child objects to parents, which are all typical in Java GUI applications. The syntax is the same as for other markup builders that are used to create XML and HTML documents in Groovy. Start by creating a simple GUI:

import groovy.swing.SwingBuilder
import javax.swing.*
def swing = new SwingBuilder()
swing.frame(title:"CICS TG Groovy Sample GUI", 
    size:[400,200], 
    defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE) {
}.show()

This creates a small window with the title "CICS TG Groovy Sample GUI". To this you must add some buttons that will let you interact with your CTGController class and a status area for displaying output:

import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.BorderLayout
def swing = new SwingBuilder()
def statusArea

swing.frame(title:"CICS TG Groovy Sample GUI", 
    size:[400,200], 
    defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE) {
borderLayout()    // Use a border layout for positioning components
statusArea = textArea(text:"Awaiting command...",lineWrap:true,editable:false)
button(text:"Click to connect...", constraints:BorderLayout.NORTH)
button(text:"Click to send a request", constraints:BorderLayout.SOUTH)
}.show()

You now need to cause the button presses to execute the appropriate interaction with the CTGController class. This is done by the actionPerformed property of the buttons. Note that you need to ensure that you import the required CICS TG classes and define a CTGController object with suitable properties:

...
button(text:"Click to connect...", 
    constraints:BorderLayout.NORTH,
    actionPerformed: {
        try {
            controller.connect()
            statusArea.text = "Connection to Gateway 
                ${controller.gatewayURL}:${controller.gatewayPort} established..."
        } catch (IOException ioe){
            statusArea.text = "Connection to Gateway failed, 
                exception text follows:\n${ioe}"
        }
    })
button(text:"Click to send a request", 
    constraints:BorderLayout.SOUTH,
    actionPerformed: {
        controller.executeRequest()
        if (controller.success) {
        statusArea.text = "Call completed successfully.\nCommarea = ${controller.result}"
        } else {
            statusArea.text = "Request failed, failure text:\n ${controller.result}"
        }
    })

You now have a complete application that will establish communication through CICS TG and then attempt to flow work to CICS. To make the application more robust and usable, now add an extra button, Close, that will close the connection to the Gateway. To ensure that there is only one connection to the Gateway established at any instance, the Connect and Close buttons will be configured to toggle between enabled and disabled to indicate the current state of the connection. To add the extra button, create a new button panel to hold both the Connect and Close buttons. Simply adding the second button to the existing location Constrations.BorderLayout.North will result in only the close button being visible because of the default layout manager. By explicitly creating your own button panel and adding the buttons, you can control their locations precisely. First you need to define two new fields to hold references to the button objects to allow you to modify their properties later:

...
def statusArea
def connectButton
def closeButton
...

You then need to replace the current code that handles the current button with code that will create your button panel and add the two buttons to that panel:

Source code for CICS TG Groovy Sample GUI
import java.awt.*;
import groovy.swing.SwingBuilder
import com.ibm.ctg.client.*
import javax.swing.*
import java.awt.BorderLayout

def controller = new CTGController(gatewayURL:"tcp://localhost",
    gatewayPort:2006, servername:"CICSTEST",
    program:"EC01", commarea:new byte[18])

def swing = new SwingBuilder()
def statusArea
def connectButton
def closeButton
    
swing.frame(title:"CICS TG Groovy Sample GUI", 
                size:[400,200], 
                defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE) {
borderLayout()	// Use a border layout for positioning components

statusArea = textArea(text:"Awaiting command...",lineWrap:true,editable:false)
panel(id:'buttonpanel', 
    constraints:BorderLayout.NORTH,
    layout:new FlowLayout()){
        connectButton = button(text:"Connect", 
            actionPerformed: {
                try {
                controller.connect()
                    statusArea.text = "Connection to Gateway 
                        ${controller.gatewayURL}:${controller.gatewayPort} established."
                connectButton.enabled=false
                closeButton.enabled=true
                    } catch (IOException ioe){
                        statusArea.text = "Connection attempt to Gateway failed, 
                            exception text follows:\n${ioe}"
                }
    })
    closeButton = button(text:"Close", 
        actionPerformed: {
        try {
            controller.close()
            statusArea.text = "Connection to Gateway 
                ${controller.gatewayURL}:${controller.gatewayPort} closed."
        connectButton.enabled=true
        closeButton.enabled=false
        } catch (IOException ioe){
            statusArea.text = "Close connection attempt failed, 
                exception text follows:\n${ioe}"
                }
        })
        closeButton.enabled=false
}

button(text:"Click to send a request", 
constraints:BorderLayout.SOUTH,
actionPerformed: {
controller.executeRequest()
if (controller.success) {
    statusArea.text = "Call completed successfully.\nCommarea = ${controller.result}"
} else {
    statusArea.text = "Request failed, failure text:\n ${controller.result}"
}
})
}.show()

End result

Here's what the finished result looks like in various stages of execution:

Initialization
Initialization
Successful connection to Gateway daemon
Connection to Gateway daemon
Successful transaction on CICS
Successful transaction on CICS
CICS unavailable
CICS unavailable

Conclusion

You have demonstrated the techniques to access CICS transactions from the Groovy programming language using CICS TG. You saw how Groovy features such as autogeneration of getters and the safe navigation operator reduce the amount of code clutter and enable a more consistent and concise access to the CICS TG Java API. Finally, you saw how you can use SwingBuilder to rapidly build a GUI front-end to CICS data.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=556766
ArticleTitle=Connecting from Groovy to CICS using the CICS Transaction Gateway
publish-date=10272010