1

I am getting the following errors when I am doing the mass update on the Case Object in Salesforce.

casesynctrigger: system.limitexception: too many future calls: 51

The reason for this error I saw is the Apex class and Trigger which I created for syncing the data between Salesforce and Website. Below are the codes of the Apex class and Trigger.

Apex Class

public class GGUWSCall
{
    private static gguEduIntegration.SFDCHandlerPort login(){
        gguEduIntegration.SFDCHandlerPort port = new gguEduIntegration.SFDCHandlerPort();

        port.inputHttpHeaders_x = new Map<String, String>();

        Blob headerValue = Blob.valueOf(GGUSettings.USERNAME + ':' + GGUSettings.PASSWORD );

        String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);

        port.inputHttpHeaders_x.put('Authorization', authorizationHeader);

        port.inputHttpHeaders_x.put('Content-Type', 'text/xml; charset=utf-8');

        return port;
    }

    @Future(callout=true) 
    public static void syncCase(String caseId, String status, String resolution
        , String resolutionMethod, String closedDate, String commentsToSubmitter)
    {                 
        gguEduIntegration.SFDCHandlerPort port = login();
        port.updateCase(caseId, status, resolution, resolutionMethod, closedDate, commentsToSubmitter);
    }
}

Apex Trigger

trigger CaseSyncTrigger on Case (after update) {
    for (Case caseNew : Trigger.new) {
        GGUWSCall.syncCase(caseNew.CaseID__c, caseNew.Status, caseNew.Resolution__c, caseNew.ResolutionMethod__c
        , caseNew.ClosedDate != null ? caseNew.ClosedDate.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\'') : ''
        , caseNew.Comments_to_Submitter__c);
        //System.debug(Logginglevel.INFO, 'caseId: '+caseNew.CaseID__c+' status: '+caseNew.Status + ' resolution: '+caseNew.Resolution__c+ ' resolutionMethod: '+ 
        //caseNew.ResolutionMethod__c + ' closeDate: '+(caseNew.ClosedDate!=null?caseNew.ClosedDate.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\''):''));
    }
}

Can somebody please help how I can avoid getting the Error.

casesynctrigger: system.limitexception: too many future calls: 51

Thanks

Kamaldeep

  • 3
    Executing an asynchronous batchable with a batch size of 50 is one way to go. – Keith C Sep 6 '18 at 17:43
4

There is Salesforce limitation that you can only do 50 future calls in 1 synchronous transaction. This is a hard limit.

As I can see you are doing 1 Callout in 1 future method. You can do upto 100 callout in 1 future method. Thus we can bulkify it by making multiple callouts in one future call. For sake of limits, lets make 50 max callouts in a transaction. Trigger context max we can have 200 records lets split it in 4 future calls.

trigger CaseSyncTrigger on Case (after update) {
    List<Case> list0 = new List<Case>();
    List<Case> list1 = new List<Case>();
    List<Case> list2 = new List<Case>();
    List<Case> list3 = new List<Case>();
    for(Integer i=0;i<Trigger.new.size();i++){

        Switch on Math.mod(i,4){
            when 0{
                    list0.add(Trigger.new[i]);
            }
            when 1{
                list1.add(Trigger.new[i]);
            }
            when 2{
                list2.add(Trigger.new[i]);
            }
            when 3{
                list3.add(Trigger.new[i]);
            }
        }


    }
    if(!list0.isEmpty()){
      GGUWSCall.bulifiedCalloutMethod(JSON.serialize(list0));
    }
    if(!list1.isEmpty()){
       GGUWSCall.bulifiedCalloutMethod(JSON.serialize(list1));
    }
    if(!list2.isEmpty()){
       GGUWSCall.bulifiedCalloutMethod(JSON.serialize(list2));
    }
    if(!list3.isEmpty()){
       GGUWSCall.bulifiedCalloutMethod(JSON.serialize(list3));
    }
}

Your service class will be

public class GGUWSCall
{
    private static gguEduIntegration.SFDCHandlerPort login(){
        gguEduIntegration.SFDCHandlerPort port = new gguEduIntegration.SFDCHandlerPort();

        port.inputHttpHeaders_x = new Map<String, String>();

        Blob headerValue = Blob.valueOf(GGUSettings.USERNAME + ':' + GGUSettings.PASSWORD );

        String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);

        port.inputHttpHeaders_x.put('Authorization', authorizationHeader);

        port.inputHttpHeaders_x.put('Content-Type', 'text/xml; charset=utf-8');

        return port;
    }


    public static void syncCase(String caseId, String status, String resolution
        , String resolutionMethod, String closedDate, String commentsToSubmitter)
    {                 
        gguEduIntegration.SFDCHandlerPort port = login();
        port.updateCase(caseId, status, resolution, resolutionMethod, closedDate, commentsToSubmitter);
    }

    @Future(callout=true) 
    public static void bulifiedCalloutMethod(String caseListString){
        List<Case> caseList =(List<Case>) JSON.deserialize(caseListString,Case.Class);
        for(Case caseNew: caseList){
        GGUWSCall.syncCase(caseNew.CaseID__c, caseNew.Status, caseNew.Resolution__c, caseNew.ResolutionMethod__c
            , caseNew.ClosedDate != null ? caseNew.ClosedDate.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\'') : ''
            , caseNew.Comments_to_Submitter__c);
        }
    }
}

There are few things I would like to add.

  1. You are not using TriggerHandler thus it will be hard to maintain in future and can run into recursion which you would have no control to stop

  2. Future methods cant be tracked and you cannot call one future method from another future method, Thus it would make sense to move the code in Queueable.

Src: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

  • Never thought that the 200 records is a max but makes sense that it is for governor limits. +1 from me for max of 4 async calls. Or could it be 1 synchronous and then up to 3 aync? – Keith C Sep 6 '18 at 19:15
  • @KeithC 200 is max size for Trigger.new for Sobjects, Can't see how it can be Synchronous as callouts in trigger are not allowed? – Pranay Jaiswal Sep 7 '18 at 8:21
  • Duh. Fair enough. – Keith C Sep 7 '18 at 9:00

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.