function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
PseudodarwinistPseudodarwinist 

@ future method errors and governor limits related to future methods

I would like to understand practical examples of @future annotated methods and also the limitations of future methods (governor limits).Can somebody help me by providing practical code examples and scenarios where i will receive errors from their org specific experiences.In what scenarios i will not be able to call @future from @Future(in what circumstances can i require the need to call a future method within a future method or from the batch class).Please help me by poiniting to a right blog or provide certain practical scenarios ?
NagendraNagendra (Salesforce Developers) 
Hi Chetan,

Use Case: I am trying to call @future method from trigger and got CANNOT_INSERT_UPDATE_ACTIVATE_ENTITYError, because of update operation within the @future method.

The basic example of the pattern I'm talking about is this
public class SaferFutureCall{
    // In this method, which you'll note is not given the @future annotation, you'll
    //   place the code that you have in your current, not-as-safe, @future method
    private static void doNormal(List<Id> idList){
        List<Contact> ContactUpdate = [SELECT id  FROM Contact where Id IN :idList];
        String ContactID;

        HttpRequest req = new HttpRequest();

        req.setTimeout(60000); 
        req.setHeader('Accept','*/*');
        req.setHeader('Content-Type','application/json'); // Content Type
        req.setMethod('GET');

        // ...and the rest of your current code
    }

    // This method doesn't look like it does too much, it's all we need to do to
    //   execute the 'doNormal' method above in an @future context.
    @future(callout=true)
    private static void doFuture(List<Id> idList){
        workToDo(idList);
    }

    // This is where the magic happens
    public static void execute(List<Id> idList){
        if(System.isFuture() || System.isBatch()){
            // If we're in an async context that doesn't allow @future callouts,
            //   we can just simply call the non-@future version of the method.
            // This avoids the "can't call @future from @future" error.
            doNormal(idList);
        } else {
            // If we're not in an async context, we can call the @future version
            //   (provided you haven't hit the limit yet)
            if(Limits.getFutureCalls() < Limits.getLimitFutureCalls()){
                doFuture(idList);
            } else {
                // place some code in here to explicitly notify you that your request
                //   to run an @future method was denied.
            }
        }
    }
}
Using this class is pretty straightforward, you'd replace your direct call to the @future method with
SaferFurure.execute(someIdList);

With that out of the way, we can turn attention to removing the @future call from inside a loop.

Given your provided trigger, it appears that you might not want to call your @future method with every record being inserted. I also doubt that you want to be repeatedly calling your @future method with the same data multiple times (which is a very likely possibility with the trigger that you currently have).

Instead, making your trigger bulk-friendly would involve first preparing the data that you want to send to your @future method, and, in a separate section of trigger code, then calling your @futuremethod.

An example based provided trigger for the same:
trigger ContactWebserviceCall on Contact (After insert) {
    // First, initialize a collection to hold data that you'll be gathering
    Set<Id> contactIdsForCallout = new Set<Id>();

    // Loop over your trigger context variable to gather your target data
    for (Contact co : Trigger.new){
        if(co.Rep_ID__c.substring(0,3) == 'CRM'){
            contactIdsForCallout.add(co.Id);
        }
    }

    // And then pass data (once, and only once) to your callout method.
    // In keeping with my example code, and your trigger code, you have a set
    //   but SaferFuture.execute() requires a List.
    // Creating a new list, and passing the set in to the constructor can easily
    //   take care of this for us.
    SaferFurure.execute(new List<Id>(contactIdsForCallout));
}

The above example resolves both callout and governors limit problems.

For more information please check with below links. Hope this helps.

Kindly mark this as solved if the reply was helpful.

Thanks,
Nagendra