CICS container operations let you pass large or multiple pieces of data between programs using channels and containers. A channel is a named collection of containers; each container holds data (up to 16MB or more) and is identified by name. You PUT CONTAINER to add or replace data, GET CONTAINER to retrieve it, and pass the channel on LINK, XCTL, RETURN, or START so the next program can access the same containers. This overcomes the 32KB COMMAREA limit and keeps data organized by name. This page explains channels, PUT/GET/DELETE CONTAINER, and how to use them with program control.
Imagine a channel as a box that can hold several labeled envelopes (containers). Each envelope has a name (e.g. "CUSTOMER", "ORDER") and can hold as much data as you need. You put something in an envelope (PUT CONTAINER), close the box, and hand the box to the next program (LINK CHANNEL). That program opens the box and takes out the envelopes it needs (GET CONTAINER). Everyone uses the same box and the same names, so there is no mix-up. The box can hold much more than the old single envelope (COMMAREA).
A channel is created implicitly when you first put a container on it: you specify a channel name and a container name. The channel exists for the life of the task (or until you delete it, depending on CICS release). A container is created or replaced by PUT CONTAINER: you give the channel name, container name, the data (FROM area), and the length (FLENGTH). If the container already exists on that channel, its content is replaced. Containers have no fixed format; they are just bytes. The application decides the layout (e.g. copybook, JSON, XML). GET CONTAINER retrieves the data: you specify channel, container name, the receiving area (INTO), and usually the length (LENGTH). CICS copies the container data into your area. If the container does not exist, you get NOTFND. If your receiving area is too small, you may get LENGERR or only partial data; you can GET with length zero to query the actual length first, then GET again with a sufficient buffer.
| Command | Purpose | Note |
|---|---|---|
| PUT CONTAINER | Create or replace a container | CHANNEL, CONTAINER name, FROM data, FLENGTH. Creates channel if needed. |
| GET CONTAINER | Retrieve container data | CHANNEL, CONTAINER name, INTO area, LENGTH. Check RESP for NOTFND or LENGERR. |
| DELETE CONTAINER | Remove a container from a channel | CHANNEL, CONTAINER name. Channel stays; other containers unchanged. |
| LINK/XCTL/RETURN CHANNEL | Pass channel to another program | CHANNEL(channel-name) instead of COMMAREA; receiver gets same channel. |
EXEC CICS PUT CONTAINER(container-name) CHANNEL(channel-name) FROM(data-area) FLENGTH(length) places the contents of the data area into the named container on the named channel. If the channel does not exist, CICS creates it. If the container already exists, it is replaced. Container-name and channel-name can be literals or identifiers. FROM is the sending area; FLENGTH is the number of bytes to store (you can use LENGTH(data-area) or a variable). Optionally use DATATYPE if you need to tag the data (e.g. text vs binary). After PUT, the data is in CICS-managed storage; the receiving program can GET it as long as the channel is passed (e.g. on LINK). Use RESP and RESP2 to detect errors (e.g. NOSPACE if the region limit is exceeded).
123456789101112131401 WS-CHAN PIC X(16) VALUE 'MYCHAN'. 01 WS-CUST PIC X(100). 01 WS-LEN PIC S9(8) BINARY. MOVE 100 TO WS-LEN EXEC CICS PUT CONTAINER('CUSTOMER') CHANNEL(WS-CHAN) FROM(WS-CUST) FLENGTH(WS-LEN) RESP(WS-RESP) END-EXEC IF WS-RESP NOT = DFHRESP(NORMAL) PERFORM CONTAINER-ERROR END-IF.
EXEC CICS GET CONTAINER(container-name) CHANNEL(channel-name) INTO(data-area) [LENGTH(data-length)] retrieves the container data into your area. You must specify the same channel and container names that were used on PUT. INTO is the receiving field; LENGTH tells CICS how many bytes your area can hold. CICS copies up to that many bytes; if the container is larger, you may get only partial data and a response indicating length (check your manual). If the container does not exist (wrong name or channel not passed), you get NOTFND. Use RESP so you can handle NOTFND and LENGERR. Some implementations allow GET with LENGTH(0) or a special option to return the container length without copying, so you can allocate or size your buffer and GET again.
1234567891011EXEC CICS GET CONTAINER('CUSTOMER') CHANNEL(WS-CHAN) INTO(WS-CUST) LENGTH(LENGTH OF WS-CUST) RESP(WS-RESP) END-EXEC IF WS-RESP = DFHRESP(NOTFND) PERFORM NO-CUSTOMER-CONTAINER ELSE IF WS-RESP = DFHRESP(NORMAL) PERFORM PROCESS-CUSTOMER END-IF.
When you LINK or XCTL to another program, you can pass the channel by specifying CHANNEL(channel-name) instead of (or in addition to) COMMAREA. The linked program receives the same channel and can GET CONTAINER for any container on it. When the linked program returns (RETURN), it can pass the channel back with RETURN CHANNEL(channel-name); the caller then has the same channel, possibly with containers added, deleted, or updated by the called program. So the channel is shared: both sides use the same channel name and container names. For START (asynchronous), you can pass a channel so the started task can read the containers. The channel and its containers are tied to the task; when the task ends, the storage is released (unless you use a mechanism like temporary storage for longer life).
123456789101112*> Caller: put data, then link EXEC CICS PUT CONTAINER('INPUT') CHANNEL('CH1') FROM(WS-IN) FLENGTH(WS-LEN) END-EXEC EXEC CICS LINK PROGRAM('SUB1') CHANNEL('CH1') END-EXEC *> Sub1: get data, process, put result, return channel EXEC CICS GET CONTAINER('INPUT') CHANNEL('CH1') INTO(WS-IN) LENGTH(WS-LEN) END-EXEC ... EXEC CICS PUT CONTAINER('OUTPUT') CHANNEL('CH1') FROM(WS-OUT) FLENGTH(WS-OUT-LEN) END-EXEC EXEC CICS RETURN CHANNEL('CH1') END-EXEC *> Caller: get result EXEC CICS GET CONTAINER('OUTPUT') CHANNEL('CH1') INTO(WS-RESULT) LENGTH(WS-RL) END-EXEC
EXEC CICS DELETE CONTAINER(container-name) CHANNEL(channel-name) removes that container from the channel. The data is discarded and the storage is released. The channel remains; other containers on it are unchanged. Use DELETE CONTAINER when you no longer need a piece of data and want to free space or when the semantics of your protocol say that a container is no longer valid. After DELETE, GET CONTAINER for that name will return NOTFND.
Always check the response after PUT and GET. NORMAL means success. NOTFND on GET means the container (or channel) was not found—check names and that the channel was passed. LENGERR can mean the receiving area was too small or the length parameter was wrong. NOSPACE on PUT means the region could not allocate storage for the container. Use FLENGTH and LENGTH consistently: the data you PUT with FLENGTH(n) should be read with a buffer of at least n bytes. If you do not know the length in advance, use the length-query option if your CICS provides it, or use a large enough buffer and document the maximum size.
1. A CICS channel is:
2. To give data to a linked program using containers you:
3. GET CONTAINER returns NOTFND when: