You are here:
Custom Synchronous Callouts
Configure a callout task capable of synchronously calling an integration procedure. Synchronous callouts are the easiest to use because they do not require coordination between different components.
You can simply use the included XOMEnhancedSystemInterface implementation to make callouts to various REST endpoints.
To configure a synchronous callout, use a synchronous implementation when configuring the System Interface referred to by the Callout Task Orchestration Item.
For example, rather than making a REST callout directly to an external system, you can create your own implementation to call an Integration Procedure. This might be a useful approach in situations where you need to manipulate the data beyond what can be done with DataRaptors configured on the Callout Task provide, or if you need to gather additional data, possibly even from other external systems, before generating the final request.
The following image is an example implementation you can use to call an Integration Procedure in a synchronous manner.
The code below is for an Apex class with a mechanism to call an Integration procedure rather than sending a request to a REST endpoint. You need to import this Apex class into your org.
/**
* This class exposes extends the Default System Interface class used by Order Management to
* make a synchronous callout to an Integration Procedure (rather than a direct REST API call).
*
* The general flow is as follows:
*
* ----------- ------------------ ------------ -----------------------
* | Orch Item | | System Interface | | this Class | | Integration Procedure |
* ----------- ------------------ ------------ -----------------------
* | | | |
* | execute | | |
* |---------------->| startBatch() | |
* | |------------------>| |
* | | | |
* | | executeItem() | |
* | |------------------>| call IP |
* | | |------------------->|
* | | | |<----------> Do integration stuff
* | | | response |
* | | processResponse() |<-------------------|
* | |<------------------| |
* | | | |
* | | endBatch() | |
* | complete |------------------>| |
* |<----------------| | |
* | | | |
*
*
*/
global class IntegrationProcedureSystemInterface extends vlocity_cmt.DefaultSystemInterface {
/**
* Default Constructor
*/
global IntegrationProcedureSystemInterface() {
super();
}
/**
* This method is a part of the ISystemInterface. It is invoked at the start of the batch
*
* @param url base URL the batch is started for
* @param path path this batch is started for
*/
global override void startBatch(String url, String path) {}
/**
* Executes a Callout OrchestrationItem
*
* @param url base URL to send the request to (in this class it is ignored as we'll be calling an Integration Procedure)
* @param path path to send the request to (in this class it is interpreted as the Integration Procedure API Key)
* @param item OrchestrationItem that needs to be executed
*/
global override void executeItem(String url, String path, vlocity_cmt__OrchestrationItem__c item) {
System.debug(' - Orchestration Item -> ' + JSON.serialize(item.getPopulatedFieldsAsMap()));
// Get the Order SObject - the technique will differ depending on if this orchestration item is related to an Order Item or a Fulfillment Request Line
Id orderId = null;
if (item.vlocity_cmt__OrderItemId__c != null) orderId = item.vlocity_cmt__OrderItemId__r.OrderId;
else {
vlocity_cmt__OrchestrationItem__c orchItem = [SELECT vlocity_cmt__OrchestrationPlanId__r.vlocity_cmt__OrderId__r.Id FROM vlocity_cmt__OrchestrationItem__c WHERE Id = :item.Id];
orderId = orchItem.vlocity_cmt__OrchestrationPlanId__r.vlocity_cmt__OrderId__r.Id;
}
vlocity_cmt.XOMOrderDomainObject orderObj = ((vlocity_cmt.XOMOrderService)vlocity_cmt.XOMObjectFactory.getService(Order.SObjectType)).getObject(orderId, true);
// The Payload sent to the Integration Procedure is generated by an Optional Request DataRaptor configured on the Orchestration Item Definition
// If no Request DataRaptor is provided it will default to something like this:
//
// {
// "order_id" : "8011U000000tpvgQAA",
// "account_id" : "0011U00000RAyv0QAD",
// "order_items" : [ {
// "order_item_id" : "8021U0000029DzJQAU",
// "action" : "Add",
// "specified_by" : {
// "specification_id" : "01t1U000000rIocQAE",
// "specification_name" : "Test Product"
// },
// "described_by" : []
// } ]
// }
//
Map<String, Object> ipInput = (Map<String, Object>)JSON.deserializeUntyped(super.generatePayload(item, orderObj));
Map<String, Object> ipOptions = new Map<String, Object>();
// Add any extra information to the payload that might be useful and otherwise not available via the DataRaptors configured in the Callout
ipInput.put('orchestration_item_id', item.Id);
ipInput.put('orchestration_item_name', item.Name);
// Call the Integration Procedure
System.debug(' - Attempting to call Integration Procedure "' + path + '"');
System.debug(' - IP Input -> ' + JSON.serialize(ipInput));
Map<String, Object> ipOutput = (Map <String, Object>) vlocity_cmt.IntegrationProcedureService.runIntegrationService(path, ipInput, ipOptions);
// process any response
processResponse(item, ipInput, ipOutput);
}
/**
* This method is called from executeItem to handle the response from the Integration Procedure.
* By default it does nothing (but some logging), but it could be customized to do something more.
*
* @param item The Orchestration Item
* @param ipInput The request sent to the Integration Procedure
* @param ipOutput The response from the Integration Procedure
*/
global virtual void processResponse(vlocity_cmt__OrchestrationItem__c item, Map<String, Object> ipInput, Map<String, Object> ipOutput) {
// Do nothing by default
System.debug(' - IP Output -> ' + JSON.serialize(ipOutput));
// For debugging, store the Request in the Orchestration Item SObject
item.Request__c = JSON.serialize(ipInput);
item.Response__c = JSON.serialize(ipOutput);
update item;
}
/**
* This method is called at the end of the batch
*
* @param url base URL for the batch
* @param path path for the batch
*/
global override void endBatch(String url, String path) {}
}


