+ Start a Discussion
Mr.BrooksMr.Brooks 

How can i best code this to avoid getting the apex cpu time limit error

@future (callout = true)
    public static void clsContactOwnerSync(){
        System.debug('WORKING!!!!!!******:');
        Integer iContactBatchSize = 1000;
        Integer iAccountBatchSize = 3000;
       
       System.debug('WORKING!!!!!!*********');
      
       String ActRecTypeID = [SELECT Name, Id, DeveloperName, SobjectType FROM RecordType where SobjectType = 'Account' and Name = 'Activated'].Id;
       //Sandbox Record Type ID = 01230000000DD54AAG
      
       List<Integer> contactCount = new List<Integer>();

       Integer iSize = 0   ;

    
       //List<Account> accountWithContacts = [SELECT OwnerId, Id, owner.isActive, Active__c, Name, account.GMF_ACF__c, (SELECT Id,OwnerId,Name FROM Contacts where end_date__c = null and CreatedDate >= 2008-10-03T00:00:00Z) FROM Account where  recordtypeid ='01230000000DD54AAG' and account.owner.House_Account__C = false and owner.isActive = true and LastModifiedDate >= Yesterday and active__c = 'Y' limit 8000];
          
      
       //List<Contact> contactsToUpdate = new List<Contact>();
    
       //For loop to iterate through all queried Account records     
       //List<Account> accounts = [Select OwnerId, Id, owner.isActive, Active__c, Name FROM Account where  recordtypeid = :ActRecTypeID and account.owner.House_Account__C = false and owner.isActive = true and LastModifiedDate >= Last_Week and active__c = 'Y' limit 1000]; LastModifiedByID = 00560000000wQdoAAE dwetl  00530000000tfuy apI Serv
        //List<Account> accounts = [SELECT OwnerId, Id, owner.isActive, Active__c, Name, account.GMF_ACF__c, (SELECT Id,OwnerId,Name, CloseDate FROM Opportunities WHERE stagename != 'DECLINE,WITHDRW') FROM Account where  recordtypeid ='01230000000DD54AAG' and account.owner.House_Account__C = false and owner.isActive = true and lastmodifiedbyid = '00560000001268M'  and active__c = 'Y' order by LastModifiedDate limit :iAccountBatchSize];//00560000001268M wendy 00560000000wQdo dwetl
        List<Opportunity> dealsToUpdate = new List<Opportunity>();




        for(Account a: [SELECT OwnerId, Id, owner.isActive, Active__c, Name, account.GMF_ACF__c, (SELECT Id,OwnerId,Name, CloseDate FROM Opportunities WHERE stagename != 'DECLINE,WITHDRW') FROM Account where  recordtypeid ='01230000000DD54AAG' and account.owner.House_Account__C = false and owner.isActive = true and lastmodifiedbyid = '00560000001268M'  and active__c = 'Y' limit :iAccountBatchSize]){

           //List<Contact> updCont = [Select ownerID, id from Contact WHERE AccountId = :a.id];
           
             for(Opportunity o: a.opportunities){
                if(o.OwnerID != a.OwnerID){   
                   
                                     
                        //c.OwnerID = a.OwnerID;
                       
                        Opportunity mOpportunity = new Opportunity();
                        mOpportunity.Id = o.Id;
                        mOpportunity.OwnerID = a.OwnerID;
                        //Contact updCont = [Select ownerID from Contact where id = :c.id];
                        //updCont.ownerid = a.ownerid;              
                        System.debug('Opportunity Id['+ o.Id +'], Name['+ o.name +']');          
                       
                                     
                        dealsToUpdate.add(mOpportunity);               
                        contactCount.add(1);
                       
                       
                        iSize = iSize + 1;
                       
                       System.debug('iSize = ' + iSize);
                       System.debug('******CLOSE DATE FORMATE*****' + o.CloseDate);
                       
                    if(iSize == iContactBatchSize){
                        update dealsToUpdate;
                        System.debug('********UPDATE COUNT: ' + iSize);
                        dealsToUpdate = new List<Opportunity>();
                        iSize = 0;             
                    }             
               }
            }
        }
       
        if(iSize < iContactBatchSize){
                        update dealsToUpdate;
                        System.debug('********UPDATE COUNT: ' + iSize);
                        dealsToUpdate = new List<Opportunity>();
                        iSize = 0;             
                    }  


   }
}
Elie.RodrigueElie.Rodrigue
You should consider using a batch job instead of a future call. This way it would split the execution of your task in multiple batch, avoiding the limits you are currently encountering.

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_batch_interface.htm
Elie.RodrigueElie.Rodrigue
I would also strongly suggest not to hardcode the ids in your query. You'll have issue when deploying.
Here is a batch class that would do pretty much what you were doing in that future call : 

global class ClsContactOwnerSyncBatch implements Database.Batchable<sObject>{

global Database.QueryLocator start(Database.BatchableContext BC)
{
  return Database.getQueryLocator('SELECT OwnerId, Id, owner.isActive, Active__c, Name, account.GMF_ACF__c, (SELECT Id,OwnerId,Name, CloseDate FROM Opportunities WHERE stagename != \'DECLINE,WITHDRW\') FROM Account where  recordtypeid =\'01230000000DD54AAG\' and account.owner.House_Account__C = false and owner.isActive = true and lastmodifiedbyid = \'00560000001268M\'  and active__c = \'Y\'');
}
global void execute(Database.BatchableContext BC, List<sObject> scope)
{
  List<Opportunity> dealsToUpdate = new List<Opportunity>();
  for(sObject obj : scope)
  {
   Account a = (Account)obj;
    for(Opportunity o: a.opportunities){
                  if(o.OwnerID != a.OwnerID){  
                      Opportunity mOpportunity = new Opportunity();
                          mOpportunity.Id = o.Id;
                          mOpportunity.OwnerID = a.OwnerID;
                          dealsToUpdate.add(mOpportunity);              
                      }
   }
  }
  if(dealsToUpdate.size()>0)
  {
   update dealsToUpdate;
  }
}

global void finish(Database.BatchableContext BC)
{
}
}


you can start it by calling : 
Database.executeBatch(new ClsContactOwnerSyncBatch(),100);

If you still have issues you could change 100 so something lower. 100 is the maximum size of the scope list in the execute method.
Elie.RodrigueElie.Rodrigue
Also, if I was you, i would work it the other way around : query the opportunities you want to modify. Currently, you will process every account that match your query criteria even there's no opp :

Select Id, OwnerId, Name, CloseDate,Account.OwnerId, Account.Id,Account.Onwer.IsActive,Account.Active__c, Account.Name, Account.GMF_ACF__c from Opportunities where stagename != 'DECLINE,WITHDRW' and Account.recordtypeid = '01230000000DD54AAG' and account.owner.House_Account__c = false and account.owner.isActive and Account.LastModifiedById = '00560000001268M' and Account.Active__c = 'Y'

You cant use SOQL to filter where the opp owner isnt the same as the account owner, but you could add a formula field in the opp that check that and add it to your soql query.

Mr.BrooksMr.Brooks
I tried this:global class DealerDealOwnerSync implements Database.Batchable<sObject>{
    //TESTING FROM A BUTTON
    public DealerDealOwnerSync(ApexPages.StandardController stdController)
    {        
      //clsContactOwnerSync();
     

    }
  
    String wendy = [SELECT Alias, Id FROM User where alias = 'wkrame1'].id;
    String dwetl = [SELECT Alias, Id FROM User where alias = 'DWETL'].id;

    global Database.QueryLocator start(Database.BatchableContext BC)
    {
      return Database.getQueryLocator('Select Id, OwnerId, Name, CloseDate,Account.OwnerId, Account.Id,Account.Onwer.IsActive,Account.Active__c, Account.Name, Account.GMF_ACF__c from Opportunities where stagename != \'DECLINE,WITHDRW\' and Account.recordtypeid = \'01230000000DD54AAG\' and account.owner.House_Account__c = false and account.owner.isActive and Account.LastModifiedDate = Last_Month and Account.LastModifiedById = :wendy and Account.Active__c = \'Y\'');
    }
   
    global void execute(Database.BatchableContext BC, List<sObject> scope){
        List<Opportunity> dealsToUpdate = new List<Opportunity>();
        for(sObject obj : scope){
            Account a = (Account)obj;
            for(Opportunity o: a.opportunities){
                if(o.OwnerID != a.OwnerID){ 
                    Opportunity mOpportunity = new Opportunity();
                    mOpportunity.Id = o.Id;
                    mOpportunity.OwnerID = a.OwnerID;
                    dealsToUpdate.add(mOpportunity);             
                }
            }
         }
         if(dealsToUpdate.size()>0)
         {
             update dealsToUpdate;
         }
    }

    global void finish(Database.BatchableContext BC)
    {
    }
   
    global class DealerDealOwnerSync_schedule implements Schedulable {
        global void execute(SchedulableContext scMain) {
            DealerDealOwnerSync clsBatchItUpSon = new DealerDealOwnerSync();
            ID idBatch = Database.executeBatch(clsBatchItUpSon,100);
        }
    }
}
Mr.BrooksMr.Brooks
When trying to save it I recieve this: Error: Compile Error: Constructor not defined: [DealerDealOwnerSync].<Constructor>() at line 43 column 51,
Also is there no way for me to test it from a button on a vf page?
Elie.RodrigueElie.Rodrigue
You need to have a constructor without a parameter. Add public DealerDealOwnerSync() ;

You can have a button start the batch job (database.executebatch) but its async so you'll have to monitor the status through the apex job monitoring page.
Mr.BrooksMr.Brooks
I am gettin this error: System.NullPointerException: Attempt to de-reference a null object

from this line of code:mOpportunity.Id = o.Id;

global void execute(Database.BatchableContext BC, List<sObject> scope){
        List<Opportunity> dealsToUpdate = new List<Opportunity>();
        for(sObject obj : scope){
            //Account a = (Account)obj;
            Opportunity o;
            Account a;
            //for(Opportunity o: a.opportunities){
                if(opportunity.OwnerID != account.OwnerID){ 
                    Opportunity mOpportunity = new Opportunity();
                    mOpportunity.Id = o.Id;
                    mOpportunity.OwnerID = a.OwnerID;
                    dealsToUpdate.add(mOpportunity);             
                //}
            }
         }

I appreciate your help.
Elie.RodrigueElie.Rodrigue
You are never assigning a value to o. Same with a. 
in fact you are not using what ever is coming from the scope. make sure you cast obj to the proper format then properlign assign a and o.
Mr.BrooksMr.Brooks
I ran it like that because when I ran it how it was originally written i recieve a conversion error on the first for loop: System.TypeException: Invalid conversion from runtime type SOBJECT:Opportunity to SOBJECT: Account

I wrote this:
global class DealerDealOwnerSync implements Database.Batchable<sObject>{
    //TESTING FROM A BUTTON
    public DealerDealOwnerSync(ApexPages.StandardController stdController)
    {       
      //clsContactOwnerSync();
    

    }
     public DealerDealOwnerSync()
   {       


   }
 
    String wendy = [SELECT Alias, Id FROM User where alias = 'wkrame1'].id;
    String dwetl = [SELECT Alias, Id FROM User where alias = 'DWETL'].id;

    global Database.QueryLocator start(Database.BatchableContext BC)
    {
      return Database.getQueryLocator('Select Id, OwnerId, Name, CloseDate,Account.OwnerId, Account.Id,Account.Owner.IsActive,Account.Active__c, Account.Name, Account.GMF_ACF__c from Opportunity where stagename != \'DECLINE,WITHDRW\' and Account.recordtypeid = \'01230000000DD54AAG\' and account.owner.House_Account__c = false and account.owner.isActive = true and Account.LastModifiedDate = Last_Month and Account.LastModifiedById = :wendy and Account.Active__c = \'Y\''); // where stagename != \'DECLINE,WITHDRW\' and Account.recordtypeid = \'01230000000DD54AAG\' and account.owner.House_Account__c = false and account.owner.isActive = true and Account.LastModifiedDate = Last_Month and Account.LastModifiedById = :wendy and Account.Active__c = \'Y\'
    }
  
    global void execute(Database.BatchableContext BC, List<sObject> scope){
        List<Opportunity> dealsToUpdate = new List<Opportunity>();
        for(sObject obj : scope){
            Account a = (Account)obj;
            /*Opportunity o;
            Account a;*/
            for(Opportunity o: a.opportunities){
                if(o.OwnerID != a.OwnerID){
                    Opportunity mOpportunity = new Opportunity();
                    mOpportunity.Id = o.Id;
                    mOpportunity.OwnerID = a.OwnerID;
                    dealsToUpdate.add(mOpportunity);            
                }
            }
         }
         if(dealsToUpdate.size()>0)
         {
             update dealsToUpdate;
         }
    }

    global void finish(Database.BatchableContext BC)
    {
        //ID d = Database.executeBatch(new DealerDealOwnerSync(),100);
    }
  
  
}