+ Start a Discussion
shankar anandshankar anand 

Finish method not getting invoked in batch apex

I'm using Database.update method in my batch class. When I run the batch job I intentionally make some error to occur to see how my code handles it. The job completes successfully but the 'finish' method from my batch class is not invoked. Why is this?I'm trying to copy an inactive Account Owner to the Contact Owner field which generates an internal Salesforce Error but the job completes successfully as I'm using Database class method instead of DML statement. I'm unable to see the debug statement of my Finish method in the log. Piece of my code

global void execute(Database.BatchableContext context, List<sObject> scope){
...............................some code
List<Contact> contacts = new List<Contact>();
        contacts.addAll(list_contacts);
        updateResult = Database.update(contacts ,false);
 for (Database.SaveResult ir : updateResult ) {  
        //Operation failed, so get all errors                       
          for(Database.Error err : ir.getErrors()){                                
          System.debug('The following error has occurred -------------'+ err.getStatusCode() + ': ' + err.getMessage());
          System.debug('Task fields that affected this error: ' + err.getFields());
           Error = 'Failed Store --'+ '  ' + ir.getId() + '    ' +err.getStatusCode() ;
           updateErrors.add(Error);             
            }
    }
}

 //Finish Method 
    global void finish(Database.BatchableContext context){
    
    List<String> listOfEmails = new List<String>();
    // Get the AsyncApexJob that represents the Batch job using the Id from the BatchableContext  
       AsyncApexJob a = [Select Id, Status, NumberOfErrors, JobItemsProcessed,TotalJobItems, CreatedBy.Email, ExtendedStatus from AsyncApexJob where Id = :context.getJobId()];  
          
System.debug('********Inside Finish***updateErrors.size()-------'+updateErrors.size());            
                // Email the Batch Job's submitter that the Job is finished.  
                if(updateErrors.size()>0){
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();    
                mail.setSubject('Account Sync batch Status: ' + a.Status);  
                String msg = 'The batch Apex job failed to update and Address for'+'   '+updateErrors.size()+ ' '+ 'Contacts' + '  ' + Error;
                mail.setPlainTextBody(msg);  
                List<Email_List__c> receivers = Email_List__c.getall().values();
                for(Email_List__c e:receivers){
                    String s = e.Email_Id__c;
                    listOfEmails.add(s);           
                }
                mail.setToAddresses(listOfEmails);
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });      
                }
  
    }

 
KaranrajKaranraj
Batch Apex is stateless by default. That means for each execution of your execute method, you receive a fresh copy of your object. All fields of the class are initialized, static and instance. If your batch process needs information that is shared across transactions, one approach is to make the Batch Apex class itself stateful by implementing the Stateful interface. This instructs Force.com to preserve the values of your static and instance variables between transactions.

Check this link for sample references - https://developer.salesforce.com/forums/ForumsMain?id=906F00000008zJ5IAI
shankar anandshankar anand
Sorry but I didn't understand how that stops my debug statement (at the beginning of Finish method) to be printed in the log? BTW I've implemented the Database.Stateful interface too.
Jon GulikerJon Guliker
I am running into a similar issue with my finish method. Did you ever get an answer to this?