Traditionally, you would transfer data between TXSeries and CICS Transaction Server (hereafter referred as CICS TS) programs using a communication area (COMMAREA), which only can send a maximum of 32K bytes of data. If an application had to send more than 32K of data, then the application would handle it by chunking the large data into 32K blocks and doing multiple DPLs. Thus the application is responsible for the logic of chunking large data and then grouping it after receiving. Figure 1 shows how data is passed between programs using a COMMAREA.
Figure 1. Data transfer between programs using a COMMAREA
Now with the availability of channels and containers, you can pass data of unlimited size between TXSeries programs, CICS TS programs and from a TXSeries program to a CICS TS program. Channels and containers also provide a structured way of sending the data.
Channels and containers
A container is a block of data designed for passing information between programs. Containers are grouped together in sets called channels. There is no limit on the number of containers that you can add to a channel, and the size of each container is limited only by the amount of storage available. A channel is a standard mechanism for exchanging data between programs. Figure 2 shows how data is passed between programs using channels and containers.
Figure 2. Data transfer between programs using channels and containers
APIs related to channels and containers
TXSeries provides EXEC CICS APIs to create, delete, reference, access and manipulate a container and associate it with a channel:
To create the container and the channel in which it is to be placed, use the
To pass a channel between programs, use the
LINK, XCTL, STARTand
RETURNAPIs with the channel parameter specified.
A called application can know when a channel is passed to it by using the
ASSIGN CHANNELAPI. If a channel is passed, it returns the channel name else returns blanks.
To retrieve the data from a container, use the
To transfer data from a container to another container in the same channel or different channel, use the
To delete a container explicitly in the program, use the
DELETE CONTAINERAPI. A channel will be deleted automatically when it goes out of scope, that is, when no program can access it.
Listing 1. Creating and using containers in a C program
/* Creating a container cont1 and placing it in channel chan1 */ EXEC CICS PUT CONTAINER(“cont1”) CHANNEL(“chan1”) FROM(instr) FLENGTH(len); /* Passing the channel chan1 to program PRG2 */ EXEC CICS LINK PROGRAM(“PRG2”) SYSID(“ISC”) CHANNEL(“chan1”);
/* Getting the channel name */ EXEC CICS ASSIGN CHANNEL(chan_name); /* Retrieving the data from cont1 */ EXEC CICS GET CONTAINER(“cont1”) CHANNEL(chan_name) INTO(outstr) FLENGTH(len); /* Moving cont1 from chan1 as cont2 in chan2 */ EXEC CICS MOVE CONTAINER(“cont1”) AS(“cont2”) CHANNEL(chan_name) TOCHANNEL(“chan2”); /* Delete cont2 from chan2 */ EXEC CICS DELETE CONTAINER(“cont2”) CHANNEL(“chan2”);
- Current channel: A program’s current channel is the channel (if any) with which it was invoked. Although the program can create other channels, the current channel for a particular invocation of a specific program never changes. The current channel is set by the calling program or transaction by issuing a LINK, XCTL, START and pseudo-conversational RETURN with the channel parameter. To discover a program’s current channel, use the ASSIGN CHANNEL API.
- Channel scope: A program can only access channels it has created, or the current channel with which it was invoked. Figure 3 clearly shows the scope of a channel and the current channel associated with the program.
Figure 3. Example demonstrating current channel and scope of a channel
Scenarios showing how to use channels
The following examples show how you might employ a channel in your application program flow.
- One channel/one program: The simplest technique is to use a channel and its
collection of containers to invoke a program as shown in Figure 4. You specify the
channel name on the EXEC CICS LINK command, and the target application program always knows exactly which channel it will be passed.
Figure 4. Passing a channel between two programs
- One channel/multiple programs: Another technique is for the first program to create a channel and some containers. This program could then link to another program passing the channel along. Subsequent programs could use the same channel, with the same or different containers, for their exchange of data. In this example we maintain only one copy of the data. Figure 5 shows passing a channel across multiple programs.
Figure 5. Passing a channel across multiple programs
- Multiple channels/one program: In this scenario a program links to multiple programs, passing them different channels as shown in Figure 6. You can see that Program A links to two programs, B and C. Each program is passed a different channel describing the different interfaces.
Figure 6. Passing multiple channels in a single program using multiple DPLs
- Multiple channels/multiple programs: In this scenario, multiple programs pass different channels to the same program. In Figure 7, you can see Program1 and Program2 send different channels to Program3. Program3 is a server program that can process requests from a number of different clients.
Figure 7. Passing multiple channels in multiple programs
Browsing containers in a channel
As previously mentioned, a channel can have any number of containers. You can browse them using the
BROWSE APIs. Each
GETNEXT API returns the container name present in the channel being browsed. Listing 2 shows APIs used to browse the containers in a channel.
Listing 2. Browsing containers in a channel
EXEC CICS STARTBROWSE CONTAINER BROWSETOKEN(&token) CHANNEL(chan_name); EXEC CICS GETNEXT CONTAINER(cont_name) BROWSETOKEN(token); EXEC CICS ENDBROWSE CONTAINER BROWSETOKEN(token);
Apart from providing the ability to send large data, channels and containers simplify data conversion by making it part of the application program. There are two types of containers: CHAR and BIT. You can only convert data on CHAR containers using PUT and GET APIs passing the CCSID (Coded Character Set Identifier) parameter. This will be mostly useful when passing data between systems with different character encoding. For example, the default character encoding used in TXSeries (distributed platforms) is ASCII, and the one used in CICS TS (z/OS) is EBCDIC. So when you pass data from TXSeries to CICS TS, it should be converted from ASCII to EBCDIC as shown in Listing 3 and Listing 4.
Listing 3. Data conversion using channels and containers - TXSeries Region
PUT CONTAINER(“CONT1”) FROM(str) FLENGTH(len) FROMCCSID(819)
Listing 4. Data conversion using channels and containers - CICS TS Region
GET CONTAINER(“CONT1”) INTO(str) FLENGTH(len) INTOCCSID(037)
In Listing 3,
FROMCCSID is specified as
819 is the
CCSID for ASCII). This value means that the data we are putting
CONT1 is in ASCII format. In Listing 4,
INTOCCSID is specified as
037 is the
CCSID for EBCDIC). This value means that the data retrieved will be converted to EBCDIC format.'
Because channels and containers deal with passing large data, you must consider a few design options to improve the overall performance of the application. The following tips describe how to use channels and containers to improve performance:
When using channels with DPL, only the changed and new containers are returned to the calling program when a DPL is complete. Take for example where PRG1 passes channel CHAN to PRG2 (See Figure 8). Then all the containers in channel CHAN are passed from PRG1 to PRG2. But only modified or newly created containers in channel CHAN are returned back to PRG1. So keeping this in mind, it’s always good to create the different containers for INPUT, OUTPUT and ERROR so that only the INPUT container passes from PRG1 to PRG2. On returning, only the OUTPUT and ERROR containers (if any error has happened) are returned, because the INPUT container is unchanged and need not be returned.
Figure 8. Using separate containers for input, output and error
- Use separate containers for read-only data versus read-write data. In addition, in some programs some structures are optional. Create separate containers for them to improve the transmission efficiency and to pass data in a more structured way between programs, which increases readability.
- Whenever an application is expecting a particular container (for example, ERROR) instead of browsing all the containers in a channel to get that particular container ERROR, it can use the GET container (“ERROR”) API and handle the response values appropriately. If the ERROR container is present in the channel, then the response value will be normal; otherwise the response value will give CONTAINERERR.
- Use separate containers for different data types, such as, binary data and character data. These containers will improve your ability to easily move between different code pages. CCSID conversion happens in the GET API if the CCSID of the container does not match the CCSID specified in the INTOCCSID parameter of the GET container. If an application needs to execute the GET API for the same container multiple times at different points, and if that needs CCSID conversion, then you shouldn’t call the GET API many times, but instead the application should maintain a local copy of the container and use it for any other further references.
Migrating a COMMAREA-based application to use channels
The following examples show how to convert an application program that is using a COMMAREA to one using a channel and container.
Programs using LINK
As shown in Figure 9, you can see Program1 links to Program2 passing COMMAREA. And in Program2, COMMAREA is retrieved using
ADDRESS COMMAREA API.
Figure 10 shows the same application using channels and containers to pass data. Program1 creates the container and channel using
PUT CONTAINER API and passes it to Program2 using LINK API. In Program2, container is retrieved using
GET CONTAINER API. And Program2 sends back the data by creating a new/modifying container in the passed channel.
Figure 9. Application using COMMAREA
Figure 10. Migrated application using channels and containers
Programs using START
Figure 11 shows Transaction1 passing data to Transaction2 via
START TRANSID API using
FROM option. The same application is changed to pass data via
START TRANSID API using
CHANNEL option as shown in Figure 12.
Figure 11. Application using COMMAREA
Figure 12. Migrated application using channels and containers
In a typical customer scenario, usually a client invokes a transaction in a TXSeries region. A client such as CICS Transaction Gateway can pass a channel to TXSeries via the IPIC protocol. Then TXSeries can handle the channel based on application logic, and can pass it on to a CICS TS region as described in the article. The following scenarios show where channels and containers can be used:
Consider TXSeries deployed in a healthcare domain that requires large images like scanned images, X-rays etc, be passed between the programs. Assume a scenario as shown in Figure 13, where a client collates a large amount of data in the form of a patient’s medical history, passes on to a server program which provides, by return, a small amount of data which is the patient’s current diagnosis. Channels and containers are best suited in these type of applications, because we are sending a huge amount of data, and there is a performance improvement as server sends only the ‘
current_diagnosis’container back to client since
‘medical_history’containers remain unchanged.
Figure 13. Using channels and containers in healthcare domain
Another example where channels and containers can be used is online shopping where a user will select a particular item from the catalog and send it to the server using channels and containers (see Figure 14). The server sends all details about that item such as its price, features, image, etc., to the user.
Figure 14. Using channels and containers in online shopping
Basically channels and containers can be used in all scenarios where a client needs to send or receive a large amount of data (> 32KB).
The sample application, provided as a download with this article, contains a C program running under a TXSeries region, which creates a channel and passes a channel to a C program running under a CICS TS region. This application is developed and tested using TXSeries 7.1 and CICS TS 3.2.
Channels and containers overcomes the limit of passing only 32K data between programs. Using COMMAREA remains the basic method for passing data, but you can use channels and containers when you need to transfer a large amount of data between programs. Minimal changes are required to migrate a COMMAREA-based application to use channels and containers. Additionally, with channels and containers, you pass data in a more structured way, and it makes the data conversion simpler and easier.
- TXSeries 7.1 information center
- CICS TS 3.2 information center
- TXSeries product information
- CICS Transaction Gateway 7.1 information center
- CICS Transaction Server V3R1 Channels and Containers Revealed
- TXSeries documentation library
- WebSphere® Application Server for z/OS®, Version 7.0
- developerworks WebSphere on System z zone