Writing an application that calls the Host API

Use the following procedure to call an OpenAPI 3.0 defined API by using the IBM® z/OS® Connect 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.

Procedure

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 Understanding the project structure and prerequisites.

  1. In the Working Storage section of your program, add COPY instructions for the following copybooks.
    • 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.
    For example,
    ```
           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.
     ```
  2. 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.
    ```
           LINKAGE SECTION.
     
          * Response structure for Operation getAllRedbooks
           COPY RBK02P01.
    ```
    The response data structure is located in the Linkage Section because the IBM z/OS Connect Host API manages the storage for the response.
  3. 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.

    Depending on your z/OS application's execution environment, you can loop through all sections for every request or perform a single initialization, then loop across the normal processing, and finally terminate.

    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.
    ```
  4. 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.
  5. 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 inlineMaxOccursLimit in the options.yaml file of the Gradle build and ensuring that the API document specifies a maxItems value that is less than the inlineMaxOccursLimit.
    • 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.
  6. 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.
    ```
  7. 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-AREA is 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-AREA contains any response that the operation provides in the field BAQ-RESP-STATUS-MESSAGE, with the HTTP status code given in BAQ-RESP-STATUS-CODE.

    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 200 or 404, or by using wild cards such as 2XX or 4XX, or 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 level language 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 responseCodeXXX-num, or -existence, and responseCodeXXX-dataarea.
    • XXX is the response code, such as 200, 4XX, or Def (default).
    • If the response is an array type, then the field is -num and states how many elements are returned within the data area, including 0.
    • If the response is an Object type, then the field is -existence and 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 -dataarea field 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 getAllRedbooks operation defines two responses: a 200, which returns an array of books, and a 404 when 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 inlineMaxOccurrsLimit can be set. For example, if inlineMaxOccurrsLimit is set to 10 and the maxItems property in the OpenAPI schema for an array type is 10 or less, then the generated language structure contains the array type inline. If maxItems is 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 Host API returns the address of the BAQBASE-RBK02P01 language structure in the BAQ-RESPONSE-AREA field 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 BAQ-RESPONSE-AREA field BAQ-RESP-STATUS-CODE.

  1. 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 Books is 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 RBK02P01-responseCode404 structure. Check responseCode404-existence is greater than 0 and if so, check the RBK02P01-responseCode404 language 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 POINTER field to contain the address for the returned error element and a COMP-5 binary 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-responseCode404 language 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 200 and the BAQBASE-RBK02P01 field responseCode200-num is greater than 0, then call a BAQGETN verb in a PERFORM VARYING loop to call Section CA-GET-EACH-BOOK for 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 Redbook elements 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.
    ```
  2. [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.
    ```
  3. 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.
    ```

Results

The COBOL application program uses the Host API to call the specified operation of the API endpoint.

What to do next

  • Compile and run your z/OS application program to call the API. For more information, see Testing z/OS applications for API calls.
  • 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.