Introduction:
This article is for CICS Developers and CICS Systems Administrators who use CICSPlex SM.
Blog Summary
- This blog answers the question “How do I avoid coding the CICSplex name in my CPSM API programs?”
- No hardcoded CICSplex equals greater source flexibility when transitioning code between environments
- An associated sample COBOL program is available
The CICSPlex SM API can be used to obtain lots of useful CICSplex related data. Typically, programs using the API issue an EXEC CPSM CONNECT with the CICSplex name supplied as a parameter. The full range of CICSPlex SM API commands can then be used on the associated CICSplex.
However, what if you want to avoid hard coding the CICSplex name within your program? For example, to avoid having to change applications as they transition between Test and Production environments, or where the CICSplex name is unknown. Don’t worry help is at hand!
Programmatically determining the CICSplex name:
I’ve written a simple COBOL program which demonstrates how this can be achieved, which you can view or download from our GitHub repository. The program follows the steps outlined below (note that the following code snippets are highlights, please refer to the program source for the full code including full error checking) :
Step 1: Find out where your CICSPlex SM API program is running
Issuing the EXEC CICS ASSIGN returns the APPLID of the CICS region where your CICSPlex SM program is executing.
EXEC CICS ASSIGN
APPLID(WS-APPLID)
END-EXEC.
Step 2: Establish a connection to CICSPlex SM
You don’t have to specify the CICSplex name on EXEC CPSM CONNECT. Connecting with just the version number gives you access to some of the CICSPlex SM tables – including the CMASPLEX table which we’ll need shortly.
MOVE '0540' TO WS-CPSM-VERSION.
EXEC CPSM CONNECT
VERSION(WS-CPSM-VERSION)
THREAD(WS-THREAD-CICSPLEX)
RESPONSE(WS-RESPONSE)
REASON(WS-REASON)
END-EXEC.
Step 3: Query CICSPlex SM for the CICSplexes known to the CMAS your region is managed by
You can issue EXEC CPSM GET on the CMASPLEX table,
INITIALIZE WS-CPSM-TEMPORARY.
MOVE 'CMASPLEX' TO WS-CPSM-TEMPORARY-OBJECT.
MOVE CMASPLEX-TBL-LEN TO WS-CPSM-TEMPORARY-LENGTH.
MOVE 0 TO WS-CPSM-TEMPORARY-COUNT.
MOVE WS-THREAD-CICSPLEX TO WS-CPSM-TEMPORARY-THREAD.
...
MOVE 0 TO WS-CPSM-TEMPORARY-COUNT
EXEC CPSM GET
OBJECT(WS-CPSM-TEMPORARY-OBJECT)
COUNT(WS-CPSM-TEMPORARY-COUNT)
RESULT(WS-CPSM-TEMPORARY-RESULT-SET)
THREAD(WS-CPSM-TEMPORARY-THREAD)
RESPONSE(WS-RESPONSE)
REASON(WS-REASON)
END-EXEC
and then PERFORM a loop which FETCHes each CICSplex and stores the name into an array.
MOVE WS-CPSM-TEMPORARY-RESULT-SET
TO WS-CPSM-CMASPLEX-RESULT-SET.
MOVE WS-CPSM-TEMPORARY-COUNT TO WS-CPSM-CMASPLEX-COUNT.
*
* Initialise the array for storing the CICSPLEX names
* and the counter to drive the subscript.
*
MOVE SPACES TO WS-CICSPLEX-NAME-ARRAY.
MOVE 0 TO WS-CICSPLEX-NAME-CNT.
*
* Loop around the number of returned CMASPLEX records
* fetching each in turn.
*
PERFORM VARYING WS-TEMP-RECORDS-1
FROM 1 BY 1
UNTIL WS-TEMP-RECORDS-1 > WS-CPSM-CMASPLEX-COUNT
*
* Retrieve (FETCH) the next record returned in the
* Result Set
*
MOVE CMASPLEX-TBL-LEN TO WS-CPSM-TEMPORARY-LENGTH
MOVE WS-CPSM-TEMPORARY-LENGTH TO WS-DISPLAY-LENGTH
EXEC CPSM FETCH INTO(CMASPLEX)
LENGTH(WS-CPSM-TEMPORARY-LENGTH)
RESULT(WS-CPSM-CMASPLEX-RESULT-SET)
THREAD(WS-THREAD-CICSPLEX)
RESPONSE(WS-RESPONSE)
REASON(WS-REASON)
END-EXEC
*
* If the FETCH of the CMASPLEX worked, store the
* CICSPlex NAME in the CPLEXNAME array.
*
ADD 1 TO WS-CICSPLEX-NAME-CNT
MOVE PLEXNAME OF CMASPLEX TO
WS-CICSPLEX-NAME-STORE(WS-CICSPLEX-NAME-CNT)
END-PERFORM.
Step 4: Determine the CICSplex your CICS region resides within
Given that an APPLID must be unique within a CICSplex, you can now query each CICSplex in the array to determine which contains the region your program is executing within. This can be done through the use of the EXEC CPSM QUALIFY command – with the CONTEXT and SCOPE set to each array entry (each CICSplex identified earlier) – followed by an EXEC CPSM GET against the CICSRGN table with a CRITERIA of the APPLID.
MOVE 'N' TO WS-CICSPLEX-KNOWN.
PERFORM VARYING WS-TEMP-RECORDS-1
FROM 1 BY 1
UNTIL WS-TEMP-RECORDS-1 > WS-CICSPLEX-NAME-CNT OR
WS-CICSPLEX-KNOWN = 'Y'
MOVE 'CICSRGN' TO WS-CPSM-TEMPORARY-OBJECT
MOVE CICSRGN-TBL-LEN TO WS-CPSM-TEMPORARY-LENGTH
MOVE 0 TO WS-CPSM-TEMPORARY-COUNT
*
* Set up a CRITERIA string containing the APPLID
*
STRING 'APPLID=' DELIMITED BY SIZE,
WS-APPLID DELIMITED BY SPACE,
'.' DELIMITED BY SIZE
INTO WS-CPSM-TEMPORARY-CRITERIA
MOVE SPACES TO WS-CPSM-TEMPORARY-PARM
MOVE WS-THREAD-CICSPLEX TO WS-CPSM-TEMPORARY-THREAD
MOVE SPACES TO WS-CPSM-TEMPORARY-SCOPE
STRING WS-CICSPLEX-NAME-STORE (WS-TEMP-RECORDS-1)
DELIMITED BY SPACE INTO WS-CPSM-TEMPORARY-SCOPE
EXEC CPSM QUALIFY
CONTEXT(WS-CPSM-TEMPORARY-SCOPE)
SCOPE(WS-CPSM-TEMPORARY-SCOPE)
THREAD(WS-THREAD-CICSPLEX)
RESPONSE(WS-RESPONSE)
REASON(WS-REASON)
END-EXEC
EXEC CPSM GET OBJECT(WS-CPSM-TEMPORARY-OBJECT)
COUNT(WS-CPSM-TEMPORARY-COUNT)
CRITERIA(WS-CPSM-TEMPORARY-CRITERIA)
LENGTH(WS-CPSM-TEMP-LEN)
RESULT(WS-CPSM-TEMPORARY-RESULT-SET)
THREAD(WS-CPSM-TEMPORARY-THREAD)
RESPONSE(WS-RESPONSE)
REASON(WS-REASON)
END-EXEC
IF WS-RESPONSE EQUAL EYUVALUE(OK)
MOVE WS-CICSPLEX-NAME-STORE (WS-TEMP-RECORDS-1) TO
WS-SAVED-CICSPLEXNAME
MOVE 'Y' TO WS-CICSPLEX-KNOWN
END-IF
END-PERFORM.
If the GET response code is 1024 (OK) then you have found the CICSplex where the CICS region that your program is executing within resides.
Conclusion
Most sites take a dim view of hardcoding, unless absolutely necessary. A no hardcoded CICSplex application is much more flexible and this in turn removes the cost and time involved in updating applications which move between environments. The sample program can be used as a standalone program with the CICSplex name returned in variable WS-SAVED-CICSPLEXNAME or alternatively the sample prgram can be extended to incorporate your own application code.