Create a processing information for business logical extension

post

/publisher/apiManagement/processingInformation/shoppingcartAdapter/shoppingCart/v4/schemas/oracle/buying/{component_name}

This method is used to create Processing Information file(PI). The Processing Information file is JavaScript file that is associated with a particular business entity - example - ShoppingCartOracle. The PI file will be stored in the Object Storage with POST operation and the processing information file will be used for ShoppingCartOracle POST and PATCH requests for processing the external busieness logic defined inside this file. Every processing information file should have the two functions defined in them, handleSignal and handleTaskSplittingResult. Therefor you can think of each Processing Information file as a javascript file that must implement a sort of interface that defines those two functions. The naming of these functions corresponds to the purpose these functions serve in the underlying framework that allows for the extensibility of business objects.


JavaScript Methods that need to be overriden in Processing Information
Method Name Usage
handleTaskSplittingResult() This is pre-processing method which gets executed before shoppingCart is created. This is callled "pre-processing" logic.
handleSignal() This is post-processing method which gets executed after shoppingCart is created.This is callled the functionality defined here the "post-processing" logic.

Task Signals definations for ShoppingCart that need to be used in Processing Information
Task Signal Name Usage
shoppingcart-pre-process This signal name is used to read the ShoppingCartOracle object from shoppingcart service as pre processing payload before cart is created and business logical extensions applied on the payload and return ShoppingCartOracle object as response.
shoppingcart-post-process This signal name is used to read the ShoppingCartOracle object from shoppingcart service as post processing payload after cart is created and business logical extensions applied on the payload and return ShoppingCartOracle object as response.
audit-info-signal-pre-process This signal name is used to update the audit details inside Processing Information for pre-processing business logic and emit this task signal.
audit-info-signal-post-process This signal name is used to update the audit details inside Processing Information for post-processing business logic and emit this task signal.

Status codes that need to be used in Processing Information
Status code Usage
SUCCESS This status code is used when successful response from spoke system.
WARNING This status code is used when error response from spoke system and still want to process the ShoppingCart and return error to user.
FAILURE This status code is used when successful response from spoke system and don't want to process the ShoppingCart and return error to user.

Example-1:Basic Skeleton of the Processing Information JavaScript Code
  import { MappingContext, SignalDefinition } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/oracle-builtins.mjs";
import { DataSignal, DIRECTION, ActionableDataSignal, SignalMetaMap, SPOKE_ID, ACTION } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/signals.mjs";
export const spokeDiscriminator = () => "oracle";
export const providedSignals = () => [];
export const handleSignal = async (payload, ctx, signalInfo) => {
}
export const handleTaskSplittingResult = async (requestJson, ctx, {apiName, apiVersion, pathId, requestHTTPMethod, sourcePropertyName}) => {
}  
Example-2:Processing Information code sample calling with signals and calling external system

Two signals in this example- callAddressValidation and addressValidateResponseSignal. The callAddressValidation signal is the outbound signal that will tell the framework to make the call to the address validation system. The first argument specifies the signal name as a string, which can be any value you want. It makes sense to give it an appropriate name for what the signal is doing, so in this case we name it "address-validate-request". The second argument is the HTTP method to be used for the request, in this case it is a POST. The third argument should always be DIRECTION.FROM_MODEL. The framework derives the baseURL of the call from the 4th argument, which is pre-registered with the framework. The fifth argument is where you specify the name of the response signal. As mentioned previously, the calls are happening asynchronously, so once a signal is fired, we have to explicitly wait for the framework to come back with a response in the form of another signal (which carries the response data and metadata from the API we are calling).

  import { MappingContext, SignalDefinition } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/oracle-builtins.mjs";
import { DataSignal, DIRECTION, ActionableDataSignal, SignalMetaMap, SPOKE_ID, ACTION } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/signals.mjs";
export const spokeDiscriminator = () => "oracle";
let addressValidateResponseSignal = new DataSignal("address-validate-reply", DIRECTION.FROM_MODEL);
let callAddressValidation = new ActionableDataSignal("address-validate-request", ACTION.POST, DIRECTION.FROM_MODEL, SPOKE_ID.RMS_SPOKE_ID, "address-validate-reply");
export const providedSignals = () => [callAddressValidation];  
Example-3:Processing Information code sample calling with signals and calling external system
To actually fire the signal (and therefor call the desired API), we can do so by following these steps-
1.Create a signal metamap. This will contain necessary meta information about the signal to make the call to the API.
2.Add the API path to the signal metamap.
3.Emit the signal, possibly containing the payload if it is a POST or PATCH to the desired API. The emit signal method takes a map that is expected to have 3 keys-
a.signalName - string value of the outbound signal we have defined
b.signalValue - the payload (if any) which we want to send to the external system. For a POST and PATCH, it cannot be null. For a GET, it must be null.
c.signalMetaMap - signal metamap containing meta information about the call to make, like the API path to add onto the registered base path.
4.Wait for the reply signal if you need to access something about the response, whether it be the response's payload or response's HTTP status code. We wait for the response signal by calling ctx.dependOn, and since it is an asynchronous call that returns a promise, we need to add "await" in front of it to wait for the response. The value we get back is an object that has the fields "payload" and "meta" present, among others. "payload" is the response payload, and "meta" is an object containing information about the network call that took place, like the response time, status code, URL called, etc.
  /* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. */ import {MappingContext, SignalDefinition} from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/oracle-builtins.mjs"; import { DataSignal, DIRECTION, ActionableDataSignal, SignalMetaMap, SPOKE_ID, ACTION } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/signals.mjs";
export const spokeDiscriminator = () => "oracle";
let addressValidateResponseSignal = new DataSignal("address-validate-reply", DIRECTION.FROM_MODEL);
let callAddressValidation = new ActionableDataSignal("address-validate-request", ACTION.POST, DIRECTION.FROM_MODEL, SPOKE_ID.RMS_SPOKE_ID, "address-validate-reply");
export const providedSignals = () => [callAddressValidation];
export const handleSignal = async (payload, ctx, signalInfo) => {
} /** * * @param requestJson {ITObject} the request object acting as input * @param ctx {MappingContext} the mapping context */ export const handleTaskSplittingResult = async (requestJson, ctx) => { console.log("In pre processing logic in PI"); let shoppingCart = ctx.workOnTaskSignalPayload("shoppingcart-pre-process");
const validateAddressMetaMap = ctx.createMeta(); validateAddressMetaMap.apiPath = "/api/shoppingCart/v4/validateBillingAddress";
for (let cartItemIndex in shoppingCart.cartItem) { let cartItem = shoppingCart.cartItem[cartItemIndex]; let addressToValidate = cartItem.shippingAddress;
//call spoke system ctx.emitSignal({ signalName:"address-validate-request", //based on signal name, the EDK knows which system to go to signalValue:addressToValidate, signalMetaMap:validateAddressMetaMap });
//wait for reply from spoke system let validateAddressResponse = await ctx.dependOn("address-validate-reply", undefined, false); let responsePayload = JSON.stringify(validateAddressResponse.payload()); let responseMeta = JSON.stringify(validateAddressResponse.meta()); } }  

Example-4:Helper function for audit logging for pre and post processing.
  export const sendSpokeResponseInfo = async (spokeCallResponseBody, spokeCallResponseMeta, signalName, ctx, successValue) => { console.log("Sending audit info for signal " + signalName);
//we have to emit a signal that is a regular json obj, not a SignalMetaMap obj type let metaObj = JSON.parse(JSON.stringify(spokeCallResponseMeta)); let payloadObjStr = JSON.stringify(spokeCallResponseBody); let auditInfoObj = {}; auditInfoObj['meta'] = metaObj; auditInfoObj['responsePayload'] = payloadObjStr; auditInfoObj['status'] = successValue;
let meta = ctx.createMeta(); ctx.emitSignal({ signalName:signalName, signalValue:auditInfoObj, signalMetaMap:meta, signalScope:"audit" }); }  

Example-5:Complete flow example with Signals and Status and Audit information calls taking Address Vaidation use case with simulator.
  import {MappingContext, SignalDefinition} from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/oracle-builtins.mjs"; import { DataSignal, DIRECTION, ActionableDataSignal, SignalMetaMap, SPOKE_ID, ACTION } from "src/it/resources/com/oracle/cx/sdk/providers/it/lib/signals.mjs";
export const spokeDiscriminator = () => "oracle";
let addressValidateResponseSignal = new DataSignal("address-validate-reply", DIRECTION.FROM_MODEL);
let callAddressValidation = new ActionableDataSignal("address-validate-request", ACTION.POST, DIRECTION.FROM_MODEL, SPOKE_ID.RMS_SPOKE_ID, "address-validate-reply");
export const providedSignals = () => [callAddressValidation];
export const handleSignal = async (payload, ctx, signalInfo) => {
} /** * * @param requestJson {ITObject} the request object acting as input * @param ctx {MappingContext} the mapping context */ export const handleTaskSplittingResult = async (requestJson, ctx) => { try { console.log("In pre processing logic in PI"); let shoppingCart = ctx.workOnTaskSignalPayload("shoppingcart-pre-process"); const validateAddressMetaMap = ctx.createMeta(); validateAddressMetaMap.apiPath = "/api/shoppingCart/v4/validateBillingAddress";
for (let cartItemIndex in shoppingCart.cartItem) { let cartItem = shoppingCart.cartItem[cartItemIndex]; let addressToValidate = cartItem.shippingAddress; //call spoke system ctx.emitSignal({ signalName:"address-validate-request", //based on signal name, the EDK knows which system to go to signalValue:addressToValidate, signalMetaMap:validateAddressMetaMap });
//wait for reply from spoke system let validateAddressResponse = await ctx.dependOn("address-validate-reply", undefined, false); let responsePayload = JSON.stringify(validateAddressResponse.payload()); let responseMeta = JSON.stringify(validateAddressResponse.meta()); if (validateAddressResponse.meta().error != null) { console.log("Error calling the address validation system"); sendSpokeResponseInfo(validateAddressResponse.payload(), validateAddressResponse.meta(), "audit-info-signal-pre-process", ctx, "FAILURE"); } else { console.log("Successfully called the address validation system"); sendSpokeResponseInfo(validateAddressResponse.payload(), validateAddressResponse.meta(), "audit-info-signal-pre-process", ctx, "SUCCESS"); }
}

} catch (e) { console.log("Error encountered in PI."); console.log(e.stack); console.log(e.name); console.log(e.message); } }
export const sendSpokeResponseInfo = async (spokeCallResponseBody, spokeCallResponseMeta, signalName, ctx, successValue) => { console.log("Sending audit info for signal " + signalName);
//we have to emit a signal that is a regular json obj, not a SignalMetaMap obj type let metaObj = JSON.parse(JSON.stringify(spokeCallResponseMeta)); let payloadObjStr = JSON.stringify(spokeCallResponseBody); let auditInfoObj = {}; auditInfoObj['meta'] = metaObj; auditInfoObj['responsePayload'] = payloadObjStr; auditInfoObj['status'] = successValue; let meta = ctx.createMeta(); ctx.emitSignal({ signalName:signalName, signalValue:auditInfoObj, signalMetaMap:meta, signalScope:"audit" }); }
 

Request

Path Parameters
Supported Media Types
Security
  • Type: oauth2
    Description: The DX4C BuyingX Rest APIs are protected with OAuth2.0 Token-based Authentication and Role-based Authorization. The Roles are segregated based on different sets of Rest APIs. This OAuth2 Security scheme represents the below Role. This scheme is added to all the required Rest end-points protected by the below role. <ul> <li><b>Support Specialist</b> : Grants full access to BuyingX Runtime Rest APIs in the context of an Agent</li> </ul>
Back to Top

Response

Supported Media Types

201 Response

Created. After successful creation of cart we will get the response with full structure of cartItems.

400 Response

Bad Request. Refer Error schema for information of the errors returned for different validation scenarios. For example, if an invalid action is provided in the request body, the following error message is populated.

"code" "CXI-BUY-0022", "reason" "Invalid body", "message" "Action specified on the cart items [cartItem[0]] is either empty or not one of the supported types. "

Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source

401 Response

Unauthorized
Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source

403 Response

Forbidden
Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source

405 Response

Method Not allowed
Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source

409 Response

Conflict
Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source

500 Response

Internal Server Error. Refer Error schema for information of the errors returned for different scenarios. For example, if issue is related to processing the request because of server errors, the following error message is populated.

"code" "CXI-BUY-0001",
"reason" "Internal Server Error"

Body ()
Root Schema : Error
Type: object
Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)
Show Source
Back to Top