Message Image  

Graphically issuing REST requests in IBM Integration Bus

 View Only
Mon July 13, 2020 09:22 AM

In this post I’ll walk though the steps to Graphically issuing REST requests in IBM Integration Bus, using HTTPRequest node.

Note that IBM Integration Bus 10.0.0.6 provides new capabilities for Calling REST APIs by using the RESTRequest node by importing the REST API swagger document. Also see the blog post .

In this post will show how you can create flows using Mapping and HTTPRequest nodes to call the Pet Store REST sample see the swagger.io pet store server.

I will focus on implementing a Graphical Data Map to setup the data used by a HTTP Request node that you can use in your flow logic to invoke REST APIs. For simplicity in this post I will incorporate these two nodes into a flow with HTTPinput and HTTPreply and use a simple comma separated name-value, CSV, message input to pass some properties to trigger the REST API calls.

With the availability of IBM Integration Bus v10 fixpack 4 you are now able to implement REST APIs using Graphical data mapping and have the JSON data model provided directly from the REST API Swagger document. I covered this facility for creating REST APIs in the post Graphical data mapping for REST APIs with JSON schema

The support for using JSON schema defined models in Graphical Data Maps is also helpful when your message flow processing requires to issue a call to an external REST API to complete it’s task, and I will show how we can import a swagger document to access the JSON schema model definitions.

Calling a REST GET operation

I started by creating an Application “ExampleCallToRESTAPI_App” which references a shared library “PetStoreShlib”. In the shared library “PetStoreShlib” I created a new file “petStoreSwagger.json” and saved the pet store swagger document into it.

I then created a new message flow “CallGetPets.msgflow” in the Application “ExampleCallToRESTAPI_App” and added the nodes shown.

Figure 1. Call Get Pets Message flow


The flow is using an HTTP Input and reply so that we can simply deploy and test the logic using the flow exerciser. The input will be a simple comma separated values, CSV, format defined in the DFDL model “PetStoreShlib\RequestAction.xsd”.

The Mapping node “buildGetPetRestCall” will be responsible for reading the input CSV message and building all the required data to issue either a get pet by “status” or get pet by “id” call to the pet store REST API. The Graphical map will use the Local Environment overrides of the HTTP Request node to set all of the call properties dynamically. For these get operations there is no request body data needed to invoke them, so the map is created with the output body as BLOB to reflect this. To create the map I double click the Mapping node and select the DFDL “RequestAction” message type for the input and set the output to the IBM supplied “BLOB” message.


Figure 2. Map Input and Outputs selection


Once the map is created and opened in the Graphical Data Mapping editor, the next action is to customize it by adding the additional folders that are required in the output. As show in the following figure to open the “Add or remove headers and folders” dialog click the “[i]” link in the output Message Assembly and then click the “Header” hyperlink in the info popup. I select the “LocalEnvironment” and “HTTPRequestHeader” to be added to the map output.


Figure 3. Customizing the Map to add output folders

Now I implement the following mappings to populate the required data values to enable the HTTPRequest node it invoke the REST API call. Refer to the properties of the REST API operations to determine the values to set.

  • LocalEnvironment.Destination.HTTP.RequestURL
    Assign the Pet Store REST API URL, “http://petstore.swagger.io”
  • LocalEnvironment.Destination.HTTP.RequestLine.RequestURI
    This will be appended to the “RequestURL” to address the operation. In this case the map is going to call either the “findPetsByStatus” or “getPetById” operation depending on the input CSV data “name” field. As shown in the following figure I used an If / Else transform to allow “RequestURL” to be assigned the concatenation of ‘/v2/pet/’ and the “value” from the input CSV field “value” for calling the “getPetById” operation. In the Else case the “RequestURL” field is simply assigned “/v2/pet/findByStatus” for calling “findPetsByStatus” operation.


Figure 4. Mapping to set the RequestURI

  • LocalEnvironment.Destination.HTTP.RequestLine.Method
    Assign the operation HTTP method as, “GET”
  • LocalEnvironment.Destination.HTTP.QueryString.status
    When the input CSV “name” is set to “status” to indicate that the “findPetsByStatus” operation is to be called, I need to provide the status values as Query parameters. To do this I will map the input CSV “value” data into a field called “status” in the QueryString folder. To achieve this I use use the add user defined function to create the “status” element in the map “QueryString” output folder. As show in the figure I click the “any” element under “QueryString” and use the add user defined element pop up action button to create a new element and change it’s name to “status”. I then map the input “value” fields to this “status” field within an If condition and use the XPath “fn:string-join()” function to build a comma separated list of all input CSV “value” fields
Figure 5. Adding the “status” QueryString

  • HTTPRequestHeader.Accept
    The Pet Store REST API can return JSON or XML format response. Inorder to receive JSON I add the “Accept” content header in the outgoing request and set it to “application/json”. Again the “HTTPRequestHeader” folder provides an “any” element which can be selected to pop up the “add user defined” button to add an element and set it’s name to “Accept”.

The mappings are now complete, as these GET operations do not require any request body data.


Figure 6. Mappings to build the REST API calls

The HTTPRequest node “Web Service URL” is a mandatory property, so even though the mapping will override this value I had to set a dummy value, “http://overridden/by/map”. I also set the “Response Message Parsing”, “Message domain” to “JSON”.

The “buildGetPetRestCall” flow is now complete and can be run using the flow exerciser. The figure below shows the flow calling the “findPetsByStatus” operation.


Figure 7. Running the getPetsByStatus operation call

I have provided a project interchange of this example flow below.

Calling a REST API PUT operation

To look at calling a REST API that will require input data I created an additional message flow “CallUpdatePet.msgflow” which has a similar pattern of nodes.

Figure 8. Message flow to call the updatePet operation


In this flow to build the data for the REST API “updatePet” operation call it is necessary to provide an instance of a “Pet” JSON object in the request body. Hence when I create the map I set the container to be the shared library “PetStoreShlib” so that the map will be collocated with the swagger document for the REST API, since this is a requirement for mapping from a JSON schema model, as noted here. I can then select the “Pet” JSON data type as the map output, and the DFDL “RequestAction” for it’s input.


Figure 9. Select the input and output for update Pet

As detailed above I then customize the map to add the “LocalEnvironment” and “HTTPRequest” additional folders that are required in the output to set the properties to issue the REST request. Again I provide mappings to set these REST API call properties as outlined below:

  • LocalEnvironment.Destination.HTTP.RequestURL
    Assign the Pet Store REST API URL, “http://petstore.swagger.io”
  • LocalEnvironment.Destination.HTTP.RequestLine.RequestURI
    This will be appended to the “RequestURL” to address the operation, so Assign “/v2/pet”
  • LocalEnvironment.Destination.HTTP.RequestLine.Method
    Assign the operation HTTP method as, “PUT”
  • HTTPRequestHeader.Content_type
    Since the flow is sending a request body with the Pet JSON object, I Assigned “application/json”.
  • HTTPRequestHeader.Accept
    Added via user defined function and Assigned “application/json”.

In my example I reuse the DFDL CSV message “RequestAction” to provide the “name” and “value” of the data members in the “Pet” object to be updated. To map from this input and set the new values in the output Request body I used some XPath predicate expressions to select the input name – value for each of the Pet JSON object’s “id”, “name” and “status” fields. These are put in a Custom XPath transform as shown in the following figure:

Figure 10. Mapping values for the Pet object

This completes the mapping. The HTTPRequest node is again configured with a dummy value for the mandatory “Web Service URL” and I set the “Response Message Parsing”, “Message domain” to “JSON”.

The “buildUpdatePetRestCall” flow is now complete and can be run using the flow exerciser. The figure below shows the flow calling the “updatePet” operation.


Figure 11. Calling the updatePet operation from the message flow

I have provided a project interchange of this example flow below.

Transforming a REST API operation response

In the examples above I only focuses on setting up the data to make the REST API call, and simply sent the response from the REST server as the message flow’s reply.

In some cases the message flow might need to transform or process the returned response body. In these cases you can use a Graphical Data Map and by ensuring it is collocated with the REST API swagger document the JSON types from the model definitions will be available to select as the message map input.

When the REST API response body will return an array of JSON objects, this could have been defined in one of two ways. If the JSON array type is defined in the swagger model definitions, then it will be available for selection to the message map. However if the operation schema object defines the response data as type array with it’s item defined as a $ref to an object in the model definitions only the object type is available in the map wizard. Currently in this case it will be necessary to add an array type in the swagger model definitions, since when a swagger document is used by maps in a shared library it will only consume the model “definitions” section.

For example the “findByStatus” operation has it’s “responses” defined with a “schema” declaring an array of the model definition “Pet” object. To map this response I added the following to provide a JSON array of the Pet object.
"Pets": { "type": "array", "items": {"$ref": "#/definitions/Pet"} },


Figure 12.  JSON Pet object and array

I have provided a map “PetStoreShlib/MapPetsToCsv.map” in the project interchange of this example below which shows the use of the Pets JSON array type.

Note when you are using swagger in a REST API project to implement an operation, the map parses the whole swagger definition so there is no need to add array types in this manner.

Summary

In this post I have reviewed the capabilities for Graphically issuing REST requests in IBM Integration Bus version 10 fixpack 4. These facilities provide the ability to rapidly develop message flows that call REST APIs graphically.


#IntegrationBus(IIB)
#IIBV10
#rest_apis
#REST-requests

Attachment(s)
zip file
IIBExampleCallToRESTAPI_PI.zip   13 KB   1 version
Uploaded - Mon July 13, 2020