1

This is more of best practice question.

Use case : When an account is changed to a particular status, the account record and its contact record is to be integrated into an external system via REST.

I am thinking of issuing two separate callouts (one for account and one for contact) in my Account "after update" trigger.

This is what I plan to do :

a) Send Account JSON from source.

b) Get Success response JSON from the destination system for a).

c) Upon getting success response, update the External Id on Account record in Source.

d) In the account update trigger whenever External Id is populated, package all the Contact records under the Account and send it as Contact JSON.

e) ...and so on.

Am I on the right path ?.

Is there a better approach to do this i.e account & contact sync ?

1

Since Summer 15, you are able to perform batch requests/responses using the REST. Check out this article in the developer guide:

https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_batch.htm#topic-title

Consider using a JSON structure that allows you to process all records in a single batch so that you only have to do one roundtrip.

If you are able to modify your external system services, consider bulkifying the method by processing a batch JSON. Otherwise, you pass a list of Account/Contact Ids and consume the Salesforce REST API so that you only have to do 2 roundtrips.

  • I agree with @dangt85, not only will the approach help in minimizing overall time, but also ensuring that the destination can make whole transaction atomic i.e. it can take appropriate measures (rollback changes, notify, provide accurate error messages) when something fails mid-way. – Anshul Sep 20 '15 at 15:14
0

I think its better to make an apex callout form trigger or aex class.

Here are the 2 approaches would suit your requirement:

  1. Callout from an Apex trigger(Asynchronous) using @future annotation on Account based on the after update event. In this approach you POST the JSON to an external service and get the response to deserialize and map it to the external id field.

Sample Code:

Apex trigger On account:

trigger IntergrationAccSyncUpdate on Account (after update) {

 for (Account acc : Trigger.new) {
   if (acc.status="Required Status") {
       IntergrationAccSyncUpdate .IntegrationAccsync(acc.Id);
       System.debug('acc.Id');
     }
}

HTTP Class:

public static void IntegrationAccsync(id accid) {
//Construct HTTP request and response
    //Http request method,Endpoint and setBody
    HttpRequest req = new HttpRequest();
    req.setHeader('Content-Type','application/json');
    String endpoint = 'https://test.webserviceurl.com';
    req.setMethod('POST');
    req.setEndpoint(endpoint); 
    req.setTimeout(2 * 60 * 1000);
    system.debug('Acc ID' +accid);
    //SOQL to construct JSON string in set body
    Account Ac=[select id,Name,status__c,
                                     (select Id ,name from Contacts) 
                                        from Account where  id=:accid];
    system.debug('without pretty'+JSON.serialize(Ac));
    String JsonString=JSON.serialize(Ac);
    req.setBody(JsonString);
    system.debug(JsonString);
    //Http response method 
    Http http = new Http();
    HTTPResponse res = http.send(req);
    System.debug(res.getBody());
    Map<String, Object> m = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
    system.debug(m);
    if(m.get('status') == 'ok' || m.get('status') == 'error' ){
           map<string,object> data = (map<string,object>)m.get('data');
           system.debug('---data----'+data);
    if(m.get('status') == 'ok'){
            acc.Account_Id__c=String.ValueOf(data.get('account_id'));
           }
       else if(m.get('status') == 'error'){
            acc.Account_Sync__c=String.valueOf(data.get('message'));
           }

    update acc;
      }
  }
  1. The next approach is to have a custom button on Account and train users to click on this button when they are ready to integrate with the external webservice. Also we can write a batch apex that runs on a nightly to push the accounts where the users didn't make a sync based on the status and external Id filters.
0

When interacting with an external system over http you need to assume that at some point the external system will be unreachable or unavailable. This assumption needs to be built into your design. Your solution needs to be able to retry the workflow. I would suggest that you should queue your requests to the external system to persistent storage.

  1. Detect database change in apex trigger
  2. Persist information to into a table object representing queued requests to the external system
  3. Schedule recurring batch job that sends information to external system
  4. Mark records as processed in table object of queued requests after positive response from external system

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.