Every CICS programmer has hit the wall. You're maintaining an application that's been running since the Reagan administration, and someone in the architecture group decides the transaction needs to pass a variable-length list of accounts, plus an...
In This Chapter
- 15.1 The COMMAREA Problem
- 15.2 Channels and Containers — Architecture, Types, and Lifecycle
- 15.3 Implementing Channels in COBOL
- 15.4 Channel Patterns — Designing for Real Applications
- 15.5 Channels with Web Services and DPL
- 15.6 Migration from COMMAREA to Channels
- 15.7 Performance Considerations
- 15.8 Project Checkpoint — Channel Design for the HA Banking System
- Summary
- Key Terms Glossary
Chapter 15: CICS Channels and Containers — Modern Data Passing for Complex Transactions
Every CICS programmer has hit the wall. You're maintaining an application that's been running since the Reagan administration, and someone in the architecture group decides the transaction needs to pass a variable-length list of accounts, plus an XML document, plus an error structure, plus audit metadata — all between programs in a single logical unit of work. You look at your 32,760-byte COMMAREA and do the math. It doesn't work.
Channels and containers are CICS's answer to a problem that's been festering since the 1970s. They're not exotic. They're not optional anymore. If you're building anything that touches web services, handles variable-length data, or communicates across CICS regions via DPL, you need them. This chapter shows you how to use them properly — and when to leave the COMMAREA alone.
15.1 The COMMAREA Problem
15.1.1 The 32KB Ceiling
COMMAREA — the Communication Area — has been the primary mechanism for passing data between CICS programs since CICS/VS. It works. Millions of transactions use it every day. But it carries a hard architectural constraint that no amount of clever coding can work around: a maximum length of 32,760 bytes.
That number comes from the halfword length field in the CICS control blocks that manage COMMAREA storage. It's been 32,760 since the beginning, and it's never going to change. IBM won't break backward compatibility on something this fundamental.
For decades, 32KB was more than enough. A typical 3270 screen drives maybe 2–4KB of data. A batch-to-online bridge might push 8KB. Even complex financial transactions rarely exceeded 16KB through the 1990s. But three forces have conspired to make 32KB insufficient:
Web services integration. When a CICS transaction serves as a back-end for a web service, the payload is often XML or JSON. These formats are verbose. A SOAP envelope carrying what amounts to 3KB of business data can easily balloon to 20KB or more with namespaces, schema references, and MTOM attachments. Pass that through two or three CICS programs, and you're bumping the ceiling.
Complex data structures. Modern business requirements demand that transactions carry richer data. A loan origination transaction might need the applicant's personal data, employment history (variable number of employers), credit accounts (variable number), collateral descriptions, regulatory disclosures, and audit trail entries — all in a single pass. Packing all of that into a fixed 32KB structure requires painful compromises.
Service-oriented architectures. When CICS programs are decomposed into fine-grained services, each service invocation needs its own data contract. A single business transaction might LINK to five or six programs, each needing different data. Multiplexing all of that through a shared COMMAREA means either a monolithic copybook or a series of redefines that make the code unreadable.
15.1.2 The Fixed-Structure Trap
The 32KB limit gets the headlines, but the fixed-structure problem is often worse in practice. A COMMAREA is defined by a COBOL copybook — a fixed-length, fixed-format record. Every program that touches the COMMAREA must include the same copybook (or a compatible one).
This creates a coupling nightmare:
01 DFHCOMMAREA.
05 CA-REQUEST-TYPE PIC X(4).
05 CA-ACCOUNT-NUMBER PIC X(12).
05 CA-CUSTOMER-DATA.
10 CA-CUST-NAME PIC X(40).
10 CA-CUST-ADDR PIC X(100).
05 CA-ACCOUNT-LIST.
10 CA-ACCT-COUNT PIC S9(4) COMP.
10 CA-ACCT-ENTRY OCCURS 20 TIMES.
15 CA-ACCT-NUM PIC X(12).
15 CA-ACCT-TYPE PIC X(2).
15 CA-ACCT-BAL PIC S9(11)V99 COMP-3.
See the problem? OCCURS 20 TIMES. What if a customer has 21 accounts? You either increase the OCCURS value — which changes the copybook length for every program that uses it — or you implement a pagination scheme where the caller invokes the program multiple times. Neither option is clean.
Adding a new field to the COMMAREA means recompiling every program that includes the copybook. In a large shop, that can mean 50 or 100 programs. Miss one, and you get a length mismatch that manifests as corrupted data at 2 AM on a Saturday.
15.1.3 Workarounds and Their Costs
Shops have developed several workarounds over the years, and you've probably used at least two of them:
TS queues as overflow. Write the excess data to a temporary storage queue, pass the queue name in the COMMAREA, and have the called program read it back. This works but adds I/O overhead, requires explicit cleanup, and introduces failure modes (what if the queue write succeeds but the LINK fails?).
Shared TWA or CWA. Stuff data into the Transaction Work Area or Common Work Area. This avoids the 32KB limit but creates implicit coupling — the called program has to know the exact layout of a shared memory area. It's a maintenance disaster.
Multiple LINKs. Break the data into chunks and call the program multiple times. This is slow, error-prone, and makes the calling program responsible for assembly logic that doesn't belong there.
GETMAIN/FREEMAIN with address passing. Allocate storage, populate it, and pass the address in the COMMAREA. This works on paper but violates CICS storage management principles, doesn't work across regions, and creates storage leak risks that will haunt you for years.
All of these workarounds share a common flaw: they force application code to solve an infrastructure problem. Channels and containers move the solution back into the infrastructure, where it belongs.
💡 Practitioner Note: If your shop still uses TS queue overflow for inter-program data passing, Chapter 15 is your migration roadmap. Channels eliminate the need for that pattern entirely and do it without the I/O overhead.
15.2 Channels and Containers — Architecture, Types, and Lifecycle
15.2.1 The Channel Model
A channel is a named, scoped collection of containers. A container is a named block of data with no fixed size limit (practical limits are constrained by region storage, but you're talking gigabytes, not kilobytes). The channel itself holds no data — it's a logical grouping mechanism. The data lives in the containers.
Think of a channel as a named briefcase and containers as the labeled folders inside it. When you LINK to a program with a channel, you're handing over the briefcase. The called program can read any folder, add new folders, remove folders, or modify the contents of existing folders. When control returns, the calling program gets the briefcase back with whatever changes were made.
The key architectural properties:
-
Named access. Containers are accessed by name, not by offset. This eliminates the positional coupling that makes COMMAREA maintenance painful. A called program can ignore containers it doesn't care about.
-
Variable length. Each container can hold any amount of data. One container might hold 50 bytes; another might hold 5MB. The CICS runtime manages the storage.
-
Multiple data structures. A single channel can carry multiple containers, each with its own data format. You don't need to pack everything into one monolithic structure.
-
Typed data. Containers can be either CHAR (character data subject to code page conversion) or BIT (binary data passed as-is). This matters enormously for web services and cross-region communication.
-
Scoped lifetime. A channel's lifetime is tied to the LINK scope. When the LINKed program returns, the channel and its containers are still available to the linking program. When the transaction ends, they're cleaned up automatically.
15.2.2 Container Types: CHAR vs. BIT
Every container has a data type — either CHAR or BIT. This is not optional and not cosmetic. It controls whether CICS performs code page conversion when the container crosses a region boundary.
CHAR containers hold character data. When a CHAR container is sent from one CICS region to another (via DPL or MRO), CICS automatically converts the data from the source region's CCSID to the target region's CCSID. If your shop runs a mix of EBCDIC code pages — and most large shops do — this is invaluable. You can also specify the source CCSID explicitly with the FROMCCSID option.
BIT containers hold binary data. No conversion is performed, ever. Use BIT containers for packed decimal fields, COMP/COMP-3 numbers, binary structures, images, PDF documents, or any data where byte-level fidelity matters.
The default, if you don't specify DATATYPE, depends on the CICS release and configuration. Always specify it explicitly. An implicit default is a bug waiting to happen.
* CHAR container — text data, eligible for conversion
EXEC CICS PUT CONTAINER('CUST-NAME')
CHANNEL('ACCT-CHAN')
FROM(WS-CUSTOMER-NAME)
FLENGTH(LENGTH OF WS-CUSTOMER-NAME)
CHAR
END-EXEC
* BIT container — binary data, no conversion
EXEC CICS PUT CONTAINER('ACCT-RECORD')
CHANNEL('ACCT-CHAN')
FROM(WS-ACCOUNT-REC)
FLENGTH(LENGTH OF WS-ACCOUNT-REC)
BIT
END-EXEC
⚠️ Critical: If you put a COMP-3 field into a CHAR container and that container crosses a region boundary, CICS will attempt code page conversion on your packed decimal data. The result will be garbage. Always use BIT for structures containing binary numeric fields.
BIT vs. CHAR Decision Matrix in Detail:
| Data Content | Container Type | Reason |
|---|---|---|
| Pure text (names, addresses, messages) | CHAR | Benefits from automatic CCSID conversion across regions |
| COBOL group items with COMP/COMP-3 fields | BIT | Any binary field corrupts under conversion |
| XML or JSON as text | CHAR | Conversion from UTF-8 to EBCDIC is exactly what you want |
| XML or JSON as raw bytes for pass-through | BIT | If the data is being forwarded without parsing, preserve byte fidelity |
| PDF, image, or binary document content | BIT | Binary formats are destroyed by character conversion |
| Mixed text and binary (e.g., record with PIC X and COMP-3) | BIT | A single binary field forces BIT for the entire container |
| Fixed-length EBCDIC record matching a copybook | BIT | COBOL copybook structures almost always contain at least one COMP or COMP-3 field |
The most common mistake in production is using CHAR for a container that holds a standard COBOL copybook record. Most COBOL records contain at least one packed decimal (COMP-3) or binary (COMP/COMP-4) field. A single binary field in an otherwise-text record means the entire container must be BIT. The safe default for COBOL record structures is BIT. Reserve CHAR for containers that hold pure character data — messages, XML text, free-form descriptions, error messages.
BIT containers in practice — beyond record structures. BIT containers see heavy use in three production patterns that go well beyond simple COBOL copybook passing. First, binary document pass-through: when a CICS transaction retrieves a PDF statement or a TIFF image from a content management system and routes it to a web service for delivery, the document bytes flow through a BIT container untouched. The CICS service handler never parses the content — it simply moves the container from the retrieval channel to the delivery channel. Second, serialized Java objects from CICS JVMServer programs: when a Java component running in a Liberty JVMServer produces a serialized result (say, a protobuf-encoded risk score), it writes the byte array to a BIT container that a downstream COBOL program retrieves and maps through a copybook overlay. Third, cryptographic material: encrypted payloads, digital signatures, and hash values must be BIT containers without exception — any CCSID conversion would corrupt the cryptographic output and cause signature verification failures or decryption errors downstream. CNB's payment authorization flow uses a BIT container named HMAC-SIGNATURE to pass a 32-byte SHA-256 HMAC between the signing program and the verification program. The container crosses an MRO link between the TOR and AOR, and the BIT designation guarantees the 32 bytes arrive identically.
Yuki Tanaka at SecureFirst discovered this the hard way when their policy inquiry transaction started returning corrupted premium amounts after deploying a new AOR in a different LPAR. The AOR used CCSID 500 (International EBCDIC) while the TOR used CCSID 37 (US EBCDIC). The policy record container was CHAR, so CICS converted every byte — including the COMP-3 premium field. The fix was a one-line change: CHAR to BIT.
15.2.3 Channel Scope and Lifetime
Channels exist in one of two scopes:
Current channel. When a program is LINKed with a CHANNEL option, that channel becomes the current channel for the invoked program. The program can access it without specifying the channel name on GET/PUT operations (though I recommend always specifying the name for clarity). The current channel is automatically propagated if the invoked program LINKs to another program without specifying its own channel.
Program-created channels. A program can create its own channels by simply putting a container into a named channel. These channels exist until explicitly deleted or until the task ends. They're useful for building up a channel before a LINK, or for maintaining multiple channels simultaneously.
The lifecycle:
- Creation. A channel is implicitly created when the first container is PUT into it. There's no CREATE CHANNEL command.
- Propagation. A channel is passed to a called program via EXEC CICS LINK ... CHANNEL('name'). The called program receives the channel and all its containers.
- Modification. Both the calling and called programs can PUT, GET, MOVE, and DELETE containers within the channel.
- Return. When the called program issues EXEC CICS RETURN, control returns to the caller. The channel reflects any changes made by the called program.
- Destruction. Channels are destroyed when the task ends. There is no explicit DELETE CHANNEL — you delete individual containers with DELETE CONTAINER.
📊 Architecture Insight: Channel scope interacts with the MRO and DPL topology you studied in Chapter 13. When a LINK CHANNEL crosses a region boundary, CICS serializes the containers, transmits them, and deserializes on the target side. CHAR containers get code page conversion during this process. BIT containers are sent byte-for-byte. This is transparent to the application — same PUT/GET API regardless of whether the target program is local or remote.
15.3 Implementing Channels in COBOL
15.3.1 PUT CONTAINER — Writing Data
The PUT CONTAINER command creates or replaces a container within a channel.
WORKING-STORAGE SECTION.
01 WS-CUSTOMER-REC.
05 WS-CUST-ID PIC X(10).
05 WS-CUST-NAME PIC X(40).
05 WS-CUST-ADDR PIC X(200).
05 WS-CUST-PHONE PIC X(15).
01 WS-RESP PIC S9(8) COMP.
01 WS-RESP2 PIC S9(8) COMP.
PROCEDURE DIVISION.
MOVE 'C001234567' TO WS-CUST-ID
MOVE 'JOHNSON, MARGARET A.' TO WS-CUST-NAME
MOVE '1420 PINE STREET, APT 3B, CHICAGO IL 60601'
TO WS-CUST-ADDR
MOVE '312-555-0147' TO WS-CUST-PHONE
EXEC CICS PUT CONTAINER('CUSTOMER-DATA')
CHANNEL('ACCT-INQUIRY')
FROM(WS-CUSTOMER-REC)
FLENGTH(LENGTH OF WS-CUSTOMER-REC)
BIT
RESP(WS-RESP)
RESP2(WS-RESP2)
END-EXEC
IF WS-RESP NOT = DFHRESP(NORMAL)
PERFORM HANDLE-CONTAINER-ERROR
END-IF
Key options on PUT CONTAINER:
| Option | Purpose |
|---|---|
| CONTAINER('name') | Container name, 1–16 characters. Case-sensitive. |
| CHANNEL('name') | Channel name, 1–16 characters. If omitted, uses the current channel. |
| FROM(data-area) | Source data area in your program. |
| FLENGTH(fullword) | Length of data. Use LENGTH OF for static structures. |
| CHAR / BIT | Data type. Always specify one. |
| DATATYPE(cvda) | Alternative to CHAR/BIT keywords — sets the type via a CVDA variable. |
| FROMCCSID(value) | For CHAR containers: specifies the CCSID of the source data. |
| FROMCODEPAGE(value) | Alternative CCSID specification using a code page name. |
| RESP/RESP2 | Response codes. Always check them. |
A few rules to internalize:
- Container names and channel names are case-sensitive.
'Customer-Data'and'CUSTOMER-DATA'are different containers. Establish a naming convention and enforce it. Most shops use all-uppercase with hyphens. - If you PUT to a container that already exists, the old data is replaced entirely. There's no append operation.
- FLENGTH must be specified. Unlike COMMAREA, CICS does not infer the length from the FROM area.
- If the CHANNEL doesn't exist yet, it is created implicitly by the first PUT.
15.3.2 GET CONTAINER — Reading Data
GET CONTAINER retrieves data from a container into a program's working storage.
WORKING-STORAGE SECTION.
01 WS-CUSTOMER-REC.
05 WS-CUST-ID PIC X(10).
05 WS-CUST-NAME PIC X(40).
05 WS-CUST-ADDR PIC X(200).
05 WS-CUST-PHONE PIC X(15).
01 WS-DATA-LEN PIC S9(8) COMP.
01 WS-RESP PIC S9(8) COMP.
01 WS-RESP2 PIC S9(8) COMP.
PROCEDURE DIVISION.
MOVE LENGTH OF WS-CUSTOMER-REC TO WS-DATA-LEN
EXEC CICS GET CONTAINER('CUSTOMER-DATA')
CHANNEL('ACCT-INQUIRY')
INTO(WS-CUSTOMER-REC)
FLENGTH(WS-DATA-LEN)
RESP(WS-RESP)
RESP2(WS-RESP2)
END-EXEC
EVALUATE WS-RESP
WHEN DFHRESP(NORMAL)
CONTINUE
WHEN DFHRESP(CONTAINERERR)
PERFORM CONTAINER-NOT-FOUND
WHEN DFHRESP(CHANNELERR)
PERFORM CHANNEL-NOT-FOUND
WHEN DFHRESP(LENGERR)
PERFORM DATA-TRUNCATED
WHEN OTHER
PERFORM HANDLE-UNEXPECTED-ERROR
END-EVALUATE
Critical response codes for GET CONTAINER:
| RESP Value | Meaning |
|---|---|
| NORMAL | Data retrieved successfully. |
| CONTAINERERR | Container not found in the channel. |
| CHANNELERR | Channel does not exist. |
| LENGERR | Container data is longer than the INTO area. Data is truncated. FLENGTH is set to the actual container length. |
The LENGERR trap. When GET returns LENGERR, it means your INTO area was too small. CICS truncates the data and sets FLENGTH to the actual container data length. Some programmers ignore LENGERR because the data they care about is at the front of the structure. Don't do this. If the container is bigger than you expect, something is wrong — either your copybook is out of date or the sending program put the wrong data in the container. Treat LENGERR as an error.
Using SET instead of INTO. For variable-length data, you can use SET to get a pointer to the container data in CICS-managed storage:
WORKING-STORAGE SECTION.
01 WS-DATA-PTR POINTER.
01 WS-DATA-LEN PIC S9(8) COMP.
LINKAGE SECTION.
01 LS-VARIABLE-DATA PIC X(1).
PROCEDURE DIVISION.
EXEC CICS GET CONTAINER('XML-PAYLOAD')
CHANNEL('WS-CHANNEL')
SET(WS-DATA-PTR)
FLENGTH(WS-DATA-LEN)
END-EXEC
SET ADDRESS OF LS-VARIABLE-DATA
TO WS-DATA-PTR
* Now LS-VARIABLE-DATA points to the container data
* WS-DATA-LEN contains the actual length
The SET approach is essential when you don't know the container's size at compile time. The storage pointed to by SET is valid until the next GET CONTAINER with SET for the same container, or until the container is deleted.
15.3.3 MOVE CONTAINER — Transferring Between Channels
MOVE CONTAINER transfers a container from one channel to another. The container is removed from the source channel and added to the target channel.
EXEC CICS MOVE CONTAINER('CUSTOMER-DATA')
CHANNEL('TEMP-CHANNEL')
AS('CUST-RECORD')
TOCHANNEL('FINAL-CHANNEL')
RESP(WS-RESP)
END-EXEC
The AS option lets you rename the container during the move. If you omit AS, the container keeps its original name. This is useful when two channels use different naming conventions.
MOVE is more efficient than a GET followed by a PUT because it avoids copying the data through your program's working storage. CICS moves the container internally. For large containers — megabytes of XML or binary data — this difference matters.
15.3.4 DELETE CONTAINER
DELETE CONTAINER removes a container from a channel. If the container doesn't exist, you get CONTAINERERR.
EXEC CICS DELETE CONTAINER('TEMP-DATA')
CHANNEL('WORK-CHANNEL')
RESP(WS-RESP)
END-EXEC
You typically use DELETE CONTAINER for cleanup — removing temporary or intermediate containers before returning control to the caller, so the caller doesn't see data it shouldn't process.
15.3.5 Container Browsing
When a program receives a channel, it might not know what containers are present. Container browsing lets you enumerate them:
WORKING-STORAGE SECTION.
01 WS-BROWSE-TOKEN PIC S9(8) COMP.
01 WS-CONTAINER-NAME PIC X(16).
01 WS-CONTAINER-SET PIC S9(8) COMP.
01 WS-RESP PIC S9(8) COMP.
PROCEDURE DIVISION.
* Start browsing
EXEC CICS STARTBROWSE CONTAINER
CHANNEL('ACCT-INQUIRY')
BROWSETOKEN(WS-BROWSE-TOKEN)
RESP(WS-RESP)
END-EXEC
IF WS-RESP NOT = DFHRESP(NORMAL)
PERFORM BROWSE-START-ERROR
STOP RUN
END-IF
* Iterate through containers
PERFORM UNTIL WS-RESP = DFHRESP(END)
EXEC CICS GETNEXT CONTAINER(WS-CONTAINER-NAME)
BROWSETOKEN(WS-BROWSE-TOKEN)
RESP(WS-RESP)
END-EXEC
IF WS-RESP = DFHRESP(NORMAL)
DISPLAY 'CONTAINER: ' WS-CONTAINER-NAME
END-IF
END-PERFORM
* End browsing
EXEC CICS ENDBROWSE CONTAINER
BROWSETOKEN(WS-BROWSE-TOKEN)
END-EXEC
Container browsing is particularly useful in service handler programs that need to process channels generically — for example, an audit program that logs all containers for compliance, or a routing program that examines container names to determine processing paths.
15.3.5.1 Production Container Browsing Pattern — Audit Logging
Here's a complete production pattern that browses a channel, reads each container, and writes an audit record. This is the pattern CNB uses for their SOX compliance logging — every container that flows through the loan origination channel is captured:
WORKING-STORAGE SECTION.
01 WS-BROWSE-TOKEN PIC S9(8) COMP.
01 WS-CONTAINER-NAME PIC X(16).
01 WS-CONTAINER-LEN PIC S9(8) COMP.
01 WS-DATA-TYPE PIC S9(8) COMP.
01 WS-CONTAINER-COUNT PIC S9(4) COMP VALUE 0.
01 WS-AUDIT-BUFFER PIC X(32000).
01 WS-RESP PIC S9(8) COMP.
01 WS-RESP2 PIC S9(8) COMP.
PROCEDURE DIVISION.
5000-AUDIT-ALL-CONTAINERS.
* Start browsing the channel
EXEC CICS STARTBROWSE CONTAINER
CHANNEL('LOAN-ORIGINATION')
BROWSETOKEN(WS-BROWSE-TOKEN)
RESP(WS-RESP)
END-EXEC
IF WS-RESP NOT = DFHRESP(NORMAL)
PERFORM 9000-LOG-BROWSE-ERROR
GOBACK
END-IF
* Iterate through every container
PERFORM UNTIL WS-RESP = DFHRESP(END)
EXEC CICS GETNEXT CONTAINER(WS-CONTAINER-NAME)
BROWSETOKEN(WS-BROWSE-TOKEN)
RESP(WS-RESP)
END-EXEC
IF WS-RESP = DFHRESP(NORMAL)
ADD 1 TO WS-CONTAINER-COUNT
* Get container length without reading data
MOVE 0 TO WS-CONTAINER-LEN
EXEC CICS GET CONTAINER(WS-CONTAINER-NAME)
CHANNEL('LOAN-ORIGINATION')
NODATA
FLENGTH(WS-CONTAINER-LEN)
RESP(WS-RESP2)
END-EXEC
* Read container data (up to 32K for audit)
IF WS-CONTAINER-LEN > 0
AND WS-CONTAINER-LEN <= 32000
EXEC CICS GET CONTAINER(WS-CONTAINER-NAME)
CHANNEL('LOAN-ORIGINATION')
INTO(WS-AUDIT-BUFFER)
FLENGTH(WS-CONTAINER-LEN)
RESP(WS-RESP2)
END-EXEC
PERFORM 5100-WRITE-AUDIT-RECORD
END-IF
END-IF
END-PERFORM
* End browsing
EXEC CICS ENDBROWSE CONTAINER
BROWSETOKEN(WS-BROWSE-TOKEN)
END-EXEC
.
Notice the use of the NODATA option on the first GET. This retrieves the container's length without actually copying the data — a lightweight probe that lets you decide whether to read the full container. For containers larger than your audit buffer, you log the container name and length but skip the data capture. This prevents a 5MB XML payload from blowing up your audit routine.
15.3.5.2 Determining Container Data Type Programmatically
When browsing containers from an unknown source, you may need to determine whether a container is CHAR or BIT before processing it. Use the INTOCCSID option on GET CONTAINER to detect the data type:
01 WS-CCSID PIC S9(8) COMP.
EXEC CICS GET CONTAINER(WS-CONTAINER-NAME)
CHANNEL('INCOMING-CHAN')
SET(WS-DATA-PTR)
FLENGTH(WS-CONTAINER-LEN)
INTOCCSID(WS-CCSID)
RESP(WS-RESP)
END-EXEC
IF WS-CCSID = 0
* BIT container — binary data, no conversion
PERFORM 6000-PROCESS-BINARY
ELSE
* CHAR container — WS-CCSID contains the CCSID
PERFORM 6100-PROCESS-CHARACTER
END-IF
For BIT containers, INTOCCSID returns 0. For CHAR containers, it returns the CCSID of the data. This distinction is essential when building generic service handlers that must process containers of any type correctly.
15.3.6 Data Conversion with FROMCCSID
When your program creates CHAR containers, you can specify the coded character set of the source data:
EXEC CICS PUT CONTAINER('MESSAGE-TEXT')
CHANNEL('RESPONSE-CHAN')
FROM(WS-UTF8-MESSAGE)
FLENGTH(WS-MSG-LENGTH)
CHAR
FROMCCSID(1208)
END-EXEC
CCSID 1208 is UTF-8. CCSID 37 is US EBCDIC. CCSID 1047 is Open Systems EBCDIC (common on z/OS UNIX). CCSID 500 is International EBCDIC.
When a CHAR container with a FROMCCSID is retrieved by a GET CONTAINER with an INTOCCSID, CICS performs the conversion automatically. This is how CICS handles data transformation for web services — the web service pipeline puts UTF-8 data into a CHAR container, and your COBOL program GETs it with an implicit conversion to your region's EBCDIC CCSID.
🔗 Spaced Review — Chapter 3 (Language Environment): The data conversion that CICS performs on CHAR containers uses the same Unicode Services that LE provides for COBOL programs. If you're debugging a conversion issue, check the CCSID values against the LE conversion tables you learned about in Chapter 3's encoding section. Mismatched CCSIDs produce the same garbled output whether the conversion happens in LE or in CICS container handling.
15.4 Channel Patterns — Designing for Real Applications
Knowing the API is table stakes. What separates a good channel design from a bad one is the patterns you apply. Here are the patterns that work in production.
15.4.1 The Multi-Container Transaction Pattern
Instead of cramming everything into one structure, decompose your data into logical containers:
Channel: LOAN-ORIGINATION
Container: REQUEST-HEADER (BIT — request type, timestamps, IDs)
Container: APPLICANT-DATA (BIT — personal information structure)
Container: EMPLOYMENT-HIST (BIT — variable-length employment records)
Container: CREDIT-ACCOUNTS (BIT — variable-length credit data)
Container: COLLATERAL-DESC (CHAR — free-text property description)
Container: RESPONSE-HEADER (BIT — response codes, timestamps)
Container: DECISION-RESULT (BIT — approval/denial structure)
Container: ERROR-DETAIL (CHAR — error messages if applicable)
This pattern has several advantages:
- Selective access. A program that only needs the applicant data reads only the APPLICANT-DATA container. It doesn't need a copybook that describes the entire channel.
- Independent evolution. Adding a new container doesn't affect programs that don't use it. You can add a REGULATORY-FLAGS container without touching any existing code.
- Variable-length support. EMPLOYMENT-HIST and CREDIT-ACCOUNTS can vary in size without affecting other containers or requiring OCCURS DEPENDING ON gymnastics.
- Clear data ownership. The requesting program populates the REQUEST containers; the responding program populates the RESPONSE containers. There's no ambiguity about who writes what.
15.4.2 The Error Container Pattern
Establish a standard error container that every program in your channel architecture understands:
01 WS-ERROR-CONTAINER.
05 EC-ERROR-FLAG PIC X(1).
88 EC-NO-ERROR VALUE 'N'.
88 EC-ERROR-OCCURRED VALUE 'Y'.
05 EC-ERROR-CODE PIC X(8).
05 EC-ERROR-SEVERITY PIC X(1).
88 EC-SEV-INFO VALUE 'I'.
88 EC-SEV-WARNING VALUE 'W'.
88 EC-SEV-ERROR VALUE 'E'.
88 EC-SEV-FATAL VALUE 'F'.
05 EC-ERROR-SOURCE PIC X(8).
05 EC-ERROR-MESSAGE PIC X(256).
05 EC-ERROR-TIMESTAMP PIC X(26).
05 EC-ABEND-CODE PIC X(4).
05 EC-EIBRESP PIC S9(8) COMP.
05 EC-EIBRESP2 PIC S9(8) COMP.
Every called program checks for the ERROR-INFO container on entry. If it's already present with an error flag, the program can short-circuit — don't process the request if a previous step already failed. On exit, if an error occurred, the program populates or updates the ERROR-INFO container.
This is the channel equivalent of an exception-handling chain, and it's far cleaner than encoding error information in the first few bytes of a COMMAREA.
15.4.3 The Metadata Container Pattern
Add a metadata container that travels with every channel:
01 WS-CHANNEL-META.
05 CM-VERSION PIC X(4).
05 CM-ORIGINATING-TRAN PIC X(4).
05 CM-ORIGINATING-PGM PIC X(8).
05 CM-CORRELATION-ID PIC X(36).
05 CM-TIMESTAMP PIC X(26).
05 CM-HOP-COUNT PIC S9(4) COMP.
05 CM-TRACE-FLAG PIC X(1).
88 CM-TRACING-ON VALUE 'Y'.
88 CM-TRACING-OFF VALUE 'N'.
The metadata container provides traceability. When a transaction chains through multiple programs, each program increments the hop count and can optionally log the container contents for debugging. The correlation ID ties the entire flow together for end-to-end tracing.
The VERSION field is particularly important. It allows you to evolve the channel's container set over time while maintaining backward compatibility. A program that understands version "0200" can handle containers that didn't exist in version "0100" — and it knows to look for them because the version tells it they might be present.
15.4.4 The Request/Response Pattern
Structure your containers as explicit request and response groups:
Channel: ACCT-SERVICE
Container: SVC-REQUEST (BIT — request structure)
Container: SVC-METADATA (BIT — metadata structure)
Container: SVC-RESPONSE (BIT — response structure)
Container: SVC-ERROR (BIT — error structure)
Container: SVC-AUDIT (BIT — audit trail entry)
The calling program populates SVC-REQUEST and SVC-METADATA. The called program reads those, populates SVC-RESPONSE (and SVC-ERROR if something went wrong), and returns. Neither program touches the other's containers except to read them.
This separation makes the data flow explicit and testable. You can write a test harness that creates a channel with known request containers and verifies the response containers — without needing the full transaction environment.
15.4.5 The Pipeline Pattern
For transactions that flow through a chain of programs, each program adds its output as a new container:
Program A (validation):
Reads: INPUT-DATA
Writes: VALIDATION-RESULT
Program B (enrichment):
Reads: INPUT-DATA, VALIDATION-RESULT
Writes: ENRICHED-DATA
Program C (processing):
Reads: ENRICHED-DATA
Writes: PROCESS-RESULT
Program D (formatting):
Reads: PROCESS-RESULT
Writes: OUTPUT-DATA
Each program in the pipeline reads what it needs and writes its contribution. No program modifies another program's containers. The channel accumulates results as it flows through the pipeline. This is a natural fit for CICS program-to-program flows and maps cleanly onto service orchestration patterns.
📊 Pattern Selection Guide: - 2–3 programs, simple data: Single container per direction (request/response). Don't over-engineer it. - 4+ programs, homogeneous data: Pipeline pattern with accumulating containers. - Complex transactions with error handling: Multi-container with error and metadata containers. - Web service back-end: Request/response pattern aligned with the WSDL/schema structure.
15.5 Channels with Web Services and DPL
15.5.1 Web Services Integration
CICS web services support is built on channels and containers. When CICS receives an inbound web service request (SOAP or REST), the web service pipeline:
- Receives the HTTP request
- Parses the SOAP/REST payload
- Places the payload data into containers on a channel
- LINKs to your COBOL program with that channel
- Reads the response containers after your program returns
- Constructs the HTTP response
The standard container names for web service data:
| Container Name | Type | Content |
|---|---|---|
| DFHWS-DATA | CHAR | Business data (the SOAP body or REST payload) |
| DFHWS-BODY | CHAR | Full SOAP body or HTTP body |
| DFHWS-OPERATION | CHAR | Web service operation name |
| DFHWS-URI | CHAR | Request URI |
| DFHWS-XMLNS | CHAR | XML namespace declarations |
Your COBOL program doesn't need to parse XML or JSON directly. The CICS pipeline and data mapping (DFHWS2LS and DFHLS2WS) handle the transformation between the XML/JSON representation and the COBOL data structure. Your program GETs the business data from the DFHWS-DATA container, processes it, and PUTs the response back.
PROCEDURE DIVISION.
* Get the inbound request data
EXEC CICS GET CONTAINER('DFHWS-DATA')
INTO(WS-REQUEST-DATA)
FLENGTH(WS-REQ-LEN)
RESP(WS-RESP)
END-EXEC
IF WS-RESP = DFHRESP(NORMAL)
PERFORM PROCESS-REQUEST
ELSE
PERFORM BUILD-FAULT-RESPONSE
END-IF
* Put the response data
EXEC CICS PUT CONTAINER('DFHWS-DATA')
FROM(WS-RESPONSE-DATA)
FLENGTH(LENGTH OF WS-RESPONSE-DATA)
CHAR
END-EXEC
EXEC CICS RETURN END-EXEC
15.5.2 Distributed Program Link (DPL) with Channels
When you LINK to a program in a remote CICS region using DPL, you can pass a channel instead of a COMMAREA. The channel and all its containers are transmitted to the remote region:
EXEC CICS LINK PROGRAM('RMTPGM01')
CHANNEL('ACCT-INQUIRY')
SYSID('CIC2')
RESP(WS-RESP)
RESP2(WS-RESP2)
END-EXEC
The CICS interconnect (ISC or MRO, depending on your topology) handles the serialization and transmission. CHAR containers get code page conversion if the remote region uses a different CCSID. BIT containers are passed as-is.
This is a massive improvement over DPL with COMMAREA for two reasons:
- No 32KB limit. You can pass as much data as the interconnect supports.
- Automatic code page conversion. CHAR containers are converted transparently. With COMMAREA over DPL, you had to handle conversion yourself or hope both regions used the same CCSID.
🔗 Spaced Review — Chapter 13 (CICS Regions and Topologies): The MRO and ISC connections you configured in Chapter 13 are the transport layer for channel-based DPL. When a channel crosses an MRO connection, CICS uses the MRO link's CCSID settings to determine conversion requirements for CHAR containers. Review Chapter 13's section on CDSECT and connection definitions if you need to configure CCSID attributes on the connection.
15.5.3 Channels and CICSPlex
In a CICSPlex environment with routing regions and application-owning regions (AORs), channels follow the transaction routing path. When a terminal-owning region (TOR) routes a transaction to an AOR, the channel created in the TOR is available in the AOR. This is transparent — your application code doesn't change.
However, be aware of the performance implications. Every container in the channel must be serialized and transmitted across the routing connection. If you've built a channel with 20 containers totaling 500KB, that's 500KB of data flowing across the interregion link. Design your channels with the routing topology in mind.
15.6 Migration from COMMAREA to Channels
15.6.1 The Coexistence Strategy
You don't migrate all at once. You can't — you'd need to rewrite and test every program simultaneously. Instead, use the coexistence strategy:
Phase 1: Wrapper programs. Write a thin wrapper that accepts a channel, extracts the data into a COMMAREA-shaped working storage area, LINKs to the existing COMMAREA-based program, and then puts the response back into the channel. This lets new channel-based callers use the existing programs without modification.
IDENTIFICATION DIVISION.
PROGRAM-ID. ACCT-WRAP.
* Wrapper: channel interface -> COMMAREA program
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-COMMAREA-DATA.
COPY ACCTCPY.
01 WS-CA-LENGTH PIC S9(8) COMP.
01 WS-RESP PIC S9(8) COMP.
PROCEDURE DIVISION.
* Extract request from channel into COMMAREA layout
MOVE LENGTH OF WS-COMMAREA-DATA TO WS-CA-LENGTH
EXEC CICS GET CONTAINER('ACCT-REQUEST')
CHANNEL('ACCT-SERVICE')
INTO(WS-COMMAREA-DATA)
FLENGTH(WS-CA-LENGTH)
RESP(WS-RESP)
END-EXEC
* Call original COMMAREA program
EXEC CICS LINK PROGRAM('ACCTINQ0')
COMMAREA(WS-COMMAREA-DATA)
LENGTH(WS-CA-LENGTH)
END-EXEC
* Put response back into channel
EXEC CICS PUT CONTAINER('ACCT-RESPONSE')
CHANNEL('ACCT-SERVICE')
FROM(WS-COMMAREA-DATA)
FLENGTH(WS-CA-LENGTH)
BIT
END-EXEC
EXEC CICS RETURN END-EXEC.
Phase 2: Dual-interface programs. Modify programs to detect whether they were invoked with a channel or a COMMAREA, and handle both:
PROCEDURE DIVISION.
* Check if we have a current channel
EXEC CICS ASSIGN CHANNEL(WS-CHANNEL-NAME)
RESP(WS-RESP)
END-EXEC
IF WS-RESP = DFHRESP(NORMAL)
AND WS-CHANNEL-NAME NOT = SPACES
* Invoked with a channel — use container interface
PERFORM PROCESS-VIA-CHANNEL
ELSE
* Invoked with COMMAREA — legacy interface
PERFORM PROCESS-VIA-COMMAREA
END-IF
Phase 3: Full migration. Once all callers have been converted to use channels, remove the COMMAREA path from the called programs. This is the least urgent step — there's no harm in leaving the dual interface in place indefinitely.
Migration sequencing for large application portfolios. In a shop with hundreds of CICS programs, you cannot migrate everything simultaneously. CNB's architecture team developed a priority-based migration sequence:
-
Tier 1 — Programs hitting the 32KB limit. These are the programs with active workarounds (TS queue overflow, multiple LINKs, GETMAIN hacks). They benefit immediately and their workaround code can be removed. At CNB, this was 14 programs.
-
Tier 2 — Web service back-end programs. The CICS web service pipeline already uses channels internally. Programs that serve as web service back-ends should use channels to align with the pipeline's native data model. This eliminates an unnecessary conversion layer. At CNB, this was 23 programs.
-
Tier 3 — Programs involved in cross-region DPL. These benefit from automatic CCSID conversion for CHAR containers and the removal of the 32KB DPL COMMAREA limit. At CNB, this was 8 programs spanning two AORs.
-
Tier 4 — High-change programs. Programs that are frequently modified benefit from the decoupled container model, where adding a new data element doesn't require recompiling all consumers. Prioritize programs with the highest annual change frequency.
-
Tier 5 — Stable programs under the 32KB limit. These work fine with COMMAREA. Migrate them opportunistically when they're being modified for other reasons. Don't create change risk for no functional benefit.
CNB completed Tiers 1-3 in six months. Tier 4 took another year. Tier 5 is ongoing — three years later, some stable COMMAREA programs have never been migrated and never will be unless they need modification.
15.6.2 Mapping COMMAREA Sections to Containers
The mapping strategy depends on your COMMAREA's structure:
Monolithic COMMAREA (single flat record): Map to a single container. This is the simplest migration — same data, same layout, just a different delivery mechanism. You gain the benefits of size flexibility but don't yet get the modularity benefits.
Sectioned COMMAREA (logical groups within the record): Map each section to its own container. If your COMMAREA has a header section, a request section, and a response section, create three containers. This gives you the modularity benefits and allows the sections to vary independently.
REDEFINES-heavy COMMAREA (multiple record types sharing the same space): Create separate containers for each record type. The calling program puts the appropriate container based on the request type. The called program checks which containers are present. This eliminates the REDEFINES pattern entirely, which is a maintenance win.
15.6.3 Migration Pitfalls
Pitfall 1: Assuming container names are padded. Container names are compared as-is, including trailing spaces. 'CUST-DATA ' (with trailing spaces to fill 16 characters) and 'CUST-DATA' are different. Use MOVE with a PIC X(16) field if you're constructing container names dynamically.
Pitfall 2: Forgetting FLENGTH. With COMMAREA, CICS infers the length. With containers, you must specify it. Every PUT needs FLENGTH. Every GET needs FLENGTH (which on return tells you the actual data length).
Pitfall 3: Not handling CONTAINERERR. A COMMAREA is always present when a program is LINKed with one. A container might not be present in a channel. Programs must handle the case where an expected container doesn't exist.
Pitfall 4: Mixed BIT/CHAR across regions. If you migrate a program that runs locally today but might be deployed remotely tomorrow, get the CHAR/BIT designation right from the start. Changing it later means changing all programs that access the container.
Pitfall 5: Performance regression from over-decomposition. Breaking a 500-byte COMMAREA into 15 containers with 30–40 bytes each adds overhead. Each container has management overhead in CICS control blocks. For small, simple data exchanges, a single container is fine. Save multi-container designs for complex transactions where the modularity provides real value.
⚖️ Migration Decision Framework: - Data < 32KB, fixed structure, no cross-region, no web services → COMMAREA is fine. Don't migrate for migration's sake. - Data > 32KB, or needs variable length → Channels required. - Web services back-end → Channels required (CICS pipeline uses them). - Cross-region DPL with code page conversion → Channels strongly recommended. - New development with complex data contracts → Channels from the start.
15.7 Performance Considerations
15.7.1 Storage Management
Channels and containers use CICS task-lifetime storage. Each container's data is held in storage managed by the CICS Storage Manager (SM domain). For most transactions, this is indistinguishable from COMMAREA storage overhead. But there are edge cases:
Large containers. A container holding 10MB of data requires 10MB of CICS DSA storage. If you're in a constrained environment (CICS TS 5.x with MEMLIMIT restrictions), large containers can push you into storage shortages. Monitor CICS storage statistics (DFHSTST) if you're passing containers larger than 1MB.
Many containers per channel. Each container has a control block overhead of approximately 200–300 bytes (varies by CICS release). A channel with 5 containers adds about 1.5KB of overhead. A channel with 100 containers adds about 30KB. Don't create hundreds of containers per channel.
Container data copies. GET CONTAINER with INTO copies the data from CICS storage into your working storage. For a 50KB container, that's 50KB copied. GET with SET avoids the copy by giving you a pointer to the CICS-managed storage. Use SET for large containers where you can work with the data in place.
15.7.2 Channel Size and DPL Performance
When a channel crosses an MRO or ISC link, all containers are serialized and transmitted. The transmission cost is proportional to the total data volume. Guidelines:
- Under 100KB total channel size: Negligible DPL overhead compared to COMMAREA. The container management adds microseconds.
- 100KB–1MB: Measurable but usually acceptable. The MRO link bandwidth is the bottleneck, not the container processing.
- Over 1MB: Consider whether all containers need to cross the link. If the remote program only needs 3 of your 10 containers, create a new channel with just those 3 and LINK with the reduced channel.
- Over 10MB: Rethink the architecture. You're probably doing something that should be batch, or that should use MQ rather than synchronous DPL.
15.7.3 Comparison: Channels vs. COMMAREA vs. TS Queues
| Characteristic | COMMAREA | Channels/Containers | TS Queue |
|---|---|---|---|
| Max data size | 32,760 bytes | Region storage limit | Queue item ~32KB, but multiple items allowed |
| I/O overhead | None (in-memory) | None (in-memory) | Auxiliary TS: disk I/O. Main TS: memory but shared. |
| Cross-region support | Yes (DPL) | Yes (DPL with auto-conversion) | Only via shared TS pools or explicit reads |
| Code page conversion | Manual | Automatic for CHAR | Manual |
| Variable-length data | Fixed structure | Native support | Each item can vary |
| Multiple data structures | REDEFINES only | Multiple containers | Multiple queue items |
| Cleanup required | No (auto) | No (auto) | Yes (explicit DELETEQ) |
| Transactional | Yes (part of UOW) | Yes (part of UOW) | Auxiliary TS: recoverable. Main TS: volatile. |
| Browsing support | No | STARTBROWSE CONTAINER | READQ with ITEM |
| Web services integration | Poor | Native | Not applicable |
The bottom line: channels are superior to COMMAREA for anything beyond simple, fixed-format data exchange under 32KB. TS queues still have a role for data that needs to persist beyond a single LINK scope — for example, data shared between different transactions, or data that needs to survive transaction abends.
15.7.4 Monitoring and Debugging
CICS provides several facilities for monitoring channel and container usage:
CICS Explorer. The CICS Explorer plug-in (in CICS TS 5.x and later) shows channels and containers for active tasks. You can browse container contents in real time.
CEMT INQUIRE TASK. Shows the current channel for a task, if any. Doesn't show container details.
CICS statistics. The SM domain statistics include container storage usage. Monitor these to track storage trends.
Application-level logging. The metadata container pattern from Section 15.4.3 gives you application-level traceability. Log the correlation ID and hop count at each step for end-to-end debugging.
Auxiliary trace. CICS auxiliary trace records container PUT and GET operations at trace level 2. The trace entries show container name, channel name, data length, and CHAR/BIT type. This is your last-resort debugging tool — auxiliary trace is expensive, but when you need it, nothing else gives you the same level of detail.
🧪 Debugging Tip: When a container GET returns unexpected data, check three things in order: (1) Is the container name spelled exactly right, including case? (2) Is the FLENGTH large enough? (3) Is the CHAR/BIT designation consistent between the PUT and GET? Nine out of ten container data problems trace back to one of these three.
15.8 Project Checkpoint — Channel Design for the HA Banking System
Context
The HA Banking Transaction Processing System processes account inquiries, transfers, and loan operations. Currently, the system uses COMMARIAs for inter-program communication, with TS queue overflow for the loan origination flow (which exceeds 32KB). The system spans three CICS regions: a TOR (CICSTORI), a primary AOR (CICSAOR1), and a secondary AOR (CICSAOR2) for disaster recovery.
Your Design Task
Design the channel architecture for three transaction flows. For each flow, specify:
- The channel name
- All containers (name, CHAR or BIT, data description, approximate size)
- Which program creates and consumes each container
- How the channel flows across regions (if applicable)
Flow 1: Account Inquiry (AINQ)
The account inquiry transaction currently uses a single COMMAREA (1,200 bytes) to pass account number, customer data, balance information, and transaction history (last 10 transactions). The business wants to expand transaction history to the last 100 transactions, which would require approximately 8,500 bytes — still under 32KB, but growing.
Programs involved: AINQ0000 (terminal handler) → AINQ0010 (validation) → AINQ0020 (data retrieval) → AINQ0030 (formatting)
Flow 2: Funds Transfer (XFER)
The funds transfer transaction uses a COMMAREA (2,400 bytes) for the source and target account details, transfer amount, and authorization codes. This flow needs to add fraud-check data (variable length, up to 50KB) and regulatory compliance records (variable length, up to 20KB).
Programs involved: XFER0000 (terminal handler) → XFER0010 (validation) → XFER0020 (fraud check) → XFER0030 (execution) → XFER0040 (confirmation)
The fraud check (XFER0020) runs in CICSAOR2 via DPL.
Flow 3: Loan Origination (LOAN)
The loan origination flow currently uses COMMAREA + TS queue overflow. The total data volume can reach 150KB, including applicant data, employment history, credit reports, collateral descriptions, and regulatory disclosures.
Programs involved: LOAN0000 (intake) → LOAN0010 (credit check, remote) → LOAN0020 (underwriting) → LOAN0030 (decision) → LOAN0040 (notification)
The credit check (LOAN0010) runs in CICSAOR2 via DPL.
Design Requirements
Apply the patterns from this chapter:
- Use error containers consistently across all flows
- Include metadata containers for traceability
- Use appropriate CHAR/BIT designations (remember DPL and code page conversion)
- Keep container counts reasonable — don't over-decompose
- Document any migration considerations for the transition from COMMAREA to channels
Sample Solution Skeleton
Here's a starting point for the Account Inquiry flow to guide your design:
CHANNEL: AINQ-CHAN
Container: AINQ-META BIT Metadata (version, correlation ID, trace)
Container: AINQ-REQUEST BIT Account number, request type, options
Container: AINQ-CUSTDATA BIT Customer demographic data
Container: AINQ-BALANCE BIT Account balance and status
Container: AINQ-TXNHIST BIT Transaction history (variable length)
Container: AINQ-ERROR BIT Error information
Complete this design for all three flows, specifying which programs PUT and GET each container, and how the channel handles the DPL boundary for the Funds Transfer and Loan Origination flows.
Spaced Review Connection
Chapter 3 (Language Environment): The FROMCCSID option on PUT CONTAINER uses the same CCSID values that LE's Unicode Services supports. When designing containers for cross-region DPL, verify that both regions' LE configurations support the CCSIDs you specify. An unsupported CCSID conversion will result in EXEC CICS errors that look like container problems but are actually LE configuration problems.
Chapter 13 (CICS Region Topologies): The channel-based DPL in the Funds Transfer and Loan Origination flows depends on the MRO connections configured in Chapter 13. The CDSECT definitions for the interregion links determine the maximum data volume that can flow in a single DPL request. If your Loan Origination channel exceeds the link's buffer size, CICS will fragment and reassemble the data — which works but adds latency. Check the connection's SENDCOUNT and RECEIVECOUNT parameters.
Summary
Channels and containers are not a replacement for COMMAREA — they're what COMMAREA should have been if it had been designed in an era of web services, variable-length data, and distributed topologies. The API is straightforward: PUT, GET, MOVE, DELETE, and browse operations that any COBOL programmer can learn in an afternoon.
The real skill is in the design. Good channel architectures use named containers that document themselves, separate request data from response data, include error and metadata containers for operational visibility, and respect the performance characteristics of the transport layer. Bad channel architectures treat the channel as a renamed COMMAREA — one monolithic container with the same rigid copybook coupling.
Migration is not a big-bang exercise. Wrappers, dual-interface programs, and the coexistence strategy let you move incrementally, one program at a time, without disrupting production. Start with the programs that need the capability — the ones hitting the 32KB limit, the web services back-ends, the DPL flows with code page mismatches — and work outward from there.
The HA Banking system project checkpoint gives you practice designing channel architectures for real transaction flows. Carry that design forward — the remaining chapters in Part 3 will build on it as we add web services, event processing, and security to the system.
Key Terms Glossary
| Term | Definition |
|---|---|
| Channel | A named, scoped collection of containers used to pass data between CICS programs. |
| Container | A named block of data within a channel, with no practical size limit. |
| COMMAREA | The traditional Communication Area for CICS inter-program data passing, limited to 32,760 bytes. |
| DFHCOMMAREA | The standard COBOL data name for the COMMAREA received by a LINKed program. |
| CHAR container | A container holding character data, eligible for automatic code page conversion during DPL. |
| BIT container | A container holding binary data, transmitted without conversion. |
| DATATYPE | The CICS option specifying whether a container is CHAR or BIT. |
| FROMCCSID | Option on PUT CONTAINER specifying the coded character set identifier of the source data. |
| Channel scope | The visibility of a channel — current channel (received via LINK) or program-created. |
| EXEC CICS PUT CONTAINER | Command to create or replace a container within a channel. |
| EXEC CICS GET CONTAINER | Command to retrieve data from a container. |
| EXEC CICS MOVE CONTAINER | Command to transfer a container between channels, optionally renaming it. |
| EXEC CICS DELETE CONTAINER | Command to remove a container from a channel. |
| DPL (Distributed Program Link) | Mechanism for LINKing to a program in a remote CICS region, supporting channel transmission. |
| Container browsing | The STARTBROWSE/GETNEXT/ENDBROWSE pattern for enumerating containers in a channel. |
| FLENGTH | The fullword length option required on PUT and GET CONTAINER operations. |
| LENGERR | RESP code returned when a GET CONTAINER's INTO area is smaller than the container data. |
| CONTAINERERR | RESP code returned when a specified container does not exist in the channel. |
| CHANNELERR | RESP code returned when a specified channel does not exist. |