Loading
Salesforce now sends email only from verified domains. Read More
Industries Order Management
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          Custom Asynchronous Callouts

          Custom Asynchronous Callouts

          Configure a callout that waits for a response from a third-party application.

          Industries Order Management commonly integrates with third-party systems by using asynchronous messaging where immediate responses from the third-party system aren't expected.  For instance, third-party systems that interact with people or require any form of manual activities can take a long period of time to complete the original request made by Order Management.  For example, an integration scenario may look as follows:

          Custom Asynchronous Callout

          Graphic showing a scenario in which Order Management calls a 3rd party system.

          In the above scenario, the interim updates and final response may arrive hours, days, or even weeks after the initial request was submitted by the order management system.  To configure an asynchronous callout, you can use the default implementation (XOMAsyncSystemInterface) that is provided when configuring the System Interface.

          The System Interface screen with the Implementation and Path fields highlighted.

          Example – Integration Procedure Asynchronous Callout

          In the same way you called an Integration Procedure in synchronous mode from a Callout Task, you can also call an Integration Procedure in an asynchronous mode.  For instance, you may use the Integration Procedure to make a request to an external system but expect one or more responses days or weeks later.  Situations like this require an asynchronous interface and callback technique to update and complete the Orchestration Item.

          Integration Procedure Asynchronous Callout

          A graph showing the flow of an asynchronous callout.

          For the callbacks to work properly, the Callout Task Orchestration Item will send a unique callback URL that the third-party application can use to send any updates.  The third-party system also needs to authenticate with Salesforce to make a successful callback.

          The IntegrationProcedureAsyncSystemInterface.cls class extends the default XOM Asynchronous System Interface class used by Order Management to make an asynchronous callout using an Integration Procedure rather than a direct REST API Call. This class captures the IP response if there is one.  The Orchestration Item is left in an Active state. The default callback handler sets the Orchestration Item to Completed.  If you want different behavior, such as handling interim responses, then create your own callback handler and modify the callback URI sent in the request.

          Import this Apex class into your org:

          global class IntegrationProcedureAsyncSystemInterface extends vlocity_cmt.XOMAsyncSystemInterface {
           
             /**
              * Default Constructor
              */
             global IntegrationProcedureAsyncSystemInterface() {
              
                 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)
              * @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('JOE - 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:
                 // 
                 // {
                 //   "responseUri" : "/services/apexrest/vlocity_cmt/asyncCallback/a2b1U000000kpOzQAI",
                 //   "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);
                 //ipInput.put('responseUri', 'your override value');   // Override the default callback URI if you have written your own callback handler
                 
                 // Call the Integration Procedure
                 System.debug('JOE - Attempting to call Integration Procedure "' + path + '"');
                 System.debug('JOE - 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('JOE - IP Output -> ' + JSON.serialize(ipOutput));
                 
                 // For debugging, store the Request in the Orchestration Item SObject
                 item.vlocity_cmt__Request__c = JSON.serialize(ipInput);
                 item.vlocity_cmt__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) {}
           
            /**
              * This method is called by the Callback service when a callback is received from an external system.
              * 
              * NOTE! The default XOMAsyncResponseRESTService class will NOT call this method.  Instead it will call the super class 
              *       method XOMAsyncSystemInterface.processResponseDeferred(), so do not expect anything you put into this method to 
              *       be executed unless you create your own callback handler which explicitly creates and instance of this class and
              *       calls this method!
              * 
              * @param item      OrchestrationItem that needs to be executed
              * @param url       base URL (XOMAsyncResponseRESTService sets this to null)
              * @param path      path to send the request to (XOMAsyncResponseRESTService sets this to null)
              * @param orderObj  The order Object related to this Orchestration Item
              * @param res       The Response object to process (XOMAsyncResponseRESTService only sets the body, no headers, etc.)
              * 
              */ 
             global virtual override void processResponseDeferred(vlocity_cmt__OrchestrationItem__c item, String url, String path, vlocity_cmt.XOMOrderDomainObject orderObj, System.HttpResponse res) {
           
                 // Customize this as needed if using your own callback handler
                 super.processResponseDeferred(item, url, path, orderObj, res);
             }    
          }

          Example – Custom REST Callback

          In the previous example, you simply relied on the default XOMAsyncResponseRESTService class to handle the callback from a third-party application.  If you are in a situation where you need to change the callback behavior, such as supporting interim updates, you may need to write your own Callback Service and use a slightly different callback URL.

          Consider this example of a custom callback to complete an item and store it, rather than initializing the AsyncSystemInterface implementation to call the 'processResponseDeferred()' method to store the response.

          item.Response__c = <>;
          item.ExecutionLog__c = <>;
          item.TimestampCompleted__c = <>;
          item.LeadTimeCompleted__c = <>;
          item.State__c = 'Completed;
          update item;
          
           
          Loading
          Salesforce Help | Article