Call REST Action

The action module for this action is "vb/action/builtin/restAction".

The call REST action is used to make a REST call in conjunction with the service definitions.

Internally, this action uses the Rest Helper, which is a public utility. Its parameters are as follows.

Parameter Name Description
endpoint The endpoint ID as defined in the service configuration.
uriParams A key/value pair map that will be used to override path and query parameters as defined in the service endpoint.
body A structured object that will be sent as the body.
requestType The content-type of the request, either 'json', 'form', or 'url'.

Note:

Note that this is deprecated. Instead, use 'contentType' and 'fileContentType'.
headers An object; each property name is a header name and value that will be sent with the request.
contentType An optional string value with an actual MIME type, which will be used for the "content-type" header. When used with "fileContentType", this is also used as the type for the File blob.
responseType If set, the specified type is used to do two things at run-time:
  • Generate a fields parameter for the REST URI to limit the attributes fetched;
  • Automatically map the fetched response to the response type (when used with the built-in vb/BusinessObjectsTransform). This applies to standard action chains.

See the definition for "responseType" in Service Data Provider Properties for details on how the assigned type is used in that context.

filePath An optional path to a file to send with the request. If "contentType" is set, that is used as the type for the File contents. If “contentType” is not set, a lookup of common file extensions will be used.
filePartName Optional, used with filePath to allow override of the default name ("file") for the FormData part.
fileContentType An optional string, used in combination with "contentType", "multipart/form-data", and "filePath".
hookHandler Used primarily by vb/ServiceDataProvider when externalizing data fetches. See Service Data ProviderServiceDataProvider for details.
requestTransformOptions A map of values to pass to the corresponding transform, as the "options" parameter.
requestTransformFunctions A map of named transform functions, called before making the request, where the function is: fn(configuration, options)
responseTransformFunctions A map of named transform functions, called before making the response, where the function is: fn(configuration, options)
responseBodyFormat  A string that allows an override of the standard Rest behavior, which normally looks for a “content-type” header to determine how to read and parse the response. Possible values are "text", "json", "blob", "arrayBuffer", "base64", "base64Url", and "formData".
responseFields This is an "advanced" field, for use specifically with JET Dynamic Forms. The value would typically be a variable that is bound to the <oj-dynamic-form> "rendered-fields" attribute. This is how a calculated layout can tell the Rest Action call which fields to fetch.

Note: the vb/BusinessObjectsTransform transform is necessary to create a query from this value.

Note: When "responseFields" is provided, "responseType" is ignored.

Using multipart/form Data

If you have set "contentType" to "multipart/form-data", the Action will interpret your request "body" object as the form parts. Each property of the body object will be a form part. If "filePath" is also set, it will be added as an additional part using the lookup of common file extension types.

If "filePath" is also set, it will be added as an additional part using the sample simple file extension type association. The name of this part will be "file", or can be specified using "filePartName".

You may optionally override the file type by using "fileContentType" for the file part.

Defining Services

In order to use a REST API, it should be first defined.

In this example, the following endpoint is registered for the 'foo' service:

{
  "openapi": "3.0",
  "info": {
    "version": "1.1",
    "title": "ifixitfast",
    "description": "FIF",
  },
  "host": "exampledomain.com",
  "basePath": "/services/root",
  "schemes": [
    "http"
  ],
  "paths": {
    "/foo/{id}": {
      "get": {
        "summary": "get a specific Foo object",
        "operationId": "getBar",
        "parameters": [
           {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string"
           }
        ],
        "responses": {
          "200": {
            "description": "",
            "schema": {}
          }
        }
      }
    }
  }
}

You can invoke that endpoint with the following, passing in a value for the 'id' path parameter from a page parameter:

"myActionChain": {
  "root": "myAction",
  "actions": {
    "myAction": {
      "module": "vb/action/builtin/restAction",
      "parameters": {
        "endpoint": "foo/getBar",
        "uriParams": { 
          "id": "{{ $page.variables.myId }}"
        }
      }
    }
  }
}

Declaring Services in the Application

Service definitions are referenced in declarations in the application or in flows. The service name and path are defined by a "services" section in an app-flow.json or xxx-flow.json model. Service declarations support two syntaxes: a string (path), or an object with "path" and "headers":

"services": {
  "fooService": "./demo-data-service.json",
  "barService": {
     "path":  "./service-def.json",
     "headers": {
        "Accept": "application/vnd.oracle.openapi3+json"
     }
  }
}

Transforms

The requestTransformOptions, requestTransformFunctions, and responseTransformFunctions can be used to modify the request and response. Some built-in service endpoints have built-in transform functions for 'sort', 'filter', 'paginate', and 'select', so options for these transform functions can be defined using the same name via the requestTransformOptions property. For third party services, the options set are based on the type of transform functions supported.

When using the Rest Action the transform names have no semantic meaning, and all request and response transforms are called.

Request and response transform functions have the following signatures.

Transform Type Parameters Return Value
Request
/**
 * configuration: {
 *  url:
 *   initConfig: {
 *     method: // string with http method
 *     body: // request body, if any
 *     credentials: // string see (fetch) Request
 *     headers: // object, map of strings
 *   }
 * },
 *
 * options: provided by the application
 *
 * context: an empty object, which exists for the
 *   lifetime of one REST call, a set of 
 *   transforms share this.
 **/
 
mytransform(configuration, options, context)

Configuration object; see "Parameters".

Typically, returns the same object passed in, or a modified one.

Response
/**
 * response: { body, headers }
 *
 * context: an empty object, see "Request transforms"
 *
 */
myresponsetransform(response, context);

The return value is application-defined. The value is returned as the 'transformResults' of the REST call result:

/**
 * {
 *  response: The (fetch) Response object. Note that the body has already
 *     been read, so the functions (ex. json()) cannot be called.
 *
 *  body: the result of the json()/text()/etc.
 * 
 *  transformResults: a map of return values from Response Transforms
 * }
 */

Example 1-18 A Simple Transform Function

One request transform function and one response transform function for a third party service or endpoint might look like this example. Here, the transform functions are defined in the page module and are configured on the RestAction directly. More commonly, transform functions are defined in the service definition and do not need to be mapped on the RestAction.

"fetchIncidentList": {
  "module": "vb/action/builtin/restAction",
  "parameters": {
    "endpoint": "ifixitfast-service/getIncidents",
    "requestTransformOptions": {
      "sort": "{{ $page.variables.sortExpression }}",
    },
    "requestTransformFunctions": {
      "sort": "{{ $page.functions.sort }}"
    },
    "responseTransformFunctions": {
      "paginate": "{{ $page.functions.paginateResponse }}"
    }
  },
  "outcomes": {
    "success": "returnSuccessResponse",
    "failure": "returnFailureResponse"
  }
},
The corresponding module functions would be:
PageModule.prototype.sort = function (configuration, options) {
   /// some code here to modify 'configuration'
   return configuration;
}

PageModule.prototype.paginateResponse = function (configuration) {
   /// some code here to modify 'configuration'
   return configuration;
}

Outcomes

The Call REST action has the following outcomes.

Outcome Description Result Payload
success

If the response code is within the 200 range (or 'ok' in fetch API terms).

  • status: number
  • headers: Headers object
  • body: the result of the call (scalar, obejct, array, etc).
{
  status: <responseCode>,
  headers: <responseHeaders>,
  body: <result body>
}
failure

If the response code is outside of the 200 range (an error response).

  • message

    • summary: string
  • error: Error object, or null
  • payload
    • status: number
    • headers: Headers object
    • body: the result of the call (scalar, obejct, array, etc).
{
  message: {
    summary: <rt message>
  },
  error: <Error, or null>,
  payload: {
    status: <responseCode>,
    headers: <responseHeaders>,
    body: <result body>
  }
}