Writing an application that calls the Host API
Before you begin
Generate and build an API requester project by using the API requester Gradle plug-in so you have the project WAR file and the data structure copybooks.
The following procedure demonstrates how to call the "getAllRedbooks" operation of the sample Redbook API from a COBOL program, by using the IBM z/OS Connect Host API. An example COBOL program is shown that calls the operation to return all the books available. For more information, see Project structure
- In the Working Storage section of your program, add COPY instructions for the following
- BAQHAREC and BAQHCONC copybooks.
- The BAQ-API-INFO data structure that was generated for the API endpoint operation that you want to call. The default format of the copybook name is APInnI01.
- The generated API endpoint request data structure. Depending on your API operation semantics, there might not be a request data structure. The default format of the copybook name is APInnQ01.
``` WORKING-STORAGE SECTION. * API requester Host API required copybooks COPY BAQHAREC. COPY BAQHCONC. * API-INFO for Operation getAllRedbooks COPY RBK02I01. * Request structure for Operation getAllRedbooks COPY RBK02Q01. ```
In the Linkage Section of your program, add COPY instructions for the generated API endpoint
response data. Depending on your API operation semantics, there might not be a response structure.
The default format of the copybook name is APInnP01.
The response data structure is located in the Linkage Section because the IBM z/OS Connect Host API manages the storage for the response.
``` LINKAGE SECTION. * Response structure for Operation getAllRedbooks COPY RBK02P01. ```
- Code the Procedure Division. In the Procedure Division, the sample code is organized into several sections to show the usage of the IBM z/OS Connect Host API callable verbs.
The Initialization Section calls BAQINIT to acquire a connection to the IBM z/OS Connect server that is used to process the request. The termination Section calls BAQTERM to release the connection. If the execution environment is CICS® then CICS manages a connection pool on behalf of IBM z/OS Connect.For example,
``` PROCEDURE DIVISION. *----------------------------------------------------------------* * A-Mainline *----------------------------------------------------------------* A-MAINLINE SECTION. A-010. PERFORM B-INIT. PERFORM C-EXECUTE. PERFORM X-TERM. A-999. STOP RUN. ```
- Call BAQINIT to acquire the connection.
In Section B-INIT, a call is made to BAQINIT to acquire the connection to an IBM z/OS Connect server. From CICS, a predefined URIMAP called BAQHZCON, is used to locate the server. From other execution environments, the language environment variables BAQHOST and BAQPORT are used.
Every verb of the IBM z/OS Connect Host API takes the first parameter as a reference to the BAQ-ZCONNECT-AREA. This data structure is used to communicate the effectiveness of the call and sets a completion code that indicates Success, Warning, Error, Severe or Critical. For unsuccessful completion codes, the reason code and message contain more detailed information to identify whether the problem occurred in the Host API call or in the IBM z/OS Connect server.For example,
``` B-INIT SECTION. B-010. * Initialise the Host API CALL BAQ-INIT-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA. * Check for bad initialization IF NOT BAQ-SUCCESS THEN MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 STRING WS-PROGRAM '--INIT failed' '-CC-' WS-CC9 '-RC-' WS-RC9 DELIMITED BY '>' INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG DISPLAY BAQ-ZCON-RETURN-MESSAGE END-IF. B-999. EXIT. ```A list of parameters can be supplied in the BAQ-ZCONNECT-AREA that is passed to the Host API, which enables capability such as dynamic routing to IBM z/OS Connect servers from CICS. For more information, see Enabling trace in the Host API for z/OS applications.
- Prepare the request. When the connection is established to an IBM z/OS Connect server, you then prepare the request data for the API operation. The address of the request data structure is set in BAQ-REQUEST-AREA. The default name of the generated structure is in the form BAQBASE-APInnQ01 and is copied from the APInnQ01 copybook. The length of this generated data structure must also be set.
Any API data that the called API operation requires is also set. In this example, the author's name.For example,
``` C-EXECUTE SECTION. C-010. * Prepare the request for sending SET BAQ-REQ-BASE-ADDRESS TO ADDRESS OF BAQBASE-RBK02Q01. MOVE LENGTH OF BAQBASE-RBK02Q01 TO BAQ-REQ-BASE-LENGTH. * Find all the Redbooks for a specific author MOVE 1 TO Xauthor-existence OF BAQBASE-RBK02Q01. MOVE "Lydia Parziale" TO Xauthor2 OF BAQBASE-RBK02Q01. MOVE 14 TO Xauthor2-length OF BAQBASE-RBK02Q01. ```Note:
- If your API operation request contains an array, then this must be in-lined by specifying
inlineMaxOccursLimitin the options.yaml file of the Gradle build and ensuring that the API document specifies a
maxItemsvalue that is less than the
- The BAQ-REQUEST-AREA can also contain a list of parameters that are used by an IBM z/OS Connect server to modify the call to the API operation, such as JWT, or OAuth security details.
- If your API operation request contains an array, then this must be in-lined by specifying
Call the API operation.
The COBOL program uses the BAQEXEC verb to call the API operation. This verb takes references to the BAQ-ZCONNECT-AREA, BAQ-API-INFO-APInnI01, BAQ-REQUEST-AREA, and BAQ-RESPONSE-AREA data structures. BAQ-ZCONNECT-AREA is used to communicate the status of the call. BAQ-API-INFO-APInnI01 contains static data that is generated by the Gradle build and contains the metadata for the API operation. BAQ-REQUEST-AREA locates the API operation request data and BAQ-RESPONSE-AREA contains the status of the call from IBM z/OS Connect to the API endpoint and a reference to any returned data.
The BAQEXEC verb contacts the IBM z/OS Connect server and passes any API operation request data in binary (COBOL language structure) form where IBM z/OS Connect transforms the binary data to a JSON payload for the request, or Path or Query parameters that match the OpenAPI description of the operation. IBM z/OS Connect then locates the API endpoint by using the
<zosconnect_endpointConnection>configuration element in server.xml and makes the request. Any JSON response is then transformed back to the binary matching the generated COBOL response language structure for the returned HTTP Status Code.
If the call fails for any reason, the BAQ-ZCONNECT-AREA data structure contains details of the problem.For example,
``` C-020. * Call the API CALL BAQ-EXEC-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA BY REFERENCE BAQ-API-INFO-RBK02I01 BY REFERENCE BAQ-REQUEST-AREA BY REFERENCE BAQ-RESPONSE-AREA. IF NOT BAQ-SUCCESS THEN MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 EVALUATE TRUE WHEN BAQ-WARNING MOVE "API RETURN WARNING" TO WS-FAIL-TYPE WHEN BAQ-ERROR MOVE "API RETURN ERROR " TO WS-FAIL-TYPE WHEN BAQ-SEVERE MOVE "API RETURN SEVERE " TO WS-FAIL-TYPE END-EVALUATE MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 STRING WS-PROGRAM '--EXEC failed' WS-FAIL-TYPE '-CC-' WS-CC9 '-RC-' WS-RC9 DELIMITED BY '>' INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG DISPLAY BAQ-ZCON-RETURN-MESSAGE END-IF. ```
- Retrieve the values from the response.
When the call to the API operation succeeds, any returned response can be used. A successful call from the IBM z/OS Connect Host API perspective is any API operation HTTP status code that is described in the OpenAPI definition for the operation.For example, a 404 (NOTFOUND), if described in the OpenAPI definition for the API operation, is seen as a successful call to the API endpoint with the response data transformed for the COBOL application. Further evaluation of
BAQ-RESPONSE-AREAis required to find out the success of the API endpoint call.
If the API operation response contains an HTTP status code that is not described in the OpenAPI definition then the
BAQ-RESPONSE-AREAcontains any response that the operation provides in the field
BAQ-RESP-STATUS-MESSAGE, with the HTTP status code given in
An OpenAPI 3.0 operation can describe multiple HTTP response codes that can be returned from the BAQEXEC call. Each one of these responses is transformed from JSON to a binary language structure that was generated by the Gradle build. The OpenAPI 3.0 specification allows defining the responses specifically, such as
404, or by using wild cards such as
default.For each defined response for the API operation in the OpenAPI 3.0 definition, the application interprets the returned data. This data can be different for each defined response, so the application language structures are also different. The Gradle build creates one
01 levellanguage structure per defined response for the operation. Therefore, the Host API must tell the COBOL application where the returned data is located in memory and how to access it. To enable this access, the BAQBASE-APInnP01 response language structure follows the following form with two 03 fields per defined operation response.
- The names of the fields are in the form
XXXis the response code, such as
- If the response is an array type, then the field is
-numand states how many elements are returned within the data area, including 0.
- If the response is an Object type, then the field is
-existenceand contains either 0 or 1 to specify whether an object was returned in the data area.
- IBM z/OS Connect generates the value in the
-dataareafield or the application to use when accessing the data area. The field contains the name of the data area that must be referenced to address the data element described by the generated language structure.
In the Redbook API example, the
getAllRedbooksoperation defines two responses: a
200, which returns an array of books, and a
404when there are no books found. For this operation, the Gradle build generates the following BAQBASE-RBK02P01 structure to describe the two valid responses.
``` 01 BAQBASE-RBK02P01. 03 responseCode200-num PIC S9(9) COMP-5 SYNC. 03 responseCode200-dataarea PIC X(16). 03 responseCode404-existence PIC S9(9) COMP-5 SYNC. 03 responseCode404-dataarea PIC X(16). ```
Further 01 Level language structures are generated to describe the data that is contained within each data area.
RBK02P01-responseCode200, provides the representation of a book, and
RBK02P01-responseCode404, an error message structure.
``` 01 RBK02P01-responseCode200. 03 responseCode200. 06 Xtitle-length PIC S9999 COMP-5 SYNC. 06 Xtitle PIC X(80). 06 authors-num PIC S9(9) COMP-5 SYNC. 06 authors-dataarea PIC X(16). 06 Xstatus-length PIC S9999 COMP-5 SYNC. 06 Xstatus PIC X(9). 06 formNumber PIC X(12). ... ```
The array of authors is also described by the data area concept and further 01 Level data structures are generated to describe each element type returned. The BAQGETN verb is used to retrieve these elements in the same way each element was retrieved for the 200 response code. This technique allows for dynamic length arrays where storage is used for the number of elements with no waste. However, if only a few elements are expected in the API then the Gradle build option
inlineMaxOccurrsLimitcan be set. For example, if
inlineMaxOccurrsLimitis set to 10 and the
maxItemsproperty in the OpenAPI schema for an array type is 10 or less, then the generated language structure contains the array type inline. If
maxItemsis greater than
inlineMaxOccurrsLimit, a data area is used.
``` 01 RBK02P01-responseCode404. 03 responseCode404. 06 Xmessage-length PIC S9999 COMP-5 SYNC. 06 Xmessage PIC X(50). 06 authorsBooks-num PIC S9(9) COMP-5 SYNC. 06 authorsBooks-dataarea PIC X(16). ```
These response language structures in the RBK02P01 copybook are all located in the LINKAGE SECTION of the COBOL program and hence must be addressed by using the storage that is returned by a successful BAQEXEC Host API call.
- The names of the fields are in the form
The Host API returns the address of the
BAQBASE-RBK02P01 language structure in the
BAQ-RESP-BASE-ADDRESS, so the COBOL program sets the address of
BAQBASE-RBK02P01 to that storage. Also, the value of the HTTP status code that is
returned by the API operation is contained in the
- Examine the status code to determine the returned data structure.
In the Redbook API example, if the status code is 200, then an array of
Booksis returned, with an individual book represented by 01 Level
RBK02P01-responseCode200. For more information about processing the good response, see COBOL Paragraph C-040. Otherwise, a 404 response was returned and the API operation returned an error represented by the 01 Level
responseCode404-existenceis greater than 0 and if so, check the
RBK02P01-responseCode404language structure to obtain the returned data area for the API operation status code.
These values are checked by using the BAQGETN (Get Next) verb of the Host API. The name of the data area to retrieve is given with a
USAGE POINTERfield to contain the address for the returned error element and a
COMP-5binary field to contain the length of the element.For example,
``` * The address of a returned Data Area Element 01 WS-ELEMENT USAGE POINTER VALUE NULL. * Length of element for BAQGETN call. 01 WS-ELEMENT-LENGTH PIC 9(9) COMP-5. ```
When the BAQGETN call returns successfully, WS-ELEMENT contains the location of the
RBK02P01-responseCode404language structure. Set the address of this structure to WS-ELEMENT and then the language structure fields can be used to display the error structure returned by the API operation.
``` C-030. * Successful call, address the base structure SET ADDRESS OF BAQBASE-RBK02P01 to BAQ-RESP-BASE-ADDRESS. * The API endpoint has returned and the HTTP Status Code could * be 200 (OK) to indicate a successful return of some Redbooks * or another code that indicates an error has been returned IF BAQ-RESP-STATUS-CODE NOT EQUAL 200 THEN IF responseCode404-existence > 0 THEN MOVE responseCode404-dataarea TO WS-DATA-AREA-NAME MOVE LENGTH OF RBK02P01-responseCode404 TO WS-ELEMENT-LENGTH * The RESTFul API sent an Error message CALL BAQ-GETN-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA WS-DATA-AREA-NAME BY REFERENCE WS-ELEMENT BY REFERENCE WS-ELEMENT-LENGTH IF NOT BAQ-SUCCESS THEN MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 STRING WS-PROGRAM '--GETN failed' '-CC-' WS-CC9 '-RC-' WS-RC9 DELIMITED BY '>' INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG DISPLAY BAQ-ZCON-RETURN-MESSAGE STOP RUN END-IF SET ADDRESS OF RBK02P01-responseCode404 to WS-ELEMENT. MOVE BAQ-RESP-STATUS-CODE TO WS-STATUS-CODE STRING WS-PROGRAM '--EXEC Redbook API returned HTTP Status Code ' WS-STATUS-CODE ' MESSAGE ' Xmessage DELIMITED BY SIZE INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG ELSE STRING WS-PROGRAM '--EXEC RESTful EP return HTTP Status Code ' WS-STATUS-CODE DELIMITED BY SIZE INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG END-IF END-IF. ```
If the API operation status code is
responseCode200-numis greater than 0, then call a BAQGETN verb in a
PERFORM VARYINGloop to call Section
CA-GET-EACH-BOOKfor each element of the array.
``` C-040. IF BAQ-RESP-STATUS-CODE = 200 THEN IF responseCode200-num > 0 THEN MOVE LENGTH OF RBK02P01-responseCode200 TO WS-ELEMENT-LENGTH DISPLAY 'Redbook Store Inventory' PERFORM CA-GET-EACH-BOOK VARYING WS-INDEX FROM 1 BY 1 UNTIL WS-INDEX > responseCode200-num ELSE STRING WS-PROGRAM '--EXEC RESTful EP - No Redbooks returned' DELIMITED BY SIZE INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG END-IF END-IF. ```BAQGETN is passed the name of the data area that references the returned
Redbookelements and every time the verb is called, the next
Redbook(represented by language structure
RBK02P01-responseCode200) is returned with the address that the language structure must be addressed with in field WS-ELEMENT.Note: Optional fields as described in the OpenAPI definition for the API operation are generated with a sibling field of the same name but suffixed with
-existence. If the value of this sibling field is 0, then the field does not exist.
``` *----------------------------------------------------------------* * CA-GET-EACH-BOOK * * Gets each Redbook returned by the API endpoint by using * BAQGETN (Get Next) and displays the book details. *----------------------------------------------------------------* CA-GET-EACH-BOOK SECTION. CA-010. CALL BAQ-GETN-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA responseCode200-dataarea BY REFERENCE WS-ELEMENT BY REFERENCE WS-ELEMENT-LENGTH IF NOT BAQ-SUCCESS THEN MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 STRING WS-PROGRAM '--GETN failed' '-CC-' WS-CC9 '-RC-' WS-RC9 DELIMITED BY '>' INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG DISPLAY BAQ-ZCON-RETURN-MESSAGE STOP RUN END-IF. SET ADDRESS OF RBK02P01-responseCode200 to WS-ELEMENT. DISPLAY OPERATION ' Redbook number ' WS-INDEX. STRING OPERATION ' Title ' Xtitle OF RBK02P01-responseCode200 (1:Xtitle-length OF RBK02P01-responseCode200) DELIMITED BY SIZE INTO WS-DISPLAY-MSG. DISPLAY WS-DISPLAY-MSG. CA-999. EXIT. ```
[Optional] Release the storage that was allocated.
When the data that was returned by the API operation is processed, the Host API can release the storage that it allocated by calling BAQFREE. This is an optional step as BAQTERM will also free the allocated storage when the program terminates.For example,
``` C-050. * Free Storage acquired by BAQEXEC CALL BAQ-FREE-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA. ```
- Terminate the connection. After the API operation is called, terminate the connection to the IBM z/OS Connect server by calling the BAQTERM verb of the Host API.Note: In CICS, the termination of the connection releases the connection to the connection pool that was used by the URIMAP, so the next BAQINIT call to acquire a connection is quicker because the cached connection from the pool is used.For example,
``` *----------------------------------------------------------------* * X-TERM * * Terminates the connection to z/OS Connect using BAQTERM. *----------------------------------------------------------------* X-TERM SECTION. X-010. * Terminate the connection CALL BAQ-TERM-NAME USING BY REFERENCE BAQ-ZCONNECT-AREA. IF NOT BAQ-SUCCESS THEN MOVE BAQ-ZCON-COMPLETION-CODE TO WS-CC9 MOVE BAQ-ZCON-REASON-CODE TO WS-RC9 STRING WS-PROGRAM '--TERM failed' WS-FAIL-TYPE '-CC-' WS-CC9 '-RC-' WS-RC9 DELIMITED BY '>' INTO WS-DISPLAY-MSG DISPLAY WS-DISPLAY-MSG DISPLAY BAQ-ZCON-RETURN-MESSAGE END-IF. X-999. EXIT. ```
What to do next
- Compile and run your z/OS application program to call the API.
- If the API that you want to call is secured with OAuth 2.0, a JWT, or an API key, you must make other modifications to your z/OS application to ensure that the required parameters are provided in the API request. For more information, see Calling secured APIs.
- When a CICS application is developed to call an API endpoint, the z/OS Connect server that is used to process the request can be chosen at run time within the CICS application. This option allows for splitting of workloads between servers, for example, based on business area. For more information, see Overriding the URIMAP in a CICS application.
- When a z/OS application is developed to call an API endpoint, the z/OS Connect server that is used to process the request can be chosen at run time within the z/OS application. This option allows for splitting of workloads between servers, for example, based on business area.
- When you develop your z/OS application to call APIs, ensure that dynamic linkage is used, where possible, between the z/OS application code and the Host API callable interface module BAQHAPI supplied by the IBM z/OS Connect. For more information, see Linking by dynamic calls.