I create the batch class for making a callout and updating contact records but while running batch class getting the "Apex CPU time limit exceeded" exception. Please see the details below

i am passing only one rates record to execute method for makeing a callouts. callouts succesfully executed and get the response from external system. once i get the resposne from external system then i am updating Exchange_Rate_Updated__c field with system.now on contact object. SELECT Id FROM Contact WHERE Type__c='simple' query returning 800 reocrds but i can't able to update the 800 records because system throughing "Maximum CPU time: 65086 out of 60000 ******* CLOSE TO LIMIT" exception. Please see the code below

public class CurrencyExchangeRate implements Database.batchable<sObject>,Database.AllowsCallouts

    test_setting__c cc=test_setting__c.getInstance('SetupOwnerId');
    Id ownerId = cc.Value__c;

    String query = 'SELECT Id,AUD_Exchange_Rate__c,Buffer_Rate__c, CAD_Exchange_Rate__c,CHF_Exchange_Rate__c,EUR_Exchange_Rate__c,MXN_Exchange_Rate__c,NZD_Exchange_Rate__c,PLN_Exchange_Rate__c,SGD_Exchange_Rate__c,USD_Exchange_Rate__c,Currency_updated_date_time__c FROM Exchange_Rates__c Where SetupOwnerId=\'' + ownerId + '\'';

    public Database.querylocator start(Database.BatchableContext BC)
        return Database.getQueryLocator(query);

    public void execute(Database.BatchableContext BC, List<Exchange_Rates__c> rates)
        system.debug('RATES ####'+rates);

        String response;

        List<ECS__Product__c> lstupdate = new List<ECS__Product__c>();

        Map<String,test_setting__c> mapcurrency = test_setting__c.getAll();
        String BaseURL =  mapcurrency.get('BaseURL').Value__c;
        String ACCESS_KEY = mapcurrency.get('ACCESS_KEY').Value__c;
        String Currencies = mapcurrency.get('Currencies').Value__c;
        String Endpoint = mapcurrency.get('EndPoint').Value__c;
        String Source = mapcurrency.get('Source').Value__c;
        String OwnerId = mapcurrency.get('SetupOwnerId').Value__c;

        String URL = BaseURL+Endpoint+'?access_key='+ACCESS_KEY+'&currencies='+Currencies+'&source='+Source+'&format=1';
        system.debug('RequestURL ####'+URL);

        Http h=new Http();

        HttpRequest req=new HttpRequest();

        HttpResponse res=new HttpResponse();

          response = res.getBody();
          MockHttpResponseGenerator mr=new MockHttpResponseGenerator();
          res = mr.channelAdvisorResponed(req);
          response = res.getBody();

        system.debug('RESPONSE ####'+response);

        CurrencyDTO cs=parse(response);
        system.debug('CS ####'+cs);

        system.debug('GBPEUR ####'+cs.quotes.GBPEUR);
        system.debug('GBPCHF ####'+cs.quotes.GBPCHF);
        system.debug('GBPUSD ####'+cs.quotes.GBPUSD);
        system.debug('GBPCAD ####'+cs.quotes.GBPCAD);
        system.debug('GBPMXN ####'+cs.quotes.GBPMXN);
        system.debug('GBPAUD ####'+cs.quotes.GBPAUD);
        system.debug('GBPNZD ####'+cs.quotes.GBPNZD);
        system.debug('GBPSGD ####'+cs.quotes.GBPSGD);

        if(cs.success ==true)
          rates[0].EUR_Exchange_Rate__c = cs.quotes.GBPEUR;
          rates[0].CHF_Exchange_Rate__c = cs.quotes.GBPCHF;
          rates[0].USD_Exchange_Rate__c = cs.quotes.GBPUSD;
          rates[0].CAD_Exchange_Rate__c = cs.quotes.GBPCAD;
          rates[0].MXN_Exchange_Rate__c = cs.quotes.GBPMXN;
          rates[0].AUD_Exchange_Rate__c = cs.quotes.GBPAUD;
          rates[0].NZD_Exchange_Rate__c = cs.quotes.GBPNZD;
          rates[0].SGD_Exchange_Rate__c = cs.quotes.GBPSGD;
          rates[0].PLN_Exchange_Rate__c = cs.quotes.GBPPLN;
          rates[0].Currency_updated_date_time__c = system.now();

          update rates[0];

          //Map<Id,ECS__Product__c> lstMap = new Map<Id,ECS__Product__c>([SELECT Id,Name,ECS__Product_Type__c,Ignore_Exchange_Rate__c FROM ECS__Product__c WHERE Ignore_Exchange_Rate__c=False and ECS__Product_Type__c='Simple']);
          //system.debug('LSTMAP ####'+lstMap.size());

         // if(lstMap.size()>0 && !lstMap.isEmpty())
            for(List<ECS__Product__c> eslst:[SELECT Id,Name,ECS__Product_Type__c,Ignore_Exchange_Rate__c FROM ECS__Product__c WHERE Ignore_Exchange_Rate__c=False and ECS__Product_Type__c='Simple' and Name='sssssssss'])
                for(ECS__Product__c es:eslst)
                    es.Exchange_Rate_Updated__c = system.now();

          system.debug('LSTUPDATESIZE ####'+lstupdate.size());
          system.debug('LSTUPDATE ####'+lstupdate);

        if(lstupdate.size()>0 && !lstupdate.isEmpty())
          update lstupdate;

public void finish(Database.BatchableContext BC)


 // Parse the Response ***//
 public static CurrencyDTO parse(String Response)
    return (CurrencyDTO) system.Json.deserialize(Response,CurrencyDTO.class);

 public class CurrencyDTO
    public boolean success {get;set;}
    public String terms {get;set;}  
    public String privacy {get;set;}    
    public Integer timestamp {get;set;} 
    public String source {get;set;}
    public Quote quotes {get;set;}

    public CurrencyDTO(boolean Success,String terms,String privacy,Integer timestamp,String Source,Quote Quotes)
        this.success = Success;
        this.terms = Terms;
        this.privacy = privacy;
        this.timestamp = timestamp;
        this.source = source;
        this.quotes = quotes;

  public class Quote
    public Double GBPEUR {get;set;}
    public Double GBPCHF {get;set;}
    public Double GBPUSD {get;set;}
    public Double GBPCAD {get;set;}
    public Double GBPMXN {get;set;}
    public Double GBPAUD {get;set;}
    public Double GBPNZD {get;set;}
    public Double GBPSGD {get;set;}
    public Double GBPPLN {get;set;}

    public Quote (Double GBPEUR,Double GBPCHF,Double GBPUSD,Double GBPCAD,Double GBPMXN,Double GBPAUD,Double GBPNZD,Double GBPSGD,Double GBPPLN)
        this.GBPEUR = GBPEUR;
        this.GBPCHF = GBPCHF;
        this.GBPUSD = GBPUSD;
        this.GBPCAD = GBPCAD;
        this.GBPMXN = GBPMXN;
        this.GBPAUD = GBPAUD;
        this.GBPNZD = GBPNZD;
        this.GBPSGD = GBPSGD;
        this.GBPPLN = GBPPLN;

w can fix this issue. Could you please help on this.

  • is it the complete code?where are you making callouts and where is the query in start method ? – Anurag A Aug 10 '16 at 15:47
  • Confused -- you are updating Contacts in execute() but the query locator is on Rates__c . Wouldn't you be getting Rates via callout in Constructor and then querying Contacts in start method? All those Contact updates could be executing triggers – cropredy Aug 11 '16 at 1:43
  • 1
    (1) in the code you posted - there is no update on Contacts, instead - something called ECS__Product__c; (2) you posted lots of irrelevant code - delete it from OP using edit; (3) is sandbox a fullcopy sandbox or just a dev sandbox - # of records queried will vary and could affect runtime. Try and mimic PROD in sandbox at least with respect to record volume - you have Limits class that can help you put debug in code to see where cpu time is going (i.e. instrument code) – cropredy Aug 11 '16 at 13:39
  • 1
    You should look up Hierarchy Custom Settings... – Adrian Larson Aug 11 '16 at 14:08
  • 1
    isn't this a duplicate of salesforce.stackexchange.com/questions/136411/… ? – cropredy Aug 12 '16 at 6:35

Your Answer

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

Browse other questions tagged or ask your own question.