Multi-Service Data Provider
The vb/MultiServiceDataProvider built-in type is a data provider implementation that combines multiple vb/ServiceDataProvider variables, each providing a unique fetch capability.
Often components that bind to data providers, like oj-combobox-one and oj-select-single (or the -many variants), require or use different 'fetch' capabilities on the data provider implementation.
For example, an oj-select-single component might call fetchFirst() (on the DataProvider implementation) to populate its options, and then call fetchByKeys() to fetch data for selected value, and fetchByOffset() to fetch items from an offset. Often the endpoint configured on a ServiceDataProvider may provide multiple capabilities - for example, most GETAll endpoints for business object REST API services also allow fetching data for specific keys, and from an offset, on the same endpoint. However, on rare occasions authors might require different endpoints to support different fetch capabilities. A MultiServiceDataProvider can be used for this purpose.
Design Time Assumptions
At design time, a service author can identify different endpoints that provide the fetchByKeys and fetchByOffset capabilities, in addition to the current fetch all (fetchFirst capability). When there are different endpoints a page author must pick different endpoints for each (fetch) capability when configuring a variable of a type vb/MultiServiceDataProvider. It is common for the same REST endpoint to support multiple capabilities.
- for fetchByKeys
- For example, the same endpoint can fetch all territories and a set of territories that match a set of territory codes (fetchByKeys):
GET /fndTerritories? and /fndTerritories?q=TerritoryCode in ('US', 'AE')
- the same endpoint can be used to fetch all customers, or to fetch customers by specific keys using the same endpoint but different query parameters:
GET /customers and GET /customers?ids=cus-101,cus-103
.
- For example, the same endpoint can fetch all territories and a set of territories that match a set of territory codes (fetchByKeys):
- for fetchByOffest
- an Oracle Cloud application endpoint can fetch all territories, and territories at a given offset - GET
/fndTerritories
and/fndTerritories?offset=50&size=10
- an Oracle Cloud application endpoint can fetch all territories, and territories at a given offset - GET
Properties
A variable of the built-in type vb/MultiServiceDataProvider can be configured with
the dataProviders
property using the following sub-properties.
dataProviders Sub-property | Type | Example | Description |
---|---|---|---|
fetchFirst | "vb/ServiceDataProvider" |
|
A MultiServiceDataProvider is needed only when more than one fetch capability needs to be configured. |
fetchByKeys | "vb/ServiceDataProvider" |
|
A reference to the vb/ServiceDataProvider variable. |
fetchByOffset | "vb/ServiceDataProvider" |
|
A reference to the vb/ServiceDataProvider variable. |
Behavior
- A variable of type vb/MultiServiceDataProvider must have at least one fetch capability defined. Otherwise an error is flagged.
- When a fetchFirst capability is not defined, a no-op fetchFirst capability is used. The JET DataProvider contract requires a fetchFirst implementation to be provided.
- All fetch capabilities must point to a variable of type vb/ServiceDataProvider.
- A MultiServiceDataProvider cannot reference another MultiServiceDataProvider variable.
Usage
Here are some of the common ways service endpoints might provide their fetch capabilities.
Usage: When a service provides unique endpoints for different fetch capabilities
When a service has unique endpoints for each fetch capability, we will require one variable of type 'vb/ServiceDataProvider
' per fetch API, and a variable of type 'vb/MultiServiceDataProvider
' variable that combines the individual ServiceDataProvider variables together. The list-of-values component will then bind to a variable of type vb/MultiServiceDataProvider
.
Let's consider this third-party REST API that is used to get information about countries.
-
fetchFirst capability: to get a list of all countries and their info, where the alpha3Code is the primary key
-
service/endpoint: rest-service/getAllCountries
-
GET https://restcountries.eu/rest/v2/all
-
- fetchByKeys capability (with multi key lookup): to get a list of countries by their
three-letter alpha code
-
service/endpoint: rest-service/getCountriesByCodes
-
GET https://restcountries.eu/rest/v2/alpha?codes=usa;mex
-
In order for the list-of-values component to use the above endpoints, the design time will need to create three variables:
-
One vb/MultiServiceDataProvider variable that references two ServiceDataProvider variables, one for each fetch capability
-
Two vb/ServiceDataProvider variables
vb/MultiServiceDataProvider Configuration
At design time, a variable using this type will be created that looks like this:
1 {
2 "variables": {
3 "countriesMultiSDP": {
4 "type": "vb/MultiServiceDataProvider",
5 "defaultValue": {
6 "dataProviders": {
7 "fetchFirst": "{{ $page.variables.allCountriesSDP }}
8 "fetchByKeys": "{{ $page.variables.countriesByCodesSDP }}"
9 }
10 }
11 }
12 }
13 }
-
Line 3: countriesMultiSDP is a variable of type vb/MultiServiceDataProvider. This defines two properties: 'fetchFirst' and 'fetchByKeys'.
-
Line 7: The fetchFirst property allows the MultiServiceDataProvider to call fetchFirst() on the referenced ServiceDataProvider variable.
-
Line 8: The fetchByKeys property allows the MultiServiceDataProvider to call fetchByKeys() on the referenced ServiceDataProvider variable.
vb/ServiceDataProvider Variables Configuration
For the above use case, the referenced ServiceDataProvider variables will be configured as follows:
Configuration | Description |
---|---|
|
Line 3: defines the ServiceDataProvider variable with a fetchFirst capability.
Line 6: defines the endpoint to use the getAllCountries operation to fetch all countries. |
|
Line 4: defines the ServiceDataProvider variable that supports a fetchByKeys capability. Line 7: uses the getCountriesByCodes operation to fetch a list of countries by their codes. Line 9: a '
Line 15: the '
|
|
Line 17: function that fixes up the transform options that will be sent to the transform functions. Line 33: set a new 'codes' query parameter, whose value is a ';' separated list of country alpha codes. |
Configuring a JET Combo/Select at Design Time
-
One vb/MultiServiceDataProvider variable
-
Two vb/ServiceDataProvider variables
-
Line 2 points to a variable of type
vb/MultiServiceDataProvider
.
1 <oj-combobox-one id="so11" value="{{ $variables.selectedActivities }}"
2 options="[[ $variables.countriesMultiSDP ]]"
3 options-keys.label='[[ "name" ]]'
4 options-keys.value='[[ "alpha3Code" ]]'
5 </oj-combobox-one>
A distinct vb/ServiceDataProvider variable is needed for each unique service/endpoint. Often authors want to provide different default filterCriterion, sortCriteria or uriParams, or even write different transforms for each capability. Isolating each capability to a unique ServiceDataProvider variable allows for this separation.
Any individual vb/ServiceDataProvider variables might externalize its fetch, or allow an actionChain to assign values to its properties directly via expressions. They can also allow a fireDataProviderEventAction to reference the Service Data Provider variable directly. First class variables are the easiest way to give page authors access.
Usage: When a service provides unique endpoints for different fetch capabilities, but the fetchByKeys endpoint only supports a single-key-based lookup
In this use case, the service supports a fetchFirst capability that fetches all rows, and a fetchByKeys capability that returns a single row by its key. There is no endpoint that can return rows by multiple keys.
To understand this usecase further let's take the example of the sample ifixitfast service - and the incidents endpoints that is used to get information about incidents.
- fetchFirst capability: to get a list of all incidents for the selected technician,
- service/endpoint:
fixitfast-service/getIncidents
GET https://.../ifixitfaster/api/incidents?technician=hcr
- service/endpoint:
- fetchByKeys capability (with single key lookup): to get a single incident it its 'id'
- service/endpoint:
fixitfast-service/getIncident
GET https://.../ifixitfaster/api/incidents/inc-101
- service/endpoint:
In order for the list-of-values component to use the above endpoints, the design time will need to create three variables:
- One vb/MultiServiceDataProvider variable that references two ServiceDataProvider variables, one for each fetch capability
- Two vb/ServiceDataProvider variables
vb/MultiServiceDataProvider Variable Configuration
The configuration for the vb/MultiServiceDataProvider
variable is similar to the previous examples.
1 {
2 "variables": {
3 "countriesMultiSDP": {
4 "type": "vb/MultiServiceDataProvider",
5 "defaultValue": {
6 "dataProviders": {
7 "fetchFirst": "{{ $page.variables.allIncidentsSDP }}"
8 "fetchByKeys": "{{ $page.variables.incidentBySingleKeySDP }}"
9 }
10 }
11 }
12 }
13 }
vb/ServiceDataProvider Variables Configuration
For the previous use case, the referenced ServiceDataProvider variables will be configured as follows.
Configuration | Description |
---|---|
some-page.json
|
|
|
Line 4: defines the ServiceDataProvider variable with the fetchByKeys capability. The ServiceDataProvider variable is configured for an implicit fetch. Line 7: uses the getIncident operation to fetch a single incident by its id. Line 9: maps the '
Line 12: a new '
Notice that a '
|
|
Line 4: defines the ServiceDataProvider variable with a fetchByKeys capability.
Line 9: sets a mergeTransformOptions function.
|
|
mergeTransformOptions function |
|
The external fetch action chain is configured as follows. Line 4: the action chain used by the ServiceDataProvider. Line 23: the RestAction, the chain calls to fetch a single incident by id. Line 28: the 'uriParams' property of the RestAction is set to the page variable "incidentId".
Line 31: the requestTransformFunction.query maps to a query transform function that substitutes the endpoint URL with the final id value. |
|
Query transform function |
Usage: When the same endpoint supports multiple fetch capabilities
Most list-of-value objects fall into this category. For example, to fetch both a list of territories and to fetch a subset of territories by their ids, the same endpoint is used:
-
fetchFirst capability:
-
service/endpoint: fa-crm-service/getTerritories
-
GET /fndTerritories?finder=EnabledFlagFinder;BindEnabledFlag=Y
-
-
fetchByKeys capability:
-
GET /fndTerritories?finder=EnabledFlagFinder;BindEnabledFlag=Y&q=TerritoryCode IN ('AE', 'AD', 'US')
-
In this case, a single ServiceDataProvider variable of type vb/ServiceDataProvider
that multiplexes different fetch capabilities is the recommended approach. The ServiceDataProvider variable can then be used to bind to the list-of-values component.
Note:
It is recommended that service authors ensure that the service is configured to use the default business object REST API transforms.vb/ServiceDataProvider Variables Configuration
The data returned by the service endpoint will look something like this:
{
"items": [
{
"TerritoryCode": "AE",
"AlternateTerritoryCode": "ar-AE",
"TerritoryShortName": "United Arab Emirates",
"CurrencyCode": "AED"
},
...
],
"count": 25,
"hasMore": false,
"limit": 25,
"offset": 0,
}
The ServiceDataProvider variables for the fetchFirst and fetchByKeys capabilities will be configured as follows
sample-page.html | Description |
---|---|
|
A finder query parameter is applied to all queries going against the endpoint. When no capabilities are set, the ServiceDataProvider variable is assumed to support a fetchFirst capability |
Configuring a JET Select-Single in Design Time
-
Line 1: the value is bound to a variable that is an array of selected TerritoryCode keys.
-
Line 2: the data attribute is bound to the ServiceDataProvider variable.
1 <oj-select-single id="so11" value="{{ $variables.selectedTerritories }}"
2 data="[[ $variables.territoriesSDPVar ]]"
3 item-text='[[ "TerritoryShortName" ]]'
4 </oj-select-single>
Usage: When a service provides a fetchByKeys capability, and DataProvider.containsKeys is called
The containsKeys() method can be called by components bound to a ServiceDataProvider variable that supports the 'fetchByKeys' capability. The default implementation of containsKeys() will call fetchByKeys() and return a oj.ContainsKeysResult object, as defined by the JET DataProvider contract. This implementation addresses the most common usecase.