04 July 2015

Outbound Message Retry Mechanism



Workflow outbound messaging is great. It provide a simple and declarative way of integrating your Salesforce environment to another system via SOAP protocol by allowing administrators to select fields to send to a certain endpoint. So take for example for Account object, I can send the record Id, Account Name and Description easily by creating a workflow outbound message and associate it with a workflow rule. I can also include a user for which the message will be send on behalf and optionally include the session id so that if the endpoint needs to update back a value to the system, it can use it back without having to authenticate.

Below is a sample workflow rule, outbound message configuration and XML SOAP message:

Sample Workflow Rule



Sample Workflow Outbound Message



Sample SOAP Message


<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
     xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <notifications xmlns="http://soap.sforce.com/2005/09/outbound">
   <OrganizationId>ORG_ID</OrganizationId>
   <ActionId>OBM_ID</ActionId>
   <SessionId>ENCRYPTED_SESSION_ID</SessionId>
   <EnterpriseUrl>SOAP_ENTERPRISE_URL_FOR_YOUR_ORG</EnterpriseUrl>
   <PartnerUrl>SOAP_PARTNER_URL_FOR_YOUR_ORG</PartnerUrl>
   <Notification>
    <Id>04l9000001F11SQAAZ</Id>
    <sObject xsi:type="sf:Account" 
       xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
     <sf:Id>0019000000g0uFmAAI</sf:Id>
     <sf:Description>Edge, founded in 1998, is a start-up based in Austin, 
           TX. The company designs and manufactures a device to convert 
           music from one digital format to another. Edge sells its 
           product through retailers and its own website.</sf:Description>
     <sf:Name>Edge Communications</sf:Name>
    </sObject>
   </Notification>
  </notifications>
 </soapenv:Body>
</soapenv:Envelope>

Note: I use requestbin to get the XML payload that Salesforce sends based on the the configuration.

Annoying Limitation 

Unfortunately while its easy to create and configure outbound message, It's also worth mentioning that this great feature has a limit. If it cannot reach the endpoint, it will only retry sending the message within 24 hours in an exponential interval up to 2 hours maximum between retries (see help documentation).

Now many can argue that the endpoint, either an integration tool or an on premise system like .Net or Java should always be up. That's an ideal scenario but may not always be true. I have worked in an ecosystem before for which the integration tool handles all of the integration for the whole company's systems and because they are in a tight budget, cannot increase the server to handle the load during peak hours and sometimes the system goes down for more than 24 hours (true story).  In short, we cannot always rely on the standard retry mechanism.

Solution/Workaround

There are two things we can do to mitigate this limit. Option one is to use the Outbound Messaging Dead Letter Queue feature which was introduce last Summer '08. What this feature does is it provides a list of failed outbound message queue and then allows administrator to request that these messages be retried for another 24 hours, and assign up to five email recipients to receive a notification once every 24 hours if one or more outbound messages are in the failed outbound message queue.

When enabled, a new checkbox named 'Add failures to failed outbound message related list' on the outbound message configuration will be added.



A new 'Failed outbound messages' related list on the Outbound Message monitoring page will be added (Setup -> Monitor -> Outbound Messages).


And a new section named 'Outbound Message notifications' under Setup -> Monitor section.




The limitation of using this is you can only automate resending by using browser action recorder such as Selenium or iMacros as you would need to click each link on the new outbound message related list.

Use Apex Scheduler

Option number two is to use Apex scheduler to execute a logic that will update the records and execute a work rule that then fires the outbound message. However, to do this there would be a couple of changes in SFDC and your middleware.


First create a sync status in the object with three statuses which we will use later. Status values would be Sent, Success and Error. The idea is that when the workflow rule that sends the Outbound Message executes, we want the Sync Status of the record to set to 'Sent'. 



On the middleware, they need to update back the record status with either 'Success' or 'Error' depending if the operation succeed or not on the other system. The idea is the record will be tagged with a success or error status and will be stuck in sent when Salesforce cannot reach the middleware.

Sample Apex Schedule Class


global class ApexRetrySchedule implements Schedulable {
   global void execute(SchedulableContext SC) {
      
      try{
          List<Account> accountList = [SELECT Id FROM Account WHERE 
               Sync_Status__c = 'Sent' LIMIT 200];
          update accountList;
      }catch(Exception e){
      }
   }
}


You will noticed I only used the scheduleable class. The reason for this is because I don't want to use the batchable interface because it will restrict the context of records the job will process. Using the scheduleable class I can query any objects and update then from the execution, keeping in mind the DML rows governor limits.

In addition, while time-based workflow can be used to update the record when the sync status is still in 'Sent', I won't recommend it as there is a limit on a number of it that an organization can be executed on a rolling 24 hours (see blogpost regarding limits dashboard).

You can schedule the batch job via the Scheduler page or via code depending on the time interval you need it.