0

I am doing salesforce to salesforce integration between two orgs using REST API. I created REST API classes in two different org that update/insert/delete records. Insert and Delete works fine. But in Update case i am getting recursion means future methods call again for update case.

Org A. on After Update. Trigger on after Update on Case object

global without sharing class CaseTriggerHandler {

    public static Boolean callagain = true;

    public override void afterUpdate(Map<Id, SObject> oldMapGeneric, Map<Id, SObject> newMapGeneric) {
        if (callagain){
            CaseUpdateRST.updateCaseRST(JSON.serialize(newMapGeneric.values());
        }
    }
}

Class to call REST API to update Case in org A

global with sharing class CaseUpdateRST {

    @future(callout = true)
    public static void updateCaseRST(String lstCase) {
        List<Case> lstCasetoUpdate = (List<Case>) JSON.deserialize(lstCase, List<Case>.class);
        String jsonStr;
        SL_CaseUpdateRST acc1 = new SL_CaseUpdateRST();
        String accessToken = acc1.ReturnAccessToken(acc1);
        if (accessToken != null) {
            List<WrapperClass> lstCaseRstUpdate = mappingCasetoRSTUpdate(lstCasetoUpdate);
            jsonStr = JSON.serialize(lstCaseRstUpdate);
            call_RSTRestAPI(jsonStr, accessToken, 'endpoint');
        }
    }
}

REST API class for update record from org B

@RestResource(urlMapping = '/Case/*')
global with sharing class updateCase {
    @HttpPost
    global static String doPost() {
        RestRequest req = RestContext.Request;
        RestResponse res = RestContext.Response;
        string req_body = req.RequestBody.ToString();
        String str_update = req.requestURI.substring(
                                req.requestURI.lastIndexOf('/') + 1);
        if (str_update == 'update') {
            updateCase(req_body);
        return 'Request scessfully';
    }
    }

    //For Update Case
    private static void updateCase(String req_Body) {
        List<Case> lstRSTCase = (List<Case>) JSON.deserialize(req_body, List<Case>.class);
        CaseTriggerHandler.callagain = false;
        update lstUpdate;
    }

}

Org B. on After Update. Trigger on after Update on Case object

global without sharing class CaseTriggerHandler {

    public static Boolean callagain = true;

    public override void afterUpdate(Map<Id, SObject> oldMapGeneric, Map<Id, SObject> newMapGeneric) {
        if (callagain){
            CaseUpdateRST.updateCaseRST(JSON.serialize(newMapGeneric.values());
        }
    }
}

Class to call REST API to update Case in org B

global with sharing class CaseUpdateRST {

    @future(callout = true)
    public static void updateCaseRST(String lstCase) {
        List<Case> lstCasetoUpdate = (List<Case>) JSON.deserialize(lstCase, List<Case>.class);
        String jsonStr;
        SL_CaseUpdateRST acc1 = new SL_CaseUpdateRST();
        String accessToken = acc1.ReturnAccessToken(acc1);
        if (accessToken != null) {
            List<WrapperClass> lstCaseRstUpdate = mappingCasetoRSTUpdate(lstCasetoUpdate);
            jsonStr = JSON.serialize(lstCaseRstUpdate);
            call_RSTRestAPI(jsonStr, accessToken, 'endpoint');
        }
    }
}

REST API class for update record from org A

@RestResource(urlMapping = '/Case/*')
global with sharing class updateCase {
    @HttpPost
    global static String doPost() {
        RestRequest req = RestContext.Request;
        RestResponse res = RestContext.Response;
        string req_body = req.RequestBody.ToString();
        String str_update = req.requestURI.substring(
                                req.requestURI.lastIndexOf('/') + 1);
        if (str_update == 'update') {
            updateCase(req_body);
        return 'Request scessfully';
    }
    }

    //For Update Case
    private static void updateCase(String req_Body) {
        List<Case> lstRSTCase = (List<Case>) JSON.deserialize(req_body, List<Case>.class);
        CaseTriggerHandler.callagain = false;
        update lstUpdate;
    }

}

Problem: future method calling again and again. Please let me know thw best way to handle recursion of trigger for update case.

0

So you are trying to sync cases in 2 Orgs.

The problem is, as you ar firing trigger and in trigger is not checking if fields have changed or not. There is no point in calling future if nothing relevant has changed. And this is the key to break your infinite calling loop.

public override void afterUpdate(Map<Id, Case> oldMapGeneric, Map<Id, Case> newMapGeneric) {

        Map<String, Schema.SObjectField> schemaFieldMap = Schema.SObjectType.case.fields.getMap();
        schemaFieldMap.remove('LastModifiedById');
        schemaFieldMap.remove('LastModifiedDate');
        schemaFieldMap.remove('SystemModstamp');

        List<Case> toSyncCases = new List<Case>();
        for(Case ca: newMapGeneric ){
            for(String fieldApiName : schemaFieldMap){
                if(ca.get(fieldApiName) != oldMapGeneric.get(ca.Id).get(fieldApiName) ){
                    toSyncCases.add(ca);
                }
            }
        }
        CaseUpdateRST.updateCaseRST(JSON.serialize(toSyncCases);

    }

Here as you can see I am skipping 3 fields , LastModifiedById , LastModifiedDate and SystemModstamp , as they are internal fields and contains no relevant data change (for syncing)

This will break the recursion(infinite callback loop)

Flow:

1)Org A , A user updates a case's field. Future will call org B to sync.

2)Org B will update the corresponding case and then it will again fire a future to sync to Org A

3) Org A, will check data and see if relevant fields have changed. Which would be false as Org A was the one who made the first update, and hence it wont call future

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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