0

I'm trying to display the error messages of each record in the email body of the Batchable Apex.

Am I correct on iterating errorMessages into String and call it in execute method then display it in emailbody? Please help!

global class LRN_ResetSabaHoursBatchable implements Database.Batchable<sObject>, Database.Stateful {

public Set<Id> contactRecordFailures = new set<Id>();
public boolean isSuccess = true;
public List<String> errorMessages = new List<String>();

global Database.QueryLocator start(Database.BatchableContext bc) {
    return Database.getQueryLocator(
        //COLLECT THE BATCHES OF RECORDS TO BE PASSED TO EXECUTE
        'SELECT Id, SABA_Hours__c, Non_SABA_Hours__c FROM Contact WHERE Non_SABA_Hours__c != NULL'
    );
}
global void execute(Database.BatchableContext bc, List<Contact> scope){
    List<Contact> contToUpdate = new List<Contact>();        
    for(Contact contact : scope){
        contact.SABA_Hours__c = 0;
        contact.Non_SABA_Hours__c = 0;
        contToUpdate.add(contact);
    }

    List<Database.SaveResult> updateResults = Database.update(contToUpdate, false);
    for (integer i = 0; i<updateResults.size();i++ ){
        if(!updateResults[i].isSuccess()){
            errorMessages.add(updateResults[i].getErrors()[0].getMessage());      
            contactRecordFailures.add(updateResults[i].Id);
            isSuccess = false;
        }
    }

} 
    
  global void finish(Database.BatchableContext bc){
      if(!isSuccess){
          Id job = bc.getJobId();
          AsyncApexJob aaj = [SELECT Id, Status,ExtendedStatus,NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob where Id =:BC.getJobId()];
          Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
          String[] toAddresses = new String[] {aaj.CreatedBy.Email};
          mail.setToAddresses(toAddresses);
          mail.setSubject('Failed to Reset Saba Hours');
          mail.setPlainTextBody(aaj.Id + aaj.CreatedBy.Name + errorMessages);
          Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
      }    
   }
}

1 Answer 1

0

you are almost there, you just need to make a few changes on your finish method:

  global void finish(Database.BatchableContext bc){
      // check if you got any errors during the execution (no need of extra boolean variable, you can get rid of it)
      if(!errorMessages.isEmpty()){
          Id job = bc.getJobId();
          AsyncApexJob aaj = [SELECT Id, Status,ExtendedStatus,NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob where Id =:BC.getJobId()];
          Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
          String[] toAddresses = new String[] {aaj.CreatedBy.Email};
          mail.setToAddresses(toAddresses);
          mail.setSubject('Failed to Reset Saba Hours');
          // get string with all your errors
          String errorsBody = String.join(errorMessages, ',');
          // format the string as needed, and then
          // use String variable instead of the list one
          mail.setPlainTextBody(aaj.Id + aaj.CreatedBy.Name + errorsBody);
          Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
      }    
   }

EDIT: you also need to iterate over all errors on your execute method:

// Iterate through each returned result
for (Database.SaveResult sr : updateResults) {
    if (!sr.isSuccess()) {
        // Operation failed, so get all errors                
        for(Database.Error err : sr.getErrors()) {
            errorMessages.add(err.getStatusCode() + ': ' + err.getMessage());
        }
    }

you can read more about here Hope this helps!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .